print-ip.c revision 146778
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: head/contrib/tcpdump/print-ip.c 146778 2005-05-29 19:09:28Z sam $ 22 */ 23 24#ifndef lint 25static const char rcsid[] _U_ = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.149 2005/04/07 00:28:17 mcr 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 46struct 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 { 0, NULL } 56}; 57 58/* 59 * print the recorded route in an IP RR, LSRR or SSRR option. 60 */ 61static void 62ip_printroute(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 printf(" [bad length %u]", length); 69 return; 70 } 71 if ((length + 1) & 3) 72 printf(" [bad length %u]", length); 73 ptr = cp[2] - 1; 74 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 75 printf(" [bad ptr %u]", cp[2]); 76 77 for (len = 3; len < length; len += 4) { 78 printf("%s", ipaddr_string(&cp[len])); 79 if (ptr > len) 80 printf (", "); 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 */ 91u_int32_t 92ip_finddst(const struct ip *ip) 93{ 94 int length; 95 int len; 96 const u_char *cp; 97 u_int32_t retval; 98 99 cp = (const u_char *)(ip + 1); 100 length = (IP_HL(ip) << 2) - sizeof(struct ip); 101 102 for (; length > 0; cp += len, length -= len) { 103 int tt; 104 105 TCHECK(*cp); 106 tt = *cp; 107 if (tt == IPOPT_EOL) 108 break; 109 else if (tt == IPOPT_NOP) 110 len = 1; 111 else { 112 TCHECK(cp[1]); 113 len = cp[1]; 114 if (len < 2) 115 break; 116 } 117 TCHECK2(*cp, len); 118 switch (tt) { 119 120 case IPOPT_SSRR: 121 case IPOPT_LSRR: 122 if (len < 7) 123 break; 124 memcpy(&retval, cp + len - 4, 4); 125 return retval; 126 } 127 } 128trunc: 129 memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 130 return retval; 131} 132 133static void 134ip_printts(register const u_char *cp, u_int length) 135{ 136 register u_int ptr; 137 register u_int len; 138 int hoplen; 139 const char *type; 140 141 if (length < 4) { 142 printf("[bad length %d]", length); 143 return; 144 } 145 printf(" TS{"); 146 hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; 147 if ((length - 4) & (hoplen-1)) 148 printf("[bad length %d]", length); 149 ptr = cp[2] - 1; 150 len = 0; 151 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) 152 printf("[bad ptr %d]", cp[2]); 153 switch (cp[3]&0xF) { 154 case IPOPT_TS_TSONLY: 155 printf("TSONLY"); 156 break; 157 case IPOPT_TS_TSANDADDR: 158 printf("TS+ADDR"); 159 break; 160 /* 161 * prespecified should really be 3, but some ones might send 2 162 * instead, and the IPOPT_TS_PRESPEC constant can apparently 163 * have both values, so we have to hard-code it here. 164 */ 165 166 case 2: 167 printf("PRESPEC2.0"); 168 break; 169 case 3: /* IPOPT_TS_PRESPEC */ 170 printf("PRESPEC"); 171 break; 172 default: 173 printf("[bad ts type %d]", cp[3]&0xF); 174 goto done; 175 } 176 177 type = " "; 178 for (len = 4; len < length; len += hoplen) { 179 if (ptr == len) 180 type = " ^ "; 181 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), 182 hoplen!=8 ? "" : ipaddr_string(&cp[len])); 183 type = " "; 184 } 185 186done: 187 printf("%s", ptr == len ? " ^ " : ""); 188 189 if (cp[3]>>4) 190 printf(" [%d hops not recorded]} ", cp[3]>>4); 191 else 192 printf("}"); 193} 194 195/* 196 * print IP options. 197 */ 198static void 199ip_optprint(register const u_char *cp, u_int length) 200{ 201 register u_int option_len; 202 203 for (; length > 0; cp += option_len, length -= option_len) { 204 u_int option_code; 205 206 TCHECK(*cp); 207 option_code = *cp; 208 209 if (option_code == IPOPT_NOP || 210 option_code == IPOPT_EOL) 211 option_len = 1; 212 213 else { 214 TCHECK(cp[1]); 215 option_len = cp[1]; 216 } 217 218 printf("%s (%u) len %u", 219 tok2str(ip_option_values,"unknown",option_code), 220 option_code, 221 option_len); 222 223 if (option_len < 2) 224 return; 225 226 TCHECK2(*cp, option_len); 227 228 switch (option_code) { 229 case IPOPT_EOL: 230 return; 231 232 case IPOPT_TS: 233 ip_printts(cp, option_len); 234 break; 235 236 case IPOPT_RR: /* fall through */ 237 case IPOPT_SSRR: 238 case IPOPT_LSRR: 239 ip_printroute( cp, option_len); 240 break; 241 242 case IPOPT_RA: 243 TCHECK(cp[3]); 244 if (EXTRACT_16BITS(&cp[2]) != 0) 245 printf("value %u", EXTRACT_16BITS(&cp[2])); 246 break; 247 248 case IPOPT_NOP: /* nothing to print - fall through */ 249 case IPOPT_SECURITY: 250 default: 251 break; 252 } 253 } 254 return; 255 256trunc: 257 printf("[|ip]"); 258} 259 260/* 261 * compute an IP header checksum. 262 * don't modifiy the packet. 263 */ 264u_short 265in_cksum(const u_short *addr, register u_int len, int csum) 266{ 267 int nleft = len; 268 const u_short *w = addr; 269 u_short answer; 270 int sum = csum; 271 272 /* 273 * Our algorithm is simple, using a 32 bit accumulator (sum), 274 * we add sequential 16 bit words to it, and at the end, fold 275 * back all the carry bits from the top 16 bits into the lower 276 * 16 bits. 277 */ 278 while (nleft > 1) { 279 sum += *w++; 280 nleft -= 2; 281 } 282 if (nleft == 1) 283 sum += htons(*(u_char *)w<<8); 284 285 /* 286 * add back carry outs from top 16 bits to low 16 bits 287 */ 288 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 289 sum += (sum >> 16); /* add carry */ 290 answer = ~sum; /* truncate to 16 bits */ 291 return (answer); 292} 293 294/* 295 * Given the host-byte-order value of the checksum field in a packet 296 * header, and the network-byte-order computed checksum of the data 297 * that the checksum covers (including the checksum itself), compute 298 * what the checksum field *should* have been. 299 */ 300u_int16_t 301in_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum) 302{ 303 u_int32_t shouldbe; 304 305 /* 306 * The value that should have gone into the checksum field 307 * is the negative of the value gotten by summing up everything 308 * *but* the checksum field. 309 * 310 * We can compute that by subtracting the value of the checksum 311 * field from the sum of all the data in the packet, and then 312 * computing the negative of that value. 313 * 314 * "sum" is the value of the checksum field, and "computed_sum" 315 * is the negative of the sum of all the data in the packets, 316 * so that's -(-computed_sum - sum), or (sum + computed_sum). 317 * 318 * All the arithmetic in question is one's complement, so the 319 * addition must include an end-around carry; we do this by 320 * doing the arithmetic in 32 bits (with no sign-extension), 321 * and then adding the upper 16 bits of the sum, which contain 322 * the carry, to the lower 16 bits of the sum, and then do it 323 * again in case *that* sum produced a carry. 324 * 325 * As RFC 1071 notes, the checksum can be computed without 326 * byte-swapping the 16-bit words; summing 16-bit words 327 * on a big-endian machine gives a big-endian checksum, which 328 * can be directly stuffed into the big-endian checksum fields 329 * in protocol headers, and summing words on a little-endian 330 * machine gives a little-endian checksum, which must be 331 * byte-swapped before being stuffed into a big-endian checksum 332 * field. 333 * 334 * "computed_sum" is a network-byte-order value, so we must put 335 * it in host byte order before subtracting it from the 336 * host-byte-order value from the header; the adjusted checksum 337 * will be in host byte order, which is what we'll return. 338 */ 339 shouldbe = sum; 340 shouldbe += ntohs(computed_sum); 341 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 342 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 343 return shouldbe; 344} 345 346#ifndef IP_MF 347#define IP_MF 0x2000 348#endif /* IP_MF */ 349#ifndef IP_DF 350#define IP_DF 0x4000 351#endif /* IP_DF */ 352#define IP_RES 0x8000 353 354static struct tok ip_frag_values[] = { 355 { IP_MF, "+" }, 356 { IP_DF, "DF" }, 357 { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */ 358 { 0, NULL } 359}; 360 361struct ip_print_demux_state { 362 const struct ip *ip; 363 const u_char *cp; 364 u_int len, off; 365 u_char nh; 366 int advance; 367}; 368 369static void 370ip_print_demux(netdissect_options *ndo, 371 struct ip_print_demux_state *ipds) 372{ 373 struct protoent *proto; 374 375again: 376 switch (ipds->nh) { 377 378 case IPPROTO_AH: 379 ipds->nh = *ipds->cp; 380 ipds->advance = ah_print(ipds->cp); 381 if (ipds->advance <= 0) 382 break; 383 ipds->cp += ipds->advance; 384 ipds->len -= ipds->advance; 385 goto again; 386 387 case IPPROTO_ESP: 388 { 389 int enh, padlen; 390 ipds->advance = esp_print(ndo, ipds->cp, ipds->len, 391 (const u_char *)ipds->ip, 392 &enh, &padlen); 393 if (ipds->advance <= 0) 394 break; 395 ipds->cp += ipds->advance; 396 ipds->len -= ipds->advance + padlen; 397 ipds->nh = enh & 0xff; 398 goto again; 399 } 400 401 case IPPROTO_IPCOMP: 402 { 403 int enh; 404 ipds->advance = ipcomp_print(ipds->cp, &enh); 405 if (ipds->advance <= 0) 406 break; 407 ipds->cp += ipds->advance; 408 ipds->len -= ipds->advance; 409 ipds->nh = enh & 0xff; 410 goto again; 411 } 412 413 case IPPROTO_SCTP: 414 sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len); 415 break; 416 417 case IPPROTO_TCP: 418 tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 419 (ipds->off &~ 0x6000)); 420 break; 421 422 case IPPROTO_UDP: 423 udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 424 (ipds->off &~ 0x6000)); 425 break; 426 427 case IPPROTO_ICMP: 428 /* pass on the MF bit plus the offset to detect fragments */ 429 icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 430 (ipds->off & 0x3fff)); 431 break; 432 433 case IPPROTO_PIGP: 434 /* 435 * XXX - the current IANA protocol number assignments 436 * page lists 9 as "any private interior gateway 437 * (used by Cisco for their IGRP)" and 88 as 438 * "EIGRP" from Cisco. 439 * 440 * Recent BSD <netinet/in.h> headers define 441 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88. 442 * We define IP_PROTO_PIGP as 9 and 443 * IP_PROTO_EIGRP as 88; those names better 444 * match was the current protocol number 445 * assignments say. 446 */ 447 igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); 448 break; 449 450 case IPPROTO_EIGRP: 451 eigrp_print(ipds->cp, ipds->len); 452 break; 453 454 case IPPROTO_ND: 455 ND_PRINT((ndo, " nd %d", ipds->len)); 456 break; 457 458 case IPPROTO_EGP: 459 egp_print(ipds->cp, ipds->len); 460 break; 461 462 case IPPROTO_OSPF: 463 ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); 464 break; 465 466 case IPPROTO_IGMP: 467 igmp_print(ipds->cp, ipds->len); 468 break; 469 470 case IPPROTO_IPV4: 471 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ 472 ip_print(gndo, ipds->cp, ipds->len); 473 if (! vflag) { 474 ND_PRINT((ndo, " (ipip-proto-4)")); 475 return; 476 } 477 break; 478 479#ifdef INET6 480 case IPPROTO_IPV6: 481 /* ip6-in-ip encapsulation */ 482 ip6_print(ipds->cp, ipds->len); 483 break; 484#endif /*INET6*/ 485 486 case IPPROTO_RSVP: 487 rsvp_print(ipds->cp, ipds->len); 488 break; 489 490 case IPPROTO_GRE: 491 /* do it */ 492 gre_print(ipds->cp, ipds->len); 493 break; 494 495 case IPPROTO_MOBILE: 496 mobile_print(ipds->cp, ipds->len); 497 break; 498 499 case IPPROTO_PIM: 500 pim_print(ipds->cp, ipds->len); 501 break; 502 503 case IPPROTO_VRRP: 504 vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl); 505 break; 506 507 default: 508 if ((proto = getprotobynumber(ipds->nh)) != NULL) 509 ND_PRINT((ndo, " %s", proto->p_name)); 510 else 511 ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); 512 ND_PRINT((ndo, " %d", ipds->len)); 513 break; 514 } 515} 516 517void 518ip_print_inner(netdissect_options *ndo, 519 const u_char *bp, 520 u_int length, u_int nh, 521 const u_char *bp2) 522{ 523 struct ip_print_demux_state ipd; 524 525 ipd.ip = (const struct ip *)bp2; 526 ipd.cp = bp; 527 ipd.len = length; 528 ipd.off = 0; 529 ipd.nh = nh; 530 ipd.advance = 0; 531 532 ip_print_demux(ndo, &ipd); 533} 534 535 536/* 537 * print an IP datagram. 538 */ 539void 540ip_print(netdissect_options *ndo, 541 const u_char *bp, 542 u_int length) 543{ 544 struct ip_print_demux_state ipd; 545 struct ip_print_demux_state *ipds=&ipd; 546 const u_char *ipend; 547 u_int hlen; 548 u_int16_t sum, ip_sum; 549 struct protoent *proto; 550 551 ipds->ip = (const struct ip *)bp; 552 if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ 553 printf("IP%u ", IP_V(ipds->ip)); 554 if (IP_V(ipds->ip) == 6) 555 printf(", wrong link-layer encapsulation"); 556 } 557 else if (!eflag) 558 printf("IP "); 559 560 if ((u_char *)(ipds->ip + 1) > snapend) { 561 printf("[|ip]"); 562 return; 563 } 564 if (length < sizeof (struct ip)) { 565 (void)printf("truncated-ip %u", length); 566 return; 567 } 568 hlen = IP_HL(ipds->ip) * 4; 569 if (hlen < sizeof (struct ip)) { 570 (void)printf("bad-hlen %u", hlen); 571 return; 572 } 573 574 ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); 575 if (length < ipds->len) 576 (void)printf("truncated-ip - %u bytes missing! ", 577 ipds->len - length); 578 if (ipds->len < hlen) { 579#ifdef GUESS_TSO 580 if (ipds->len) { 581 (void)printf("bad-len %u", ipds->len); 582 return; 583 } 584 else { 585 /* we guess that it is a TSO send */ 586 ipds->len = length; 587 } 588#else 589 (void)printf("bad-len %u", ipds->len); 590 return; 591#endif /* GUESS_TSO */ 592 } 593 594 /* 595 * Cut off the snapshot length to the end of the IP payload. 596 */ 597 ipend = bp + ipds->len; 598 if (ipend < snapend) 599 snapend = ipend; 600 601 ipds->len -= hlen; 602 603 ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); 604 605 if (vflag) { 606 (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos); 607 /* ECN bits */ 608 if (ipds->ip->ip_tos & 0x03) { 609 switch (ipds->ip->ip_tos & 0x03) { 610 case 1: 611 (void)printf(",ECT(1)"); 612 break; 613 case 2: 614 (void)printf(",ECT(0)"); 615 break; 616 case 3: 617 (void)printf(",CE"); 618 } 619 } 620 621 if (ipds->ip->ip_ttl >= 1) 622 (void)printf(", ttl %3u", ipds->ip->ip_ttl); 623 624 /* 625 * for the firewall guys, print id, offset. 626 * On all but the last stick a "+" in the flags portion. 627 * For unfragmented datagrams, note the don't fragment flag. 628 */ 629 630 (void)printf(", id %u, offset %u, flags [%s], proto: %s (%u)", 631 EXTRACT_16BITS(&ipds->ip->ip_id), 632 (ipds->off & 0x1fff) * 8, 633 bittok2str(ip_frag_values, "none", ipds->off&0xe000 ), 634 tok2str(ipproto_values,"unknown",ipds->ip->ip_p), 635 ipds->ip->ip_p); 636 637 (void)printf(", length: %u", EXTRACT_16BITS(&ipds->ip->ip_len)); 638 639 if ((hlen - sizeof(struct ip)) > 0) { 640 printf(", options ( "); 641 ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); 642 printf(" )"); 643 } 644 645 if ((u_char *)ipds->ip + hlen <= snapend) { 646 sum = in_cksum((const u_short *)ipds->ip, hlen, 0); 647 if (sum != 0) { 648 ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); 649 (void)printf(", bad cksum %x (->%x)!", ip_sum, 650 in_cksum_shouldbe(ip_sum, sum)); 651 } 652 } 653 654 printf(") "); 655 } 656 657 /* 658 * If this is fragment zero, hand it to the next higher 659 * level protocol. 660 */ 661 if ((ipds->off & 0x1fff) == 0) { 662 ipds->cp = (const u_char *)ipds->ip + hlen; 663 ipds->nh = ipds->ip->ip_p; 664 665 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && 666 ipds->nh != IPPROTO_SCTP) { 667 (void)printf("%s > %s: ", 668 ipaddr_string(&ipds->ip->ip_src), 669 ipaddr_string(&ipds->ip->ip_dst)); 670 } 671 ip_print_demux(ndo, ipds); 672 } else { 673 /* Ultra quiet now means that all this stuff should be suppressed */ 674 if (qflag > 1) return; 675 676 /* 677 * if this isn't the first frag, we're missing the 678 * next level protocol header. print the ip addr 679 * and the protocol. 680 */ 681 if (ipds->off & 0x1fff) { 682 (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src), 683 ipaddr_string(&ipds->ip->ip_dst)); 684 if ((proto = getprotobynumber(ipds->ip->ip_p)) != NULL) 685 (void)printf(" %s", proto->p_name); 686 else 687 (void)printf(" ip-proto-%d", ipds->ip->ip_p); 688 } 689 } 690} 691 692void 693ipN_print(register const u_char *bp, register u_int length) 694{ 695 struct ip *ip, hdr; 696 697 ip = (struct ip *)bp; 698 if (length < 4) { 699 (void)printf("truncated-ip %d", length); 700 return; 701 } 702 memcpy (&hdr, (char *)ip, 4); 703 switch (IP_V(&hdr)) { 704 case 4: 705 ip_print (gndo, bp, length); 706 return; 707#ifdef INET6 708 case 6: 709 ip6_print (bp, length); 710 return; 711#endif 712 default: 713 (void)printf("unknown ip %d", IP_V(&hdr)); 714 return; 715 } 716} 717 718/* 719 * Local Variables: 720 * c-style: whitesmith 721 * c-basic-offset: 8 722 * End: 723 */ 724 725 726