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