]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip.c
8a2fa2e32945d18bcbe94f48ec75c9c657708ece
[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[] _U_ =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.159 2007-09-14 01:29:28 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 static const char tstr[] = "[|ip]";
45
46 static const struct tok ip_option_values[] = {
47 { IPOPT_EOL, "EOL" },
48 { IPOPT_NOP, "NOP" },
49 { IPOPT_TS, "timestamp" },
50 { IPOPT_SECURITY, "security" },
51 { IPOPT_RR, "RR" },
52 { IPOPT_SSRR, "SSRR" },
53 { IPOPT_LSRR, "LSRR" },
54 { IPOPT_RA, "RA" },
55 { IPOPT_RFC1393, "traceroute" },
56 { 0, NULL }
57 };
58
59 /*
60 * print the recorded route in an IP RR, LSRR or SSRR option.
61 */
62 static void
63 ip_printroute(register const u_char *cp, u_int length)
64 {
65 register u_int ptr;
66 register u_int len;
67
68 if (length < 3) {
69 printf(" [bad length %u]", length);
70 return;
71 }
72 if ((length + 1) & 3)
73 printf(" [bad length %u]", length);
74 ptr = cp[2] - 1;
75 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
76 printf(" [bad ptr %u]", cp[2]);
77
78 for (len = 3; len < length; len += 4) {
79 printf(" %s", ipaddr_string(&cp[len]));
80 if (ptr > len)
81 printf(",");
82 }
83 }
84
85 /*
86 * If source-routing is present and valid, return the final destination.
87 * Otherwise, return IP destination.
88 *
89 * This is used for UDP and TCP pseudo-header in the checksum
90 * calculation.
91 */
92 static u_int32_t
93 ip_finddst(const struct ip *ip)
94 {
95 int length;
96 int len;
97 const u_char *cp;
98 u_int32_t retval;
99
100 cp = (const u_char *)(ip + 1);
101 length = (IP_HL(ip) << 2) - sizeof(struct ip);
102
103 for (; length > 0; cp += len, length -= len) {
104 int tt;
105
106 TCHECK(*cp);
107 tt = *cp;
108 if (tt == IPOPT_EOL)
109 break;
110 else if (tt == IPOPT_NOP)
111 len = 1;
112 else {
113 TCHECK(cp[1]);
114 len = cp[1];
115 if (len < 2)
116 break;
117 }
118 TCHECK2(*cp, len);
119 switch (tt) {
120
121 case IPOPT_SSRR:
122 case IPOPT_LSRR:
123 if (len < 7)
124 break;
125 memcpy(&retval, cp + len - 4, 4);
126 return retval;
127 }
128 }
129 trunc:
130 memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t));
131 return retval;
132 }
133
134 /*
135 * Compute a V4-style checksum by building a pseudoheader.
136 */
137 int
138 nextproto4_cksum(const struct ip *ip, const u_int8_t *data,
139 u_int len, u_int next_proto)
140 {
141 struct phdr {
142 u_int32_t src;
143 u_int32_t dst;
144 u_char mbz;
145 u_char proto;
146 u_int16_t len;
147 } ph;
148 struct cksum_vec vec[2];
149
150 /* pseudo-header.. */
151 ph.len = htons((u_int16_t)len);
152 ph.mbz = 0;
153 ph.proto = next_proto;
154 memcpy(&ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
155 if (IP_HL(ip) == 5)
156 memcpy(&ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
157 else
158 ph.dst = ip_finddst(ip);
159
160 vec[0].ptr = (const u_int8_t *)(void *)&ph;
161 vec[0].len = sizeof(ph);
162 vec[1].ptr = data;
163 vec[1].len = len;
164 return (in_cksum(vec, 2));
165 }
166
167 static void
168 ip_printts(register const u_char *cp, u_int length)
169 {
170 register u_int ptr;
171 register u_int len;
172 int hoplen;
173 const char *type;
174
175 if (length < 4) {
176 printf("[bad length %u]", length);
177 return;
178 }
179 printf(" TS{");
180 hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
181 if ((length - 4) & (hoplen-1))
182 printf("[bad length %u]", length);
183 ptr = cp[2] - 1;
184 len = 0;
185 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
186 printf("[bad ptr %u]", cp[2]);
187 switch (cp[3]&0xF) {
188 case IPOPT_TS_TSONLY:
189 printf("TSONLY");
190 break;
191 case IPOPT_TS_TSANDADDR:
192 printf("TS+ADDR");
193 break;
194 /*
195 * prespecified should really be 3, but some ones might send 2
196 * instead, and the IPOPT_TS_PRESPEC constant can apparently
197 * have both values, so we have to hard-code it here.
198 */
199
200 case 2:
201 printf("PRESPEC2.0");
202 break;
203 case 3: /* IPOPT_TS_PRESPEC */
204 printf("PRESPEC");
205 break;
206 default:
207 printf("[bad ts type %d]", cp[3]&0xF);
208 goto done;
209 }
210
211 type = " ";
212 for (len = 4; len < length; len += hoplen) {
213 if (ptr == len)
214 type = " ^ ";
215 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
216 hoplen!=8 ? "" : ipaddr_string(&cp[len]));
217 type = " ";
218 }
219
220 done:
221 printf("%s", ptr == len ? " ^ " : "");
222
223 if (cp[3]>>4)
224 printf(" [%d hops not recorded]} ", cp[3]>>4);
225 else
226 printf("}");
227 }
228
229 /*
230 * print IP options.
231 */
232 static void
233 ip_optprint(register const u_char *cp, u_int length)
234 {
235 register u_int option_len;
236 const char *sep = "";
237
238 for (; length > 0; cp += option_len, length -= option_len) {
239 u_int option_code;
240
241 printf("%s", sep);
242 sep = ",";
243
244 TCHECK(*cp);
245 option_code = *cp;
246
247 printf("%s",
248 tok2str(ip_option_values,"unknown %u",option_code));
249
250 if (option_code == IPOPT_NOP ||
251 option_code == IPOPT_EOL)
252 option_len = 1;
253
254 else {
255 TCHECK(cp[1]);
256 option_len = cp[1];
257 if (option_len < 2) {
258 printf(" [bad length %u]", option_len);
259 return;
260 }
261 }
262
263 if (option_len > length) {
264 printf(" [bad length %u]", option_len);
265 return;
266 }
267
268 TCHECK2(*cp, option_len);
269
270 switch (option_code) {
271 case IPOPT_EOL:
272 return;
273
274 case IPOPT_TS:
275 ip_printts(cp, option_len);
276 break;
277
278 case IPOPT_RR: /* fall through */
279 case IPOPT_SSRR:
280 case IPOPT_LSRR:
281 ip_printroute(cp, option_len);
282 break;
283
284 case IPOPT_RA:
285 if (option_len < 4) {
286 printf(" [bad length %u]", option_len);
287 break;
288 }
289 TCHECK(cp[3]);
290 if (EXTRACT_16BITS(&cp[2]) != 0)
291 printf(" value %u", EXTRACT_16BITS(&cp[2]));
292 break;
293
294 case IPOPT_NOP: /* nothing to print - fall through */
295 case IPOPT_SECURITY:
296 default:
297 break;
298 }
299 }
300 return;
301
302 trunc:
303 printf("%s", tstr);
304 }
305
306 #define IP_RES 0x8000
307
308 static const struct tok ip_frag_values[] = {
309 { IP_MF, "+" },
310 { IP_DF, "DF" },
311 { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
312 { 0, NULL }
313 };
314
315 struct ip_print_demux_state {
316 const struct ip *ip;
317 const u_char *cp;
318 u_int len, off;
319 u_char nh;
320 int advance;
321 };
322
323 static void
324 ip_print_demux(netdissect_options *ndo,
325 struct ip_print_demux_state *ipds)
326 {
327 struct protoent *proto;
328 struct cksum_vec vec[1];
329
330 again:
331 switch (ipds->nh) {
332
333 case IPPROTO_AH:
334 ipds->nh = *ipds->cp;
335 ipds->advance = ah_print(ipds->cp);
336 if (ipds->advance <= 0)
337 break;
338 ipds->cp += ipds->advance;
339 ipds->len -= ipds->advance;
340 goto again;
341
342 case IPPROTO_ESP:
343 {
344 int enh, padlen;
345 ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
346 (const u_char *)ipds->ip,
347 &enh, &padlen);
348 if (ipds->advance <= 0)
349 break;
350 ipds->cp += ipds->advance;
351 ipds->len -= ipds->advance + padlen;
352 ipds->nh = enh & 0xff;
353 goto again;
354 }
355
356 case IPPROTO_IPCOMP:
357 {
358 int enh;
359 ipds->advance = ipcomp_print(ipds->cp, &enh);
360 if (ipds->advance <= 0)
361 break;
362 ipds->cp += ipds->advance;
363 ipds->len -= ipds->advance;
364 ipds->nh = enh & 0xff;
365 goto again;
366 }
367
368 case IPPROTO_SCTP:
369 sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
370 break;
371
372 case IPPROTO_DCCP:
373 dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
374 break;
375
376 case IPPROTO_TCP:
377 /* pass on the MF bit plus the offset to detect fragments */
378 tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
379 ipds->off & (IP_MF|IP_OFFMASK));
380 break;
381
382 case IPPROTO_UDP:
383 /* pass on the MF bit plus the offset to detect fragments */
384 udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
385 ipds->off & (IP_MF|IP_OFFMASK));
386 break;
387
388 case IPPROTO_ICMP:
389 /* pass on the MF bit plus the offset to detect fragments */
390 icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
391 ipds->off & (IP_MF|IP_OFFMASK));
392 break;
393
394 case IPPROTO_PIGP:
395 /*
396 * XXX - the current IANA protocol number assignments
397 * page lists 9 as "any private interior gateway
398 * (used by Cisco for their IGRP)" and 88 as
399 * "EIGRP" from Cisco.
400 *
401 * Recent BSD <netinet/in.h> headers define
402 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
403 * We define IP_PROTO_PIGP as 9 and
404 * IP_PROTO_EIGRP as 88; those names better
405 * match was the current protocol number
406 * assignments say.
407 */
408 igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
409 break;
410
411 case IPPROTO_EIGRP:
412 eigrp_print(ipds->cp, ipds->len);
413 break;
414
415 case IPPROTO_ND:
416 ND_PRINT((ndo, " nd %d", ipds->len));
417 break;
418
419 case IPPROTO_EGP:
420 egp_print(ipds->cp, ipds->len);
421 break;
422
423 case IPPROTO_OSPF:
424 ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
425 break;
426
427 case IPPROTO_IGMP:
428 igmp_print(ipds->cp, ipds->len);
429 break;
430
431 case IPPROTO_IPV4:
432 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
433 ip_print(ndo, ipds->cp, ipds->len);
434 if (! vflag) {
435 ND_PRINT((ndo, " (ipip-proto-4)"));
436 return;
437 }
438 break;
439
440 #ifdef INET6
441 case IPPROTO_IPV6:
442 /* ip6-in-ip encapsulation */
443 ip6_print(ndo, ipds->cp, ipds->len);
444 break;
445 #endif /*INET6*/
446
447 case IPPROTO_RSVP:
448 rsvp_print(ipds->cp, ipds->len);
449 break;
450
451 case IPPROTO_GRE:
452 /* do it */
453 gre_print(ipds->cp, ipds->len);
454 break;
455
456 case IPPROTO_MOBILE:
457 mobile_print(ipds->cp, ipds->len);
458 break;
459
460 case IPPROTO_PIM:
461 vec[0].ptr = ipds->cp;
462 vec[0].len = ipds->len;
463 pim_print(ipds->cp, ipds->len, in_cksum(vec, 1));
464 break;
465
466 case IPPROTO_VRRP:
467 if (packettype == PT_CARP) {
468 if (vflag)
469 (void)printf("carp %s > %s: ",
470 ipaddr_string(&ipds->ip->ip_src),
471 ipaddr_string(&ipds->ip->ip_dst));
472 carp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
473 } else {
474 if (vflag)
475 (void)printf("vrrp %s > %s: ",
476 ipaddr_string(&ipds->ip->ip_src),
477 ipaddr_string(&ipds->ip->ip_dst));
478 vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
479 }
480 break;
481
482 case IPPROTO_PGM:
483 pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
484 break;
485
486 default:
487 if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL)
488 ND_PRINT((ndo, " %s", proto->p_name));
489 else
490 ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
491 ND_PRINT((ndo, " %d", ipds->len));
492 break;
493 }
494 }
495
496 void
497 ip_print_inner(netdissect_options *ndo,
498 const u_char *bp,
499 u_int length, u_int nh,
500 const u_char *bp2)
501 {
502 struct ip_print_demux_state ipd;
503
504 ipd.ip = (const struct ip *)bp2;
505 ipd.cp = bp;
506 ipd.len = length;
507 ipd.off = 0;
508 ipd.nh = nh;
509 ipd.advance = 0;
510
511 ip_print_demux(ndo, &ipd);
512 }
513
514
515 /*
516 * print an IP datagram.
517 */
518 void
519 ip_print(netdissect_options *ndo,
520 const u_char *bp,
521 u_int length)
522 {
523 struct ip_print_demux_state ipd;
524 struct ip_print_demux_state *ipds=&ipd;
525 const u_char *ipend;
526 u_int hlen;
527 struct cksum_vec vec[1];
528 u_int16_t sum, ip_sum;
529 struct protoent *proto;
530
531 ipds->ip = (const struct ip *)bp;
532 if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
533 printf("IP%u ", IP_V(ipds->ip));
534 if (IP_V(ipds->ip) == 6)
535 printf(", wrong link-layer encapsulation");
536 }
537 else if (!eflag)
538 printf("IP ");
539
540 if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) {
541 printf("%s", tstr);
542 return;
543 }
544 if (length < sizeof (struct ip)) {
545 (void)printf("truncated-ip %u", length);
546 return;
547 }
548 hlen = IP_HL(ipds->ip) * 4;
549 if (hlen < sizeof (struct ip)) {
550 (void)printf("bad-hlen %u", hlen);
551 return;
552 }
553
554 ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
555 if (length < ipds->len)
556 (void)printf("truncated-ip - %u bytes missing! ",
557 ipds->len - length);
558 if (ipds->len < hlen) {
559 #ifdef GUESS_TSO
560 if (ipds->len) {
561 (void)printf("bad-len %u", ipds->len);
562 return;
563 }
564 else {
565 /* we guess that it is a TSO send */
566 ipds->len = length;
567 }
568 #else
569 (void)printf("bad-len %u", ipds->len);
570 return;
571 #endif /* GUESS_TSO */
572 }
573
574 /*
575 * Cut off the snapshot length to the end of the IP payload.
576 */
577 ipend = bp + ipds->len;
578 if (ipend < ndo->ndo_snapend)
579 ndo->ndo_snapend = ipend;
580
581 ipds->len -= hlen;
582
583 ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
584
585 if (vflag) {
586 (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos);
587 /* ECN bits */
588 if (ipds->ip->ip_tos & 0x03) {
589 switch (ipds->ip->ip_tos & 0x03) {
590 case 1:
591 (void)printf(",ECT(1)");
592 break;
593 case 2:
594 (void)printf(",ECT(0)");
595 break;
596 case 3:
597 (void)printf(",CE");
598 }
599 }
600
601 if (ipds->ip->ip_ttl >= 1)
602 (void)printf(", ttl %u", ipds->ip->ip_ttl);
603
604 /*
605 * for the firewall guys, print id, offset.
606 * On all but the last stick a "+" in the flags portion.
607 * For unfragmented datagrams, note the don't fragment flag.
608 */
609
610 (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)",
611 EXTRACT_16BITS(&ipds->ip->ip_id),
612 (ipds->off & 0x1fff) * 8,
613 bittok2str(ip_frag_values, "none", ipds->off&0xe000),
614 tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
615 ipds->ip->ip_p);
616
617 (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len));
618
619 if ((hlen - sizeof(struct ip)) > 0) {
620 printf(", options (");
621 ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
622 printf(")");
623 }
624
625 if (!Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
626 vec[0].ptr = (const u_int8_t *)(void *)ipds->ip;
627 vec[0].len = hlen;
628 sum = in_cksum(vec, 1);
629 if (sum != 0) {
630 ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
631 (void)printf(", bad cksum %x (->%x)!", ip_sum,
632 in_cksum_shouldbe(ip_sum, sum));
633 }
634 }
635
636 printf(")\n ");
637 }
638
639 /*
640 * If this is fragment zero, hand it to the next higher
641 * level protocol.
642 */
643 if ((ipds->off & 0x1fff) == 0) {
644 ipds->cp = (const u_char *)ipds->ip + hlen;
645 ipds->nh = ipds->ip->ip_p;
646
647 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
648 ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
649 (void)printf("%s > %s: ",
650 ipaddr_string(&ipds->ip->ip_src),
651 ipaddr_string(&ipds->ip->ip_dst));
652 }
653 ip_print_demux(ndo, ipds);
654 } else {
655 /* Ultra quiet now means that all this stuff should be suppressed */
656 if (qflag > 1) return;
657
658 /*
659 * if this isn't the first frag, we're missing the
660 * next level protocol header. print the ip addr
661 * and the protocol.
662 */
663 if (ipds->off & 0x1fff) {
664 (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src),
665 ipaddr_string(&ipds->ip->ip_dst));
666 if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
667 (void)printf(" %s", proto->p_name);
668 else
669 (void)printf(" ip-proto-%d", ipds->ip->ip_p);
670 }
671 }
672 }
673
674 void
675 ipN_print(register const u_char *bp, register u_int length)
676 {
677 struct ip *ip, hdr;
678
679 ip = (struct ip *)bp;
680 if (length < 4) {
681 (void)printf("truncated-ip %d", length);
682 return;
683 }
684 memcpy (&hdr, (char *)ip, 4);
685 switch (IP_V(&hdr)) {
686 case 4:
687 ip_print (gndo, bp, length);
688 return;
689 #ifdef INET6
690 case 6:
691 ip6_print (gndo, bp, length);
692 return;
693 #endif
694 default:
695 (void)printf("unknown ip %d", IP_V(&hdr));
696 return;
697 }
698 }
699
700 /*
701 * Local Variables:
702 * c-style: whitesmith
703 * c-basic-offset: 8
704 * End:
705 */
706
707