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