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