07238f51d5697be72ee33f52143270a83dccd700
[dragonfly.git] / contrib / tcpdump-3.9 / print-ip.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 static const char rcsid[] _U_ =
24     "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.149.2.9 2007/09/14 01:30:02 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "addrtoname.h"
38 #include "interface.h"
39 #include "extract.h"                    /* must come after interface.h */
40
41 #include "ip.h"
42 #include "ipproto.h"
43
44 struct tok ip_option_values[] = {
45     { IPOPT_EOL, "EOL" },
46     { IPOPT_NOP, "NOP" },
47     { IPOPT_TS, "timestamp" },
48     { IPOPT_SECURITY, "security" },
49     { IPOPT_RR, "RR" },
50     { IPOPT_SSRR, "SSRR" },
51     { IPOPT_LSRR, "LSRR" },
52     { IPOPT_RA, "RA" },
53     { IPOPT_RFC1393, "traceroute" },
54     { 0, NULL }
55 };
56
57 /*
58  * print the recorded route in an IP RR, LSRR or SSRR option.
59  */
60 static void
61 ip_printroute(register const u_char *cp, u_int length)
62 {
63         register u_int ptr;
64         register u_int len;
65
66         if (length < 3) {
67                 printf(" [bad length %u]", length);
68                 return;
69         }
70         if ((length + 1) & 3)
71                 printf(" [bad length %u]", length);
72         ptr = cp[2] - 1;
73         if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
74                 printf(" [bad ptr %u]", cp[2]);
75
76         for (len = 3; len < length; len += 4) {
77                 printf(" %s", ipaddr_string(&cp[len]));
78                 if (ptr > len)
79                         printf(",");
80         }
81 }
82
83 /*
84  * If source-routing is present and valid, return the final destination.
85  * Otherwise, return IP destination.
86  *
87  * This is used for UDP and TCP pseudo-header in the checksum
88  * calculation.
89  */
90 u_int32_t
91 ip_finddst(const struct ip *ip)
92 {
93         int length;
94         int len;
95         const u_char *cp;
96         u_int32_t retval;
97
98         cp = (const u_char *)(ip + 1);
99         length = (IP_HL(ip) << 2) - sizeof(struct ip);
100
101         for (; length > 0; cp += len, length -= len) {
102                 int tt;
103
104                 TCHECK(*cp);
105                 tt = *cp;
106                 if (tt == IPOPT_EOL)
107                         break;
108                 else if (tt == IPOPT_NOP)
109                         len = 1;
110                 else {
111                         TCHECK(cp[1]);
112                         len = cp[1];
113                         if (len < 2)
114                                 break;
115                 }
116                 TCHECK2(*cp, len);
117                 switch (tt) {
118
119                 case IPOPT_SSRR:
120                 case IPOPT_LSRR:
121                         if (len < 7)
122                                 break;
123                         memcpy(&retval, cp + len - 4, 4);
124                         return retval;
125                 }
126         }
127 trunc:
128         memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t));
129         return retval;
130 }
131
132 static void
133 ip_printts(register const u_char *cp, u_int length)
134 {
135         register u_int ptr;
136         register u_int len;
137         int hoplen;
138         const char *type;
139
140         if (length < 4) {
141                 printf("[bad length %u]", length);
142                 return;
143         }
144         printf(" TS{");
145         hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
146         if ((length - 4) & (hoplen-1))
147                 printf("[bad length %u]", length);
148         ptr = cp[2] - 1;
149         len = 0;
150         if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
151                 printf("[bad ptr %u]", cp[2]);
152         switch (cp[3]&0xF) {
153         case IPOPT_TS_TSONLY:
154                 printf("TSONLY");
155                 break;
156         case IPOPT_TS_TSANDADDR:
157                 printf("TS+ADDR");
158                 break;
159         /*
160          * prespecified should really be 3, but some ones might send 2
161          * instead, and the IPOPT_TS_PRESPEC constant can apparently
162          * have both values, so we have to hard-code it here.
163          */
164
165         case 2:
166                 printf("PRESPEC2.0");
167                 break;
168         case 3:                 /* IPOPT_TS_PRESPEC */
169                 printf("PRESPEC");
170                 break;
171         default:
172                 printf("[bad ts type %d]", cp[3]&0xF);
173                 goto done;
174         }
175
176         type = " ";
177         for (len = 4; len < length; len += hoplen) {
178                 if (ptr == len)
179                         type = " ^ ";
180                 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
181                        hoplen!=8 ? "" : ipaddr_string(&cp[len]));
182                 type = " ";
183         }
184
185 done:
186         printf("%s", ptr == len ? " ^ " : "");
187
188         if (cp[3]>>4)
189                 printf(" [%d hops not recorded]} ", cp[3]>>4);
190         else
191                 printf("}");
192 }
193
194 /*
195  * print IP options.
196  */
197 static void
198 ip_optprint(register const u_char *cp, u_int length)
199 {
200         register u_int option_len;
201         const char *sep = "";
202
203         for (; length > 0; cp += option_len, length -= option_len) {
204                 u_int option_code;
205
206                 printf("%s", sep);
207                 sep = ",";
208
209                 TCHECK(*cp);
210                 option_code = *cp;
211
212                 printf("%s",
213                         tok2str(ip_option_values,"unknown %u",option_code));
214
215                 if (option_code == IPOPT_NOP ||
216                     option_code == IPOPT_EOL)
217                         option_len = 1;
218
219                 else {
220                         TCHECK(cp[1]);
221                         option_len = cp[1];
222                         if (option_len < 2) {
223                                 printf(" [bad length %u]", option_len);
224                                 return;
225                         }
226                 }
227
228                 if (option_len > length) {
229                         printf(" [bad length %u]", option_len);
230                         return;
231                 }
232
233                 TCHECK2(*cp, option_len);
234
235                 switch (option_code) {
236                 case IPOPT_EOL:
237                         return;
238
239                 case IPOPT_TS:
240                         ip_printts(cp, option_len);
241                         break;
242
243                 case IPOPT_RR:       /* fall through */
244                 case IPOPT_SSRR:
245                 case IPOPT_LSRR:
246                         ip_printroute(cp, option_len);
247                         break;
248
249                 case IPOPT_RA:
250                         if (option_len < 4) {
251                                 printf(" [bad length %u]", option_len);
252                                 break;
253                         }
254                         TCHECK(cp[3]);
255                         if (EXTRACT_16BITS(&cp[2]) != 0)
256                             printf(" value %u", EXTRACT_16BITS(&cp[2]));
257                         break;
258
259                 case IPOPT_NOP:       /* nothing to print - fall through */
260                 case IPOPT_SECURITY:
261                 default:
262                         break;
263                 }
264         }
265         return;
266
267 trunc:
268         printf("[|ip]");
269 }
270
271 /*
272  * compute an IP header checksum.
273  * don't modifiy the packet.
274  */
275 u_short
276 in_cksum(const u_short *addr, register u_int len, int csum)
277 {
278         int nleft = len;
279         const u_short *w = addr;
280         u_short answer;
281         int sum = csum;
282
283         /*
284          *  Our algorithm is simple, using a 32 bit accumulator (sum),
285          *  we add sequential 16 bit words to it, and at the end, fold
286          *  back all the carry bits from the top 16 bits into the lower
287          *  16 bits.
288          */
289         while (nleft > 1)  {
290                 sum += *w++;
291                 nleft -= 2;
292         }
293         if (nleft == 1)
294                 sum += htons(*(u_char *)w<<8);
295
296         /*
297          * add back carry outs from top 16 bits to low 16 bits
298          */
299         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
300         sum += (sum >> 16);                     /* add carry */
301         answer = ~sum;                          /* truncate to 16 bits */
302         return (answer);
303 }
304
305 /*
306  * Given the host-byte-order value of the checksum field in a packet
307  * header, and the network-byte-order computed checksum of the data
308  * that the checksum covers (including the checksum itself), compute
309  * what the checksum field *should* have been.
310  */
311 u_int16_t
312 in_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum)
313 {
314         u_int32_t shouldbe;
315
316         /*
317          * The value that should have gone into the checksum field
318          * is the negative of the value gotten by summing up everything
319          * *but* the checksum field.
320          *
321          * We can compute that by subtracting the value of the checksum
322          * field from the sum of all the data in the packet, and then
323          * computing the negative of that value.
324          *
325          * "sum" is the value of the checksum field, and "computed_sum"
326          * is the negative of the sum of all the data in the packets,
327          * so that's -(-computed_sum - sum), or (sum + computed_sum).
328          *
329          * All the arithmetic in question is one's complement, so the
330          * addition must include an end-around carry; we do this by
331          * doing the arithmetic in 32 bits (with no sign-extension),
332          * and then adding the upper 16 bits of the sum, which contain
333          * the carry, to the lower 16 bits of the sum, and then do it
334          * again in case *that* sum produced a carry.
335          *
336          * As RFC 1071 notes, the checksum can be computed without
337          * byte-swapping the 16-bit words; summing 16-bit words
338          * on a big-endian machine gives a big-endian checksum, which
339          * can be directly stuffed into the big-endian checksum fields
340          * in protocol headers, and summing words on a little-endian
341          * machine gives a little-endian checksum, which must be
342          * byte-swapped before being stuffed into a big-endian checksum
343          * field.
344          *
345          * "computed_sum" is a network-byte-order value, so we must put
346          * it in host byte order before subtracting it from the
347          * host-byte-order value from the header; the adjusted checksum
348          * will be in host byte order, which is what we'll return.
349          */
350         shouldbe = sum;
351         shouldbe += ntohs(computed_sum);
352         shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
353         shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
354         return shouldbe;
355 }
356
357 #define IP_RES 0x8000
358
359 static struct tok ip_frag_values[] = {
360         { IP_MF,        "+" },
361         { IP_DF,        "DF" },
362         { IP_RES,       "rsvd" }, /* The RFC3514 evil ;-) bit */
363         { 0,            NULL }
364 };
365
366 struct ip_print_demux_state {
367         const struct ip *ip;
368         const u_char *cp;
369         u_int   len, off;
370         u_char  nh;
371         int     advance;
372 };
373
374 static void
375 ip_print_demux(netdissect_options *ndo,
376                struct ip_print_demux_state *ipds)
377 {
378         struct protoent *proto;
379
380 again:
381         switch (ipds->nh) {
382
383         case IPPROTO_AH:
384                 ipds->nh = *ipds->cp;
385                 ipds->advance = ah_print(ipds->cp);
386                 if (ipds->advance <= 0)
387                         break;
388                 ipds->cp += ipds->advance;
389                 ipds->len -= ipds->advance;
390                 goto again;
391
392         case IPPROTO_ESP:
393         {
394                 int enh, padlen;
395                 ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
396                                     (const u_char *)ipds->ip,
397                                     &enh, &padlen);
398                 if (ipds->advance <= 0)
399                         break;
400                 ipds->cp += ipds->advance;
401                 ipds->len -= ipds->advance + padlen;
402                 ipds->nh = enh & 0xff;
403                 goto again;
404         }
405         
406         case IPPROTO_IPCOMP:
407         {
408                 int enh;
409                 ipds->advance = ipcomp_print(ipds->cp, &enh);
410                 if (ipds->advance <= 0)
411                         break;
412                 ipds->cp += ipds->advance;
413                 ipds->len -= ipds->advance;
414                 ipds->nh = enh & 0xff;
415                 goto again;
416         }
417
418         case IPPROTO_SCTP:
419                 sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
420                 break;
421
422         case IPPROTO_DCCP:
423                 dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
424                 break;
425                 
426         case IPPROTO_TCP:
427                 /* pass on the MF bit plus the offset to detect fragments */
428                 tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
429                           ipds->off & (IP_MF|IP_OFFMASK));
430                 break;
431                 
432         case IPPROTO_UDP:
433                 /* pass on the MF bit plus the offset to detect fragments */
434                 udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
435                           ipds->off & (IP_MF|IP_OFFMASK));
436                 break;
437                 
438         case IPPROTO_ICMP:
439                 /* pass on the MF bit plus the offset to detect fragments */
440                 icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
441                            ipds->off & (IP_MF|IP_OFFMASK));
442                 break;
443                 
444         case IPPROTO_PIGP:
445                 /*
446                  * XXX - the current IANA protocol number assignments
447                  * page lists 9 as "any private interior gateway
448                  * (used by Cisco for their IGRP)" and 88 as
449                  * "EIGRP" from Cisco.
450                  *
451                  * Recent BSD <netinet/in.h> headers define
452                  * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
453                  * We define IP_PROTO_PIGP as 9 and
454                  * IP_PROTO_EIGRP as 88; those names better
455                  * match was the current protocol number
456                  * assignments say.
457                  */
458                 igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
459                 break;
460                 
461         case IPPROTO_EIGRP:
462                 eigrp_print(ipds->cp, ipds->len);
463                 break;
464                 
465         case IPPROTO_ND:
466                 ND_PRINT((ndo, " nd %d", ipds->len));
467                 break;
468
469         case IPPROTO_EGP:
470                 egp_print(ipds->cp, ipds->len);
471                 break;
472
473         case IPPROTO_OSPF:
474                 ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
475                 break;
476
477         case IPPROTO_IGMP:
478                 igmp_print(ipds->cp, ipds->len);
479                 break;
480
481         case IPPROTO_IPV4:
482                 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
483                 ip_print(gndo, ipds->cp, ipds->len);
484                 if (! vflag) {
485                         ND_PRINT((ndo, " (ipip-proto-4)"));
486                         return;
487                 }
488                 break;
489                 
490 #ifdef INET6
491         case IPPROTO_IPV6:
492                 /* ip6-in-ip encapsulation */
493                 ip6_print(ipds->cp, ipds->len);
494                 break;
495 #endif /*INET6*/
496
497         case IPPROTO_RSVP:
498                 rsvp_print(ipds->cp, ipds->len);
499                 break;
500
501         case IPPROTO_GRE:
502                 /* do it */
503                 gre_print(ipds->cp, ipds->len);
504                 break;
505
506         case IPPROTO_MOBILE:
507                 mobile_print(ipds->cp, ipds->len);
508                 break;
509
510         case IPPROTO_PIM:
511                 pim_print(ipds->cp,  ipds->len);
512                 break;
513
514         case IPPROTO_VRRP:
515                 vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
516                 break;
517
518         case IPPROTO_PGM:
519                 pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
520                 break;
521
522         default:
523                 if ((proto = getprotobynumber(ipds->nh)) != NULL)
524                         ND_PRINT((ndo, " %s", proto->p_name));
525                 else
526                         ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
527                 ND_PRINT((ndo, " %d", ipds->len));
528                 break;
529         }
530 }
531                
532 void
533 ip_print_inner(netdissect_options *ndo,
534                const u_char *bp,
535                u_int length, u_int nh,
536                const u_char *bp2)
537 {
538         struct ip_print_demux_state  ipd;
539
540         ipd.ip = (const struct ip *)bp2;
541         ipd.cp = bp;
542         ipd.len  = length;
543         ipd.off  = 0;
544         ipd.nh   = nh;
545         ipd.advance = 0;
546
547         ip_print_demux(ndo, &ipd);
548 }
549
550
551 /*
552  * print an IP datagram.
553  */
554 void
555 ip_print(netdissect_options *ndo,
556          const u_char *bp,
557          u_int length)
558 {
559         struct ip_print_demux_state  ipd;
560         struct ip_print_demux_state *ipds=&ipd;
561         const u_char *ipend;
562         u_int hlen;
563         u_int16_t sum, ip_sum;
564         struct protoent *proto;
565
566         ipds->ip = (const struct ip *)bp;
567         if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
568             printf("IP%u ", IP_V(ipds->ip));
569             if (IP_V(ipds->ip) == 6)
570                 printf(", wrong link-layer encapsulation");
571         }
572         else if (!eflag)
573             printf("IP ");
574
575         if ((u_char *)(ipds->ip + 1) > snapend) {
576                 printf("[|ip]");
577                 return;
578         }
579         if (length < sizeof (struct ip)) {
580                 (void)printf("truncated-ip %u", length);
581                 return;
582         }
583         hlen = IP_HL(ipds->ip) * 4;
584         if (hlen < sizeof (struct ip)) {
585                 (void)printf("bad-hlen %u", hlen);
586                 return;
587         }
588
589         ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
590         if (length < ipds->len)
591                 (void)printf("truncated-ip - %u bytes missing! ",
592                         ipds->len - length);
593         if (ipds->len < hlen) {
594 #ifdef GUESS_TSO
595             if (ipds->len) {
596                 (void)printf("bad-len %u", ipds->len);
597                 return;
598             }
599             else {
600                 /* we guess that it is a TSO send */
601                 ipds->len = length;
602             }
603 #else
604             (void)printf("bad-len %u", ipds->len);
605             return;
606 #endif /* GUESS_TSO */
607         }
608
609         /*
610          * Cut off the snapshot length to the end of the IP payload.
611          */
612         ipend = bp + ipds->len;
613         if (ipend < snapend)
614                 snapend = ipend;
615
616         ipds->len -= hlen;
617
618         ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
619
620         if (vflag) {
621             (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos);
622             /* ECN bits */
623             if (ipds->ip->ip_tos & 0x03) {
624                 switch (ipds->ip->ip_tos & 0x03) {
625                 case 1:
626                     (void)printf(",ECT(1)");
627                     break;
628                 case 2:
629                     (void)printf(",ECT(0)");
630                     break;
631                 case 3:
632                     (void)printf(",CE");
633                 }
634             }
635
636             if (ipds->ip->ip_ttl >= 1)
637                 (void)printf(", ttl %u", ipds->ip->ip_ttl);    
638
639             /*
640              * for the firewall guys, print id, offset.
641              * On all but the last stick a "+" in the flags portion.
642              * For unfragmented datagrams, note the don't fragment flag.
643              */
644
645             (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)",
646                          EXTRACT_16BITS(&ipds->ip->ip_id),
647                          (ipds->off & 0x1fff) * 8,
648                          bittok2str(ip_frag_values, "none", ipds->off&0xe000),
649                          tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
650                          ipds->ip->ip_p);
651
652             (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len));
653
654             if ((hlen - sizeof(struct ip)) > 0) {
655                 printf(", options (");
656                 ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
657                 printf(")");
658             }
659
660             if ((u_char *)ipds->ip + hlen <= snapend) {
661                 sum = in_cksum((const u_short *)ipds->ip, hlen, 0);
662                 if (sum != 0) {
663                     ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
664                     (void)printf(", bad cksum %x (->%x)!", ip_sum,
665                              in_cksum_shouldbe(ip_sum, sum));
666                 }
667             }
668
669             printf(") ");
670         }
671
672         /*
673          * If this is fragment zero, hand it to the next higher
674          * level protocol.
675          */
676         if ((ipds->off & 0x1fff) == 0) {
677                 ipds->cp = (const u_char *)ipds->ip + hlen;
678                 ipds->nh = ipds->ip->ip_p;
679
680                 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
681                     ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
682                         (void)printf("%s > %s: ",
683                                      ipaddr_string(&ipds->ip->ip_src),
684                                      ipaddr_string(&ipds->ip->ip_dst));
685                 }
686                 ip_print_demux(ndo, ipds);
687         } else {
688             /* Ultra quiet now means that all this stuff should be suppressed */
689             if (qflag > 1) return;
690
691             /*
692              * if this isn't the first frag, we're missing the
693              * next level protocol header.  print the ip addr
694              * and the protocol.
695              */
696             if (ipds->off & 0x1fff) {
697                 (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src),
698                              ipaddr_string(&ipds->ip->ip_dst));
699                 if ((proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
700                     (void)printf(" %s", proto->p_name);
701                 else
702                     (void)printf(" ip-proto-%d", ipds->ip->ip_p);
703             } 
704         }
705 }
706
707 void
708 ipN_print(register const u_char *bp, register u_int length)
709 {
710         struct ip *ip, hdr;
711
712         ip = (struct ip *)bp;
713         if (length < 4) {
714                 (void)printf("truncated-ip %d", length);
715                 return;
716         }
717         memcpy (&hdr, (char *)ip, 4);
718         switch (IP_V(&hdr)) {
719         case 4:
720                 ip_print (gndo, bp, length);
721                 return;
722 #ifdef INET6
723         case 6:
724                 ip6_print (bp, length);
725                 return;
726 #endif
727         default:
728                 (void)printf("unknown ip %d", IP_V(&hdr));
729                 return;
730         }
731 }
732
733 /*
734  * Local Variables:
735  * c-style: whitesmith
736  * c-basic-offset: 8
737  * End:
738  */
739
740