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 * $FreeBSD$ 22 */ 23 24 #ifndef lint 25 static const char rcsid[] _U_ = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.159 2007-09-14 01:29:28 guy Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <tcpdump-stdinc.h> 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 #include "addrtoname.h" 40 #include "interface.h" 41 #include "extract.h" /* must come after interface.h */ 42 43 #include "ip.h" 44 #include "ipproto.h" 45 46 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("[|ip]"); 304 } 305 306 #define IP_RES 0x8000 307 308 static 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 case IPPROTO_PFSYNC: 487 pfsync_ip_print(ipds->cp, ipds->len); 488 break; 489 490 default: 491 if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) 492 ND_PRINT((ndo, " %s", proto->p_name)); 493 else 494 ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); 495 ND_PRINT((ndo, " %d", ipds->len)); 496 break; 497 } 498 } 499 500 void 501 ip_print_inner(netdissect_options *ndo, 502 const u_char *bp, 503 u_int length, u_int nh, 504 const u_char *bp2) 505 { 506 struct ip_print_demux_state ipd; 507 508 ipd.ip = (const struct ip *)bp2; 509 ipd.cp = bp; 510 ipd.len = length; 511 ipd.off = 0; 512 ipd.nh = nh; 513 ipd.advance = 0; 514 515 ip_print_demux(ndo, &ipd); 516 } 517 518 519 /* 520 * print an IP datagram. 521 */ 522 void 523 ip_print(netdissect_options *ndo, 524 const u_char *bp, 525 u_int length) 526 { 527 struct ip_print_demux_state ipd; 528 struct ip_print_demux_state *ipds=&ipd; 529 const u_char *ipend; 530 u_int hlen; 531 struct cksum_vec vec[1]; 532 u_int16_t sum, ip_sum; 533 struct protoent *proto; 534 535 ipds->ip = (const struct ip *)bp; 536 if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ 537 printf("IP%u ", IP_V(ipds->ip)); 538 if (IP_V(ipds->ip) == 6) 539 printf(", wrong link-layer encapsulation"); 540 } 541 else if (!eflag) 542 printf("IP "); 543 544 if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) { 545 printf("[|ip]"); 546 return; 547 } 548 if (length < sizeof (struct ip)) { 549 (void)printf("truncated-ip %u", length); 550 return; 551 } 552 hlen = IP_HL(ipds->ip) * 4; 553 if (hlen < sizeof (struct ip)) { 554 (void)printf("bad-hlen %u", hlen); 555 return; 556 } 557 558 ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); 559 if (length < ipds->len) 560 (void)printf("truncated-ip - %u bytes missing! ", 561 ipds->len - length); 562 if (ipds->len < hlen) { 563 #ifdef GUESS_TSO 564 if (ipds->len) { 565 (void)printf("bad-len %u", ipds->len); 566 return; 567 } 568 else { 569 /* we guess that it is a TSO send */ 570 ipds->len = length; 571 } 572 #else 573 (void)printf("bad-len %u", ipds->len); 574 return; 575 #endif /* GUESS_TSO */ 576 } 577 578 /* 579 * Cut off the snapshot length to the end of the IP payload. 580 */ 581 ipend = bp + ipds->len; 582 if (ipend < ndo->ndo_snapend) 583 ndo->ndo_snapend = ipend; 584 585 ipds->len -= hlen; 586 587 ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); 588 589 if (vflag) { 590 (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos); 591 /* ECN bits */ 592 if (ipds->ip->ip_tos & 0x03) { 593 switch (ipds->ip->ip_tos & 0x03) { 594 case 1: 595 (void)printf(",ECT(1)"); 596 break; 597 case 2: 598 (void)printf(",ECT(0)"); 599 break; 600 case 3: 601 (void)printf(",CE"); 602 } 603 } 604 605 if (ipds->ip->ip_ttl >= 1) 606 (void)printf(", ttl %u", ipds->ip->ip_ttl); 607 608 /* 609 * for the firewall guys, print id, offset. 610 * On all but the last stick a "+" in the flags portion. 611 * For unfragmented datagrams, note the don't fragment flag. 612 */ 613 614 (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)", 615 EXTRACT_16BITS(&ipds->ip->ip_id), 616 (ipds->off & 0x1fff) * 8, 617 bittok2str(ip_frag_values, "none", ipds->off&0xe000), 618 tok2str(ipproto_values,"unknown",ipds->ip->ip_p), 619 ipds->ip->ip_p); 620 621 (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)); 622 623 if ((hlen - sizeof(struct ip)) > 0) { 624 printf(", options ("); 625 ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); 626 printf(")"); 627 } 628 629 if (!Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) { 630 vec[0].ptr = (const u_int8_t *)(void *)ipds->ip; 631 vec[0].len = hlen; 632 sum = in_cksum(vec, 1); 633 if (sum != 0) { 634 ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); 635 (void)printf(", bad cksum %x (->%x)!", ip_sum, 636 in_cksum_shouldbe(ip_sum, sum)); 637 } 638 } 639 640 printf(")\n "); 641 } 642 643 /* 644 * If this is fragment zero, hand it to the next higher 645 * level protocol. 646 */ 647 if ((ipds->off & 0x1fff) == 0) { 648 ipds->cp = (const u_char *)ipds->ip + hlen; 649 ipds->nh = ipds->ip->ip_p; 650 651 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && 652 ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) { 653 (void)printf("%s > %s: ", 654 ipaddr_string(&ipds->ip->ip_src), 655 ipaddr_string(&ipds->ip->ip_dst)); 656 } 657 ip_print_demux(ndo, ipds); 658 } else { 659 /* Ultra quiet now means that all this stuff should be suppressed */ 660 if (qflag > 1) return; 661 662 /* 663 * if this isn't the first frag, we're missing the 664 * next level protocol header. print the ip addr 665 * and the protocol. 666 */ 667 if (ipds->off & 0x1fff) { 668 (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src), 669 ipaddr_string(&ipds->ip->ip_dst)); 670 if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) 671 (void)printf(" %s", proto->p_name); 672 else 673 (void)printf(" ip-proto-%d", ipds->ip->ip_p); 674 } 675 } 676 } 677 678 void 679 ipN_print(register const u_char *bp, register u_int length) 680 { 681 struct ip *ip, hdr; 682 683 ip = (struct ip *)bp; 684 if (length < 4) { 685 (void)printf("truncated-ip %d", length); 686 return; 687 } 688 memcpy (&hdr, (char *)ip, 4); 689 switch (IP_V(&hdr)) { 690 case 4: 691 ip_print (gndo, bp, length); 692 return; 693 #ifdef INET6 694 case 6: 695 ip6_print (gndo, bp, length); 696 return; 697 #endif 698 default: 699 (void)printf("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