]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip.c
bpf_dump.c moved to libpcap
[tcpdump] / 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[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.82 2000-05-10 05:11:27 itojun Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/ip_var.h>
39 #include <netinet/udp.h>
40 #include <netinet/udp_var.h>
41 #include <netinet/tcp.h>
42
43 #ifdef HAVE_MALLOC_H
44 #include <malloc.h>
45 #endif
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50
51 #include "addrtoname.h"
52 #include "interface.h"
53 #include "extract.h" /* must come after interface.h */
54
55 /* Compatibility */
56 #ifndef IPPROTO_ND
57 #define IPPROTO_ND 77
58 #endif
59
60 #ifndef IN_CLASSD
61 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
62 #endif
63
64 /* (following from ipmulti/mrouted/prune.h) */
65
66 /*
67 * The packet format for a traceroute request.
68 */
69 struct tr_query {
70 u_int tr_src; /* traceroute source */
71 u_int tr_dst; /* traceroute destination */
72 u_int tr_raddr; /* traceroute response address */
73 u_int tr_rttlqid; /* response ttl and qid */
74 };
75
76 #define TR_GETTTL(x) (int)(((x) >> 24) & 0xff)
77 #define TR_GETQID(x) ((x) & 0x00ffffff)
78
79 /*
80 * Traceroute response format. A traceroute response has a tr_query at the
81 * beginning, followed by one tr_resp for each hop taken.
82 */
83 struct tr_resp {
84 u_int tr_qarr; /* query arrival time */
85 u_int tr_inaddr; /* incoming interface address */
86 u_int tr_outaddr; /* outgoing interface address */
87 u_int tr_rmtaddr; /* parent address in source tree */
88 u_int tr_vifin; /* input packet count on interface */
89 u_int tr_vifout; /* output packet count on interface */
90 u_int tr_pktcnt; /* total incoming packets for src-grp */
91 u_char tr_rproto; /* routing proto deployed on router */
92 u_char tr_fttl; /* ttl required to forward on outvif */
93 u_char tr_smask; /* subnet mask for src addr */
94 u_char tr_rflags; /* forwarding error codes */
95 };
96
97 /* defs within mtrace */
98 #define TR_QUERY 1
99 #define TR_RESP 2
100
101 /* fields for tr_rflags (forwarding error codes) */
102 #define TR_NO_ERR 0
103 #define TR_WRONG_IF 1
104 #define TR_PRUNED 2
105 #define TR_OPRUNED 3
106 #define TR_SCOPED 4
107 #define TR_NO_RTE 5
108 #define TR_NO_FWD 7
109 #define TR_NO_SPACE 0x81
110 #define TR_OLD_ROUTER 0x82
111
112 /* fields for tr_rproto (routing protocol) */
113 #define TR_PROTO_DVMRP 1
114 #define TR_PROTO_MOSPF 2
115 #define TR_PROTO_PIM 3
116 #define TR_PROTO_CBT 4
117
118 static void print_mtrace(register const u_char *bp, register u_int len)
119 {
120 register struct tr_query *tr = (struct tr_query *)(bp + 8);
121
122 printf("mtrace %lu: %s to %s reply-to %s",
123 (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
124 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
125 ipaddr_string(&tr->tr_raddr));
126 if (IN_CLASSD(ntohl(tr->tr_raddr)))
127 printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
128 }
129
130 static void print_mresp(register const u_char *bp, register u_int len)
131 {
132 register struct tr_query *tr = (struct tr_query *)(bp + 8);
133
134 printf("mresp %lu: %s to %s reply-to %s",
135 (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
136 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
137 ipaddr_string(&tr->tr_raddr));
138 if (IN_CLASSD(ntohl(tr->tr_raddr)))
139 printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
140 }
141
142 static void
143 igmp_print(register const u_char *bp, register u_int len,
144 register const u_char *bp2)
145 {
146 register const struct ip *ip;
147
148 ip = (const struct ip *)bp2;
149 (void)printf("%s > %s: ",
150 ipaddr_string(&ip->ip_src),
151 ipaddr_string(&ip->ip_dst));
152
153 if (qflag) {
154 (void)printf("igmp");
155 return;
156 }
157
158 TCHECK2(bp[0], 8);
159 switch (bp[0]) {
160 case 0x11:
161 (void)printf("igmp query");
162 if (EXTRACT_32BITS(&bp[4]))
163 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
164 if (len != 8)
165 (void)printf(" [len %d]", len);
166 break;
167 case 0x12:
168 (void)printf("igmp v1 report %s", ipaddr_string(&bp[4]));
169 if (len != 8)
170 (void)printf(" [len %d]", len);
171 break;
172 case 0x16:
173 (void)printf("igmp v2 report %s", ipaddr_string(&bp[4]));
174 break;
175 case 0x17:
176 (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
177 break;
178 case 0x13:
179 (void)printf("igmp dvmrp");
180 if (len < 8)
181 (void)printf(" [len %d]", len);
182 else
183 dvmrp_print(bp, len);
184 break;
185 case 0x14:
186 (void)printf("igmp pimv1");
187 pimv1_print(bp, len);
188 break;
189 case 0x1e:
190 print_mresp(bp, len);
191 break;
192 case 0x1f:
193 print_mtrace(bp, len);
194 break;
195 default:
196 (void)printf("igmp-%d", bp[0]);
197 break;
198 }
199
200 if (vflag && TTEST2(bp[0], len)) {
201 /* Check the IGMP checksum */
202 if (in_cksum((const u_short*)bp, len, 0))
203 printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
204 }
205 return;
206 trunc:
207 fputs("[|igmp]", stdout);
208 }
209
210 /*
211 * print the recorded route in an IP RR, LSRR or SSRR option.
212 */
213 static void
214 ip_printroute(const char *type, register const u_char *cp, u_int length)
215 {
216 register u_int ptr = cp[2] - 1;
217 register u_int len;
218
219 printf(" %s{", type);
220 if ((length + 1) & 3)
221 printf(" [bad length %d]", length);
222 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
223 printf(" [bad ptr %d]", cp[2]);
224
225 type = "";
226 for (len = 3; len < length; len += 4) {
227 if (ptr == len)
228 type = "#";
229 printf("%s%s", type, ipaddr_string(&cp[len]));
230 type = " ";
231 }
232 printf("%s}", ptr == len? "#" : "");
233 }
234
235 static void
236 ip_printts(register const u_char *cp, u_int length)
237 {
238 register u_int ptr = cp[2] - 1;
239 register u_int len = 0;
240 int hoplen;
241 char *type;
242
243 printf(" TS{");
244 hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
245 if ((length - 4) & (hoplen-1))
246 printf("[bad length %d]", length);
247 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
248 printf("[bad ptr %d]", cp[2]);
249 switch (cp[3]&0xF) {
250 case IPOPT_TS_TSONLY:
251 printf("TSONLY");
252 break;
253 case IPOPT_TS_TSANDADDR:
254 printf("TS+ADDR");
255 break;
256 /*
257 * prespecified should really be 3, but some ones might send 2
258 * instead, and the IPOPT_TS_PRESPEC constant can apparently
259 * have both values, so we have to hard-code it here.
260 */
261
262 case 2:
263 printf("PRESPEC2.0");
264 break;
265 case 3: /* IPOPT_TS_PRESPEC */
266 printf("PRESPEC");
267 break;
268 default:
269 printf("[bad ts type %d]", cp[3]&0xF);
270 goto done;
271 }
272
273 type = " ";
274 for (len = 4; len < length; len += hoplen) {
275 if (ptr == len)
276 type = " ^ ";
277 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
278 hoplen!=8 ? "" : ipaddr_string(&cp[len]));
279 type = " ";
280 }
281
282 done:
283 printf("%s", ptr == len ? " ^ " : "");
284
285 if (cp[3]>>4)
286 printf(" [%d hops not recorded]} ", cp[3]>>4);
287 else
288 printf("}");
289 }
290
291 /*
292 * print IP options.
293 */
294 static void
295 ip_optprint(register const u_char *cp, u_int length)
296 {
297 register u_int len;
298
299 for (; length > 0; cp += len, length -= len) {
300 int tt = *cp;
301
302 if (tt == IPOPT_NOP || tt == IPOPT_EOL)
303 len = 1;
304 else {
305 if (&cp[1] >= snapend) {
306 printf("[|ip]");
307 return;
308 }
309 len = cp[1];
310 }
311 if (len <= 0) {
312 printf("[|ip op len %d]", len);
313 return;
314 }
315 if (&cp[1] >= snapend || cp + len > snapend) {
316 printf("[|ip]");
317 return;
318 }
319 switch (tt) {
320
321 case IPOPT_EOL:
322 printf(" EOL");
323 if (length > 1)
324 printf("-%d", length - 1);
325 return;
326
327 case IPOPT_NOP:
328 printf(" NOP");
329 break;
330
331 case IPOPT_TS:
332 ip_printts(cp, len);
333 break;
334
335 #ifndef IPOPT_SECURITY
336 #define IPOPT_SECURITY 130
337 #endif /* IPOPT_SECURITY */
338 case IPOPT_SECURITY:
339 printf(" SECURITY{%d}", len);
340 break;
341
342 case IPOPT_RR:
343 ip_printroute("RR", cp, len);
344 break;
345
346 case IPOPT_SSRR:
347 ip_printroute("SSRR", cp, len);
348 break;
349
350 case IPOPT_LSRR:
351 ip_printroute("LSRR", cp, len);
352 break;
353
354 #ifndef IPOPT_RA
355 #define IPOPT_RA 148 /* router alert */
356 #endif
357 case IPOPT_RA:
358 printf(" RA");
359 if (len != 4)
360 printf("{%d}", len);
361 else if (cp[2] || cp[3])
362 printf("%d.%d", cp[2], cp[3]);
363 break;
364
365 default:
366 printf(" IPOPT-%d{%d}", cp[0], len);
367 break;
368 }
369 }
370 }
371
372 /*
373 * compute an IP header checksum.
374 * don't modifiy the packet.
375 */
376 u_short
377 in_cksum(const u_short *addr, register int len, u_short csum)
378 {
379 int nleft = len;
380 const u_short *w = addr;
381 u_short answer;
382 int sum = csum;
383
384 /*
385 * Our algorithm is simple, using a 32 bit accumulator (sum),
386 * we add sequential 16 bit words to it, and at the end, fold
387 * back all the carry bits from the top 16 bits into the lower
388 * 16 bits.
389 */
390 while (nleft > 1) {
391 sum += *w++;
392 nleft -= 2;
393 }
394 if (nleft == 1)
395 sum += htons(*(u_char *)w<<8);
396
397 /*
398 * add back carry outs from top 16 bits to low 16 bits
399 */
400 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
401 sum += (sum >> 16); /* add carry */
402 answer = ~sum; /* truncate to 16 bits */
403 return (answer);
404 }
405
406 /*
407 * print an IP datagram.
408 */
409 void
410 ip_print(register const u_char *bp, register u_int length)
411 {
412 register const struct ip *ip;
413 register u_int hlen, len, len0, off;
414 register const u_char *cp;
415 u_char nh;
416 int advance;
417
418 ip = (const struct ip *)bp;
419 #ifdef LBL_ALIGN
420 /*
421 * If the IP header is not aligned, copy into abuf.
422 * This will never happen with BPF. It does happen raw packet
423 * dumps from -r.
424 */
425 if ((long)ip & 3) {
426 static u_char *abuf = NULL;
427 static int didwarn = 0;
428
429 if (abuf == NULL) {
430 abuf = (u_char *)malloc(snaplen);
431 if (abuf == NULL)
432 error("ip_print: malloc");
433 }
434 memcpy((char *)abuf, (char *)ip, min(length, snaplen));
435 snapend += abuf - (u_char *)ip;
436 packetp = abuf;
437 ip = (struct ip *)abuf;
438 /* We really want libpcap to give us aligned packets */
439 if (!didwarn) {
440 warning("compensating for unaligned libpcap packets");
441 ++didwarn;
442 }
443 }
444 #endif
445 if ((u_char *)(ip + 1) > snapend) {
446 printf("[|ip]");
447 return;
448 }
449 if (length < sizeof (struct ip)) {
450 (void)printf("truncated-ip %d", length);
451 return;
452 }
453 hlen = ip->ip_hl * 4;
454 if (hlen < sizeof (struct ip)) {
455 (void)printf("bad-hlen %d", hlen);
456 return;
457 }
458
459 len = ntohs(ip->ip_len);
460 if (length < len)
461 (void)printf("truncated-ip - %d bytes missing!",
462 len - length);
463 len -= hlen;
464 len0 = len;
465
466 /*
467 * If this is fragment zero, hand it to the next higher
468 * level protocol.
469 */
470 off = ntohs(ip->ip_off);
471 if ((off & 0x1fff) == 0) {
472 cp = (const u_char *)ip + hlen;
473 nh = ip->ip_p;
474
475 if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) {
476 (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
477 ipaddr_string(&ip->ip_dst));
478 }
479 again:
480 switch (nh) {
481
482 #ifndef IPPROTO_AH
483 #define IPPROTO_AH 51
484 #endif
485 case IPPROTO_AH:
486 nh = *cp;
487 advance = ah_print(cp, (const u_char *)ip);
488 cp += advance;
489 len -= advance;
490 goto again;
491
492 #ifndef IPPROTO_ESP
493 #define IPPROTO_ESP 50
494 #endif
495 case IPPROTO_ESP:
496 {
497 int enh;
498 advance = esp_print(cp, (const u_char *)ip, &enh);
499 cp += advance;
500 len -= advance;
501 if (enh < 0)
502 break;
503 nh = enh & 0xff;
504 goto again;
505 }
506
507 #ifndef IPPROTO_IPCOMP
508 #define IPPROTO_IPCOMP 108
509 #endif
510 case IPPROTO_IPCOMP:
511 {
512 int enh;
513 advance = ipcomp_print(cp, (const u_char *)ip, &enh);
514 cp += advance;
515 len -= advance;
516 if (enh < 0)
517 break;
518 nh = enh & 0xff;
519 goto again;
520 }
521
522 case IPPROTO_TCP:
523 tcp_print(cp, len, (const u_char *)ip);
524 break;
525
526 case IPPROTO_UDP:
527 udp_print(cp, len, (const u_char *)ip);
528 break;
529
530 case IPPROTO_ICMP:
531 icmp_print(cp, len, (const u_char *)ip);
532 break;
533
534 #ifndef IPPROTO_IGRP
535 #define IPPROTO_IGRP 9
536 #endif
537 case IPPROTO_IGRP:
538 igrp_print(cp, len, (const u_char *)ip);
539 break;
540
541 case IPPROTO_ND:
542 #if 0
543 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
544 ipaddr_string(&ip->ip_dst));
545 #endif
546 (void)printf(" nd %d", len);
547 break;
548
549 case IPPROTO_EGP:
550 egp_print(cp, len, (const u_char *)ip);
551 break;
552
553 #ifndef IPPROTO_OSPF
554 #define IPPROTO_OSPF 89
555 #endif
556 case IPPROTO_OSPF:
557 ospf_print(cp, len, (const u_char *)ip);
558 break;
559
560 #ifndef IPPROTO_IGMP
561 #define IPPROTO_IGMP 2
562 #endif
563 case IPPROTO_IGMP:
564 igmp_print(cp, len, (const u_char *)ip);
565 break;
566
567 case 4:
568 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
569 #if 0
570 if (vflag)
571 (void)printf("%s > %s: ",
572 ipaddr_string(&ip->ip_src),
573 ipaddr_string(&ip->ip_dst));
574 #endif
575 ip_print(cp, len);
576 if (! vflag) {
577 printf(" (ipip)");
578 return;
579 }
580 break;
581
582 #ifdef INET6
583 #ifndef IP6PROTO_ENCAP
584 #define IP6PROTO_ENCAP 41
585 #endif
586 case IP6PROTO_ENCAP:
587 /* ip6-in-ip encapsulation */
588 #if 0
589 if (vflag)
590 (void)printf("%s > %s: ",
591 ipaddr_string(&ip->ip_src),
592 ipaddr_string(&ip->ip_dst));
593 #endif
594 ip6_print(cp, len);
595 if (! vflag) {
596 printf(" (encap)");
597 return;
598 }
599 break;
600 #endif /*INET6*/
601
602
603 #ifndef IPPROTO_GRE
604 #define IPPROTO_GRE 47
605 #endif
606 case IPPROTO_GRE:
607 if (vflag)
608 (void)printf("gre %s > %s: ",
609 ipaddr_string(&ip->ip_src),
610 ipaddr_string(&ip->ip_dst));
611 /* do it */
612 gre_print(cp, len);
613 if (! vflag) {
614 printf(" (gre encap)");
615 return;
616 }
617 break;
618
619 #ifndef IPPROTO_MOBILE
620 #define IPPROTO_MOBILE 55
621 #endif
622 case IPPROTO_MOBILE:
623 if (vflag)
624 (void)printf("mobile %s > %s: ",
625 ipaddr_string(&ip->ip_src),
626 ipaddr_string(&ip->ip_dst));
627 mobile_print(cp, len);
628 if (! vflag) {
629 printf(" (mobile encap)");
630 return;
631 }
632 break;
633
634 #ifndef IPPROTO_PIM
635 #define IPPROTO_PIM 103
636 #endif
637 case IPPROTO_PIM:
638 pim_print(cp, len);
639 break;
640
641 #ifndef IPPROTO_VRRP
642 #define IPPROTO_VRRP 112
643 #endif
644 case IPPROTO_VRRP:
645 vrrp_print(cp, len, ip->ip_ttl);
646 break;
647
648 default:
649 #if 0
650 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
651 ipaddr_string(&ip->ip_dst));
652 #endif
653 (void)printf(" ip-proto-%d %d", nh, len);
654 break;
655 }
656 }
657
658 /* Ultra quiet now means that all this stuff should be suppressed */
659 /* res 3-Nov-98 */
660 if (qflag > 1) return;
661
662
663 /*
664 * for fragmented datagrams, print id:size@offset. On all
665 * but the last stick a "+". For unfragmented datagrams, note
666 * the don't fragment flag.
667 */
668 len = len0; /* get the original length */
669 if (off & 0x3fff) {
670 /*
671 * if this isn't the first frag, we're missing the
672 * next level protocol header. print the ip addr.
673 */
674 if (off & 0x1fff)
675 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
676 ipaddr_string(&ip->ip_dst));
677 #ifndef IP_MF
678 #define IP_MF 0x2000
679 #endif /* IP_MF */
680 #ifndef IP_DF
681 #define IP_DF 0x4000
682 #endif /* IP_DF */
683 (void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
684 (off & 0x1fff) * 8,
685 (off & IP_MF)? "+" : "");
686
687 } else if (off & IP_DF)
688 (void)printf(" (DF)");
689
690 if (ip->ip_tos) {
691 (void)printf(" [tos 0x%x", (int)ip->ip_tos);
692 /* ECN bits */
693 if (ip->ip_tos&0x02) {
694 (void)printf(",ECT");
695 if (ip->ip_tos&0x01)
696 (void)printf(",CE");
697 }
698 (void)printf("] ");
699 }
700
701 if (ip->ip_ttl <= 1)
702 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
703
704 if (vflag) {
705 int sum;
706 char *sep = "";
707
708 printf(" (");
709 if (ip->ip_ttl > 1) {
710 (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
711 sep = ", ";
712 }
713 if ((off & 0x3fff) == 0) {
714 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
715 sep = ", ";
716 }
717 if ((u_char *)ip + hlen <= snapend) {
718 sum = in_cksum((const u_short *)ip, hlen, 0);
719 if (sum != 0) {
720 (void)printf("%sbad cksum %x!", sep,
721 ntohs(ip->ip_sum));
722 sep = ", ";
723 }
724 }
725 if ((hlen -= sizeof(struct ip)) > 0) {
726 (void)printf("%soptlen=%d", sep, hlen);
727 ip_optprint((u_char *)(ip + 1), hlen);
728 }
729 printf(")");
730 }
731 }