]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip.c
Don't try to print packets with a too-short hlen.
[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.80 2000-01-25 01:03:23 fenner 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 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
303 if (len <= 0) {
304 printf("[|ip op len %d]", len);
305 return;
306 }
307 if (&cp[1] >= snapend || cp + len > snapend) {
308 printf("[|ip]");
309 return;
310 }
311 switch (tt) {
312
313 case IPOPT_EOL:
314 printf(" EOL");
315 if (length > 1)
316 printf("-%d", length - 1);
317 return;
318
319 case IPOPT_NOP:
320 printf(" NOP");
321 break;
322
323 case IPOPT_TS:
324 ip_printts(cp, len);
325 break;
326
327 #ifndef IPOPT_SECURITY
328 #define IPOPT_SECURITY 130
329 #endif /* IPOPT_SECURITY */
330 case IPOPT_SECURITY:
331 printf(" SECURITY{%d}", len);
332 break;
333
334 case IPOPT_RR:
335 ip_printroute("RR", cp, len);
336 break;
337
338 case IPOPT_SSRR:
339 ip_printroute("SSRR", cp, len);
340 break;
341
342 case IPOPT_LSRR:
343 ip_printroute("LSRR", cp, len);
344 break;
345
346 #ifndef IPOPT_RA
347 #define IPOPT_RA 148 /* router alert */
348 #endif
349 case IPOPT_RA:
350 printf(" RA");
351 if (len != 4)
352 printf("{%d}", len);
353 else if (cp[2] || cp[3])
354 printf("%d.%d", cp[2], cp[3]);
355 break;
356
357 default:
358 printf(" IPOPT-%d{%d}", cp[0], len);
359 break;
360 }
361 }
362 }
363
364 /*
365 * compute an IP header checksum.
366 * don't modifiy the packet.
367 */
368 u_short
369 in_cksum(const u_short *addr, register int len, u_short csum)
370 {
371 int nleft = len;
372 const u_short *w = addr;
373 u_short answer;
374 int sum = csum;
375
376 /*
377 * Our algorithm is simple, using a 32 bit accumulator (sum),
378 * we add sequential 16 bit words to it, and at the end, fold
379 * back all the carry bits from the top 16 bits into the lower
380 * 16 bits.
381 */
382 while (nleft > 1) {
383 sum += *w++;
384 nleft -= 2;
385 }
386 if (nleft == 1)
387 sum += htons(*(u_char *)w<<8);
388
389 /*
390 * add back carry outs from top 16 bits to low 16 bits
391 */
392 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
393 sum += (sum >> 16); /* add carry */
394 answer = ~sum; /* truncate to 16 bits */
395 return (answer);
396 }
397
398 /*
399 * print an IP datagram.
400 */
401 void
402 ip_print(register const u_char *bp, register u_int length)
403 {
404 register const struct ip *ip;
405 register u_int hlen, len, len0, off;
406 register const u_char *cp;
407 u_char nh;
408 int advance;
409
410 ip = (const struct ip *)bp;
411 #ifdef LBL_ALIGN
412 /*
413 * If the IP header is not aligned, copy into abuf.
414 * This will never happen with BPF. It does happen raw packet
415 * dumps from -r.
416 */
417 if ((long)ip & 3) {
418 static u_char *abuf = NULL;
419 static int didwarn = 0;
420
421 if (abuf == NULL) {
422 abuf = (u_char *)malloc(snaplen);
423 if (abuf == NULL)
424 error("ip_print: malloc");
425 }
426 memcpy((char *)abuf, (char *)ip, min(length, snaplen));
427 snapend += abuf - (u_char *)ip;
428 packetp = abuf;
429 ip = (struct ip *)abuf;
430 /* We really want libpcap to give us aligned packets */
431 if (!didwarn) {
432 warning("compensating for unaligned libpcap packets");
433 ++didwarn;
434 }
435 }
436 #endif
437 if ((u_char *)(ip + 1) > snapend) {
438 printf("[|ip]");
439 return;
440 }
441 if (length < sizeof (struct ip)) {
442 (void)printf("truncated-ip %d", length);
443 return;
444 }
445 hlen = ip->ip_hl * 4;
446 if (hlen < sizeof (struct ip)) {
447 (void)printf("bad-hlen %d", hlen);
448 return;
449 }
450
451 len = ntohs(ip->ip_len);
452 if (length < len)
453 (void)printf("truncated-ip - %d bytes missing!",
454 len - length);
455 len -= hlen;
456 len0 = len;
457
458 /*
459 * If this is fragment zero, hand it to the next higher
460 * level protocol.
461 */
462 off = ntohs(ip->ip_off);
463 if ((off & 0x1fff) == 0) {
464 cp = (const u_char *)ip + hlen;
465 nh = ip->ip_p;
466
467 if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) {
468 (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
469 ipaddr_string(&ip->ip_dst));
470 }
471 again:
472 switch (nh) {
473
474 #ifndef IPPROTO_AH
475 #define IPPROTO_AH 51
476 #endif
477 case IPPROTO_AH:
478 nh = *cp;
479 advance = ah_print(cp, (const u_char *)ip);
480 cp += advance;
481 len -= advance;
482 goto again;
483
484 #ifndef IPPROTO_ESP
485 #define IPPROTO_ESP 50
486 #endif
487 case IPPROTO_ESP:
488 {
489 int enh;
490 advance = esp_print(cp, (const u_char *)ip, &enh);
491 cp += advance;
492 len -= advance;
493 if (enh < 0)
494 break;
495 nh = enh & 0xff;
496 goto again;
497 }
498
499 #ifndef IPPROTO_IPCOMP
500 #define IPPROTO_IPCOMP 108
501 #endif
502 case IPPROTO_IPCOMP:
503 {
504 int enh;
505 advance = ipcomp_print(cp, (const u_char *)ip, &enh);
506 cp += advance;
507 len -= advance;
508 if (enh < 0)
509 break;
510 nh = enh & 0xff;
511 goto again;
512 }
513
514 case IPPROTO_TCP:
515 tcp_print(cp, len, (const u_char *)ip);
516 break;
517
518 case IPPROTO_UDP:
519 udp_print(cp, len, (const u_char *)ip);
520 break;
521
522 case IPPROTO_ICMP:
523 icmp_print(cp, len, (const u_char *)ip);
524 break;
525
526 #ifndef IPPROTO_IGRP
527 #define IPPROTO_IGRP 9
528 #endif
529 case IPPROTO_IGRP:
530 igrp_print(cp, len, (const u_char *)ip);
531 break;
532
533 case IPPROTO_ND:
534 #if 0
535 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
536 ipaddr_string(&ip->ip_dst));
537 #endif
538 (void)printf(" nd %d", len);
539 break;
540
541 case IPPROTO_EGP:
542 egp_print(cp, len, (const u_char *)ip);
543 break;
544
545 #ifndef IPPROTO_OSPF
546 #define IPPROTO_OSPF 89
547 #endif
548 case IPPROTO_OSPF:
549 ospf_print(cp, len, (const u_char *)ip);
550 break;
551
552 #ifndef IPPROTO_IGMP
553 #define IPPROTO_IGMP 2
554 #endif
555 case IPPROTO_IGMP:
556 igmp_print(cp, len, (const u_char *)ip);
557 break;
558
559 case 4:
560 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
561 #if 0
562 if (vflag)
563 (void)printf("%s > %s: ",
564 ipaddr_string(&ip->ip_src),
565 ipaddr_string(&ip->ip_dst));
566 #endif
567 ip_print(cp, len);
568 if (! vflag) {
569 printf(" (ipip)");
570 return;
571 }
572 break;
573
574 #ifdef INET6
575 #ifndef IP6PROTO_ENCAP
576 #define IP6PROTO_ENCAP 41
577 #endif
578 case IP6PROTO_ENCAP:
579 /* ip6-in-ip encapsulation */
580 #if 0
581 if (vflag)
582 (void)printf("%s > %s: ",
583 ipaddr_string(&ip->ip_src),
584 ipaddr_string(&ip->ip_dst));
585 #endif
586 ip6_print(cp, len);
587 if (! vflag) {
588 printf(" (encap)");
589 return;
590 }
591 break;
592 #endif /*INET6*/
593
594
595 #ifndef IPPROTO_GRE
596 #define IPPROTO_GRE 47
597 #endif
598 case IPPROTO_GRE:
599 if (vflag)
600 (void)printf("gre %s > %s: ",
601 ipaddr_string(&ip->ip_src),
602 ipaddr_string(&ip->ip_dst));
603 /* do it */
604 gre_print(cp, len);
605 if (! vflag) {
606 printf(" (gre encap)");
607 return;
608 }
609 break;
610
611 #ifndef IPPROTO_MOBILE
612 #define IPPROTO_MOBILE 55
613 #endif
614 case IPPROTO_MOBILE:
615 if (vflag)
616 (void)printf("mobile %s > %s: ",
617 ipaddr_string(&ip->ip_src),
618 ipaddr_string(&ip->ip_dst));
619 mobile_print(cp, len);
620 if (! vflag) {
621 printf(" (mobile encap)");
622 return;
623 }
624 break;
625
626 #ifndef IPPROTO_PIM
627 #define IPPROTO_PIM 103
628 #endif
629 case IPPROTO_PIM:
630 pim_print(cp, len);
631 break;
632
633 default:
634 #if 0
635 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
636 ipaddr_string(&ip->ip_dst));
637 #endif
638 (void)printf(" ip-proto-%d %d", nh, len);
639 break;
640 }
641 }
642
643 /* Ultra quiet now means that all this stuff should be suppressed */
644 /* res 3-Nov-98 */
645 if (qflag > 1) return;
646
647
648 /*
649 * for fragmented datagrams, print id:size@offset. On all
650 * but the last stick a "+". For unfragmented datagrams, note
651 * the don't fragment flag.
652 */
653 len = len0; /* get the original length */
654 if (off & 0x3fff) {
655 /*
656 * if this isn't the first frag, we're missing the
657 * next level protocol header. print the ip addr.
658 */
659 if (off & 0x1fff)
660 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
661 ipaddr_string(&ip->ip_dst));
662 #ifndef IP_MF
663 #define IP_MF 0x2000
664 #endif /* IP_MF */
665 #ifndef IP_DF
666 #define IP_DF 0x4000
667 #endif /* IP_DF */
668 (void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
669 (off & 0x1fff) * 8,
670 (off & IP_MF)? "+" : "");
671
672 } else if (off & IP_DF)
673 (void)printf(" (DF)");
674
675 if (ip->ip_tos) {
676 (void)printf(" [tos 0x%x", (int)ip->ip_tos);
677 /* ECN bits */
678 if (ip->ip_tos&0x02) {
679 (void)printf(",ECT");
680 if (ip->ip_tos&0x01)
681 (void)printf(",CE");
682 }
683 (void)printf("] ");
684 }
685
686 if (ip->ip_ttl <= 1)
687 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
688
689 if (vflag) {
690 int sum;
691 char *sep = "";
692
693 printf(" (");
694 if (ip->ip_ttl > 1) {
695 (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
696 sep = ", ";
697 }
698 if ((off & 0x3fff) == 0) {
699 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
700 sep = ", ";
701 }
702 if ((u_char *)ip + hlen <= snapend) {
703 sum = in_cksum((const u_short *)ip, hlen, 0);
704 if (sum != 0) {
705 (void)printf("%sbad cksum %x!", sep,
706 ntohs(ip->ip_sum));
707 sep = ", ";
708 }
709 }
710 if ((hlen -= sizeof(struct ip)) > 0) {
711 (void)printf("%soptlen=%d", sep, hlen);
712 ip_optprint((u_char *)(ip + 1), hlen);
713 }
714 printf(")");
715 }
716 }