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