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[] = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.79 1999/12/22 06:27:21 itojun Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <sys/param.h> 34 #include <sys/time.h> 35 #include <sys/socket.h> 36 37 #include <netinet/in.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.h> 40 #include <netinet/ip_var.h> 41 #include <netinet/udp.h> 42 #include <netinet/udp_var.h> 43 #include <netinet/tcp.h> 44 45 #ifdef HAVE_MALLOC_H 46 #include <malloc.h> 47 #endif 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 53 #include "addrtoname.h" 54 #include "interface.h" 55 #include "extract.h" /* must come after interface.h */ 56 57 /* Compatibility */ 58 #ifndef IPPROTO_ND 59 #define IPPROTO_ND 77 60 #endif 61 62 #ifndef IN_CLASSD 63 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) 64 #endif 65 66 /* (following from ipmulti/mrouted/prune.h) */ 67 68 /* 69 * The packet format for a traceroute request. 70 */ 71 struct tr_query { 72 u_int tr_src; /* traceroute source */ 73 u_int tr_dst; /* traceroute destination */ 74 u_int tr_raddr; /* traceroute response address */ 75 u_int tr_rttlqid; /* response ttl and qid */ 76 }; 77 78 #define TR_GETTTL(x) (int)(((x) >> 24) & 0xff) 79 #define TR_GETQID(x) ((x) & 0x00ffffff) 80 81 /* 82 * Traceroute response format. A traceroute response has a tr_query at the 83 * beginning, followed by one tr_resp for each hop taken. 84 */ 85 struct tr_resp { 86 u_int tr_qarr; /* query arrival time */ 87 u_int tr_inaddr; /* incoming interface address */ 88 u_int tr_outaddr; /* outgoing interface address */ 89 u_int tr_rmtaddr; /* parent address in source tree */ 90 u_int tr_vifin; /* input packet count on interface */ 91 u_int tr_vifout; /* output packet count on interface */ 92 u_int tr_pktcnt; /* total incoming packets for src-grp */ 93 u_char tr_rproto; /* routing proto deployed on router */ 94 u_char tr_fttl; /* ttl required to forward on outvif */ 95 u_char tr_smask; /* subnet mask for src addr */ 96 u_char tr_rflags; /* forwarding error codes */ 97 }; 98 99 /* defs within mtrace */ 100 #define TR_QUERY 1 101 #define TR_RESP 2 102 103 /* fields for tr_rflags (forwarding error codes) */ 104 #define TR_NO_ERR 0 105 #define TR_WRONG_IF 1 106 #define TR_PRUNED 2 107 #define TR_OPRUNED 3 108 #define TR_SCOPED 4 109 #define TR_NO_RTE 5 110 #define TR_NO_FWD 7 111 #define TR_NO_SPACE 0x81 112 #define TR_OLD_ROUTER 0x82 113 114 /* fields for tr_rproto (routing protocol) */ 115 #define TR_PROTO_DVMRP 1 116 #define TR_PROTO_MOSPF 2 117 #define TR_PROTO_PIM 3 118 #define TR_PROTO_CBT 4 119 120 static void print_mtrace(register const u_char *bp, register u_int len) 121 { 122 register struct tr_query *tr = (struct tr_query *)(bp + 8); 123 124 printf("mtrace %lu: %s to %s reply-to %s", 125 (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)), 126 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 127 ipaddr_string(&tr->tr_raddr)); 128 if (IN_CLASSD(ntohl(tr->tr_raddr))) 129 printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid))); 130 } 131 132 static void print_mresp(register const u_char *bp, register u_int len) 133 { 134 register struct tr_query *tr = (struct tr_query *)(bp + 8); 135 136 printf("mresp %lu: %s to %s reply-to %s", 137 (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)), 138 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 139 ipaddr_string(&tr->tr_raddr)); 140 if (IN_CLASSD(ntohl(tr->tr_raddr))) 141 printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid))); 142 } 143 144 static void 145 igmp_print(register const u_char *bp, register u_int len, 146 register const u_char *bp2) 147 { 148 register const struct ip *ip; 149 150 ip = (const struct ip *)bp2; 151 (void)printf("%s > %s: ", 152 ipaddr_string(&ip->ip_src), 153 ipaddr_string(&ip->ip_dst)); 154 155 if (qflag) { 156 (void)printf("igmp"); 157 return; 158 } 159 160 TCHECK2(bp[0], 8); 161 switch (bp[0]) { 162 case 0x11: 163 (void)printf("igmp %s query", bp[1] ? "v2" : "v1"); 164 if (bp[1] && bp[1] != 100) 165 (void)printf(" [intvl %d]", bp[1]); 166 (void)printf("igmp query"); 167 if (EXTRACT_32BITS(&bp[4])) 168 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4])); 169 if (len != 8) 170 (void)printf(" [len %d]", len); 171 break; 172 case 0x12: 173 case 0x16: 174 (void)printf("igmp %s report %s", 175 (bp[0] & 0x0f) == 6 ? "v2" : "v1", 176 ipaddr_string(&bp[4])); 177 if (len != 8) 178 (void)printf(" [len %d]", len); 179 if (bp[1]) 180 (void)printf(" [b1=0x%x]", bp[1]); 181 break; 182 case 0x17: 183 (void)printf("igmp leave %s", ipaddr_string(&bp[4])); 184 if (len != 8) 185 (void)printf(" [len %d]", len); 186 if (bp[1]) 187 (void)printf(" [b1=0x%x]", bp[1]); 188 break; 189 case 0x13: 190 (void)printf("igmp dvmrp"); 191 if (len < 8) 192 (void)printf(" [len %d]", len); 193 else 194 dvmrp_print(bp, len); 195 break; 196 case 0x14: 197 (void)printf("igmp pimv1"); 198 pimv1_print(bp, len); 199 break; 200 case 0x1e: 201 print_mresp(bp, len); 202 break; 203 case 0x1f: 204 print_mtrace(bp, len); 205 break; 206 default: 207 (void)printf("igmp-%d", bp[0] & 0xf); 208 if (bp[1]) 209 (void)printf(" [b1=0x%02x]", bp[1]); 210 break; 211 } 212 213 if (vflag && TTEST2(bp[0], len)) { 214 /* Check the IGMP checksum */ 215 if (in_cksum((const u_short*)bp, len, 0)) 216 printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2])); 217 } 218 return; 219 trunc: 220 fputs("[|igmp]", stdout); 221 } 222 223 /* 224 * print the recorded route in an IP RR, LSRR or SSRR option. 225 */ 226 static void 227 ip_printroute(const char *type, register const u_char *cp, u_int length) 228 { 229 register u_int ptr = cp[2] - 1; 230 register u_int len; 231 232 printf(" %s{", type); 233 if ((length + 1) & 3) 234 printf(" [bad length %d]", length); 235 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 236 printf(" [bad ptr %d]", cp[2]); 237 238 type = ""; 239 for (len = 3; len < length; len += 4) { 240 if (ptr == len) 241 type = "#"; 242 printf("%s%s", type, ipaddr_string(&cp[len])); 243 type = " "; 244 } 245 printf("%s}", ptr == len? "#" : ""); 246 } 247 248 static void 249 ip_printts(register const u_char *cp, u_int length) 250 { 251 register u_int ptr = cp[2] - 1; 252 register u_int len = 0; 253 int hoplen; 254 char *type; 255 256 printf(" TS{"); 257 hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; 258 if ((length - 4) & (hoplen-1)) 259 printf("[bad length %d]", length); 260 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) 261 printf("[bad ptr %d]", cp[2]); 262 switch (cp[3]&0xF) { 263 case IPOPT_TS_TSONLY: 264 printf("TSONLY"); 265 break; 266 case IPOPT_TS_TSANDADDR: 267 printf("TS+ADDR"); 268 break; 269 /* 270 * prespecified should really be 3, but some ones might send 2 271 * instead, and the IPOPT_TS_PRESPEC constant can apparently 272 * have both values, so we have to hard-code it here. 273 */ 274 275 case 2: 276 printf("PRESPEC2.0"); 277 break; 278 case 3: /* IPOPT_TS_PRESPEC */ 279 printf("PRESPEC"); 280 break; 281 default: 282 printf("[bad ts type %d]", cp[3]&0xF); 283 goto done; 284 } 285 286 type = " "; 287 for (len = 4; len < length; len += hoplen) { 288 if (ptr == len) 289 type = " ^ "; 290 printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), 291 hoplen!=8 ? "" : ipaddr_string(&cp[len])); 292 type = " "; 293 } 294 295 done: 296 printf("%s", ptr == len ? " ^ " : ""); 297 298 if (cp[3]>>4) 299 printf(" [%d hops not recorded]} ", cp[3]>>4); 300 else 301 printf("}"); 302 } 303 304 /* 305 * print IP options. 306 */ 307 static void 308 ip_optprint(register const u_char *cp, u_int length) 309 { 310 register u_int len; 311 312 for (; length > 0; cp += len, length -= len) { 313 int tt = *cp; 314 315 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; 316 if (len <= 0) { 317 printf("[|ip op len %d]", len); 318 return; 319 } 320 if (&cp[1] >= snapend || cp + len > snapend) { 321 printf("[|ip]"); 322 return; 323 } 324 switch (tt) { 325 326 case IPOPT_EOL: 327 printf(" EOL"); 328 if (length > 1) 329 printf("-%d", length - 1); 330 return; 331 332 case IPOPT_NOP: 333 printf(" NOP"); 334 break; 335 336 case IPOPT_TS: 337 ip_printts(cp, len); 338 break; 339 340 #ifndef IPOPT_SECURITY 341 #define IPOPT_SECURITY 130 342 #endif /* IPOPT_SECURITY */ 343 case IPOPT_SECURITY: 344 printf(" SECURITY{%d}", len); 345 break; 346 347 case IPOPT_RR: 348 ip_printroute("RR", cp, len); 349 break; 350 351 case IPOPT_SSRR: 352 ip_printroute("SSRR", cp, len); 353 break; 354 355 case IPOPT_LSRR: 356 ip_printroute("LSRR", cp, len); 357 break; 358 359 #ifndef IPOPT_RA 360 #define IPOPT_RA 148 /* router alert */ 361 #endif 362 case IPOPT_RA: 363 printf(" RA"); 364 if (len != 4) 365 printf("{%d}", len); 366 else if (cp[2] || cp[3]) 367 printf("%d.%d", cp[2], cp[3]); 368 break; 369 370 default: 371 printf(" IPOPT-%d{%d}", cp[0], len); 372 break; 373 } 374 } 375 } 376 377 /* 378 * compute an IP header checksum. 379 * don't modifiy the packet. 380 */ 381 u_short 382 in_cksum(const u_short *addr, register int len, u_short csum) 383 { 384 int nleft = len; 385 const u_short *w = addr; 386 u_short answer; 387 int sum = csum; 388 389 /* 390 * Our algorithm is simple, using a 32 bit accumulator (sum), 391 * we add sequential 16 bit words to it, and at the end, fold 392 * back all the carry bits from the top 16 bits into the lower 393 * 16 bits. 394 */ 395 while (nleft > 1) { 396 sum += *w++; 397 nleft -= 2; 398 } 399 if (nleft == 1) 400 sum += htons(*(u_char *)w<<8); 401 402 /* 403 * add back carry outs from top 16 bits to low 16 bits 404 */ 405 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 406 sum += (sum >> 16); /* add carry */ 407 answer = ~sum; /* truncate to 16 bits */ 408 return (answer); 409 } 410 411 /* 412 * print an IP datagram. 413 */ 414 void 415 ip_print(register const u_char *bp, register u_int length) 416 { 417 register const struct ip *ip; 418 register u_int hlen, len, len0, off; 419 register const u_char *cp; 420 u_char nh; 421 int advance; 422 423 ip = (const struct ip *)bp; 424 #ifdef LBL_ALIGN 425 /* 426 * If the IP header is not aligned, copy into abuf. 427 * This will never happen with BPF. It does happen raw packet 428 * dumps from -r. 429 */ 430 if ((long)ip & 3) { 431 static u_char *abuf = NULL; 432 static int didwarn = 0; 433 434 if (abuf == NULL) { 435 abuf = (u_char *)malloc(snaplen); 436 if (abuf == NULL) 437 error("ip_print: malloc"); 438 } 439 memcpy((char *)abuf, (char *)ip, min(length, snaplen)); 440 snapend += abuf - (u_char *)ip; 441 packetp = abuf; 442 ip = (struct ip *)abuf; 443 /* We really want libpcap to give us aligned packets */ 444 if (!didwarn) { 445 warning("compensating for unaligned libpcap packets"); 446 ++didwarn; 447 } 448 } 449 #endif 450 if ((u_char *)(ip + 1) > snapend) { 451 printf("[|ip]"); 452 return; 453 } 454 if (length < sizeof (struct ip)) { 455 (void)printf("truncated-ip %d", length); 456 return; 457 } 458 hlen = ip->ip_hl * 4; 459 460 len = ntohs(ip->ip_len); 461 if (length < len) 462 (void)printf("truncated-ip - %d bytes missing!", 463 len - length); 464 len -= hlen; 465 len0 = len; 466 467 /* 468 * If this is fragment zero, hand it to the next higher 469 * level protocol. 470 */ 471 off = ntohs(ip->ip_off); 472 if ((off & 0x1fff) == 0) { 473 cp = (const u_char *)ip + hlen; 474 nh = ip->ip_p; 475 476 if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) { 477 (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src), 478 ipaddr_string(&ip->ip_dst)); 479 } 480 again: 481 switch (nh) { 482 483 #ifndef IPPROTO_AH 484 #define IPPROTO_AH 51 485 #endif 486 case IPPROTO_AH: 487 nh = *cp; 488 advance = ah_print(cp, (const u_char *)ip); 489 cp += advance; 490 len -= advance; 491 goto again; 492 493 #ifndef IPPROTO_ESP 494 #define IPPROTO_ESP 50 495 #endif 496 case IPPROTO_ESP: 497 { 498 int enh; 499 advance = esp_print(cp, (const u_char *)ip, &enh); 500 cp += advance; 501 len -= advance; 502 if (enh < 0) 503 break; 504 nh = enh & 0xff; 505 goto again; 506 } 507 508 #ifndef IPPROTO_IPCOMP 509 #define IPPROTO_IPCOMP 108 510 #endif 511 case IPPROTO_IPCOMP: 512 { 513 int enh; 514 advance = ipcomp_print(cp, (const u_char *)ip, &enh); 515 cp += advance; 516 len -= advance; 517 if (enh < 0) 518 break; 519 nh = enh & 0xff; 520 goto again; 521 } 522 523 case IPPROTO_TCP: 524 tcp_print(cp, len, (const u_char *)ip); 525 break; 526 527 case IPPROTO_UDP: 528 udp_print(cp, len, (const u_char *)ip); 529 break; 530 531 case IPPROTO_ICMP: 532 icmp_print(cp, len, (const u_char *)ip); 533 break; 534 535 #ifndef IPPROTO_IGRP 536 #define IPPROTO_IGRP 9 537 #endif 538 case IPPROTO_IGRP: 539 igrp_print(cp, len, (const u_char *)ip); 540 break; 541 542 case IPPROTO_ND: 543 #if 0 544 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 545 ipaddr_string(&ip->ip_dst)); 546 #endif 547 (void)printf(" nd %d", len); 548 break; 549 550 case IPPROTO_EGP: 551 egp_print(cp, len, (const u_char *)ip); 552 break; 553 554 #ifndef IPPROTO_OSPF 555 #define IPPROTO_OSPF 89 556 #endif 557 case IPPROTO_OSPF: 558 ospf_print(cp, len, (const u_char *)ip); 559 break; 560 561 #ifndef IPPROTO_IGMP 562 #define IPPROTO_IGMP 2 563 #endif 564 case IPPROTO_IGMP: 565 igmp_print(cp, len, (const u_char *)ip); 566 break; 567 568 case 4: 569 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ 570 #if 0 571 if (vflag) 572 (void)printf("%s > %s: ", 573 ipaddr_string(&ip->ip_src), 574 ipaddr_string(&ip->ip_dst)); 575 #endif 576 ip_print(cp, len); 577 if (! vflag) { 578 printf(" (ipip)"); 579 return; 580 } 581 break; 582 583 #ifdef INET6 584 #ifndef IP6PROTO_ENCAP 585 #define IP6PROTO_ENCAP 41 586 #endif 587 case IP6PROTO_ENCAP: 588 /* ip6-in-ip encapsulation */ 589 #if 0 590 if (vflag) 591 (void)printf("%s > %s: ", 592 ipaddr_string(&ip->ip_src), 593 ipaddr_string(&ip->ip_dst)); 594 #endif 595 ip6_print(cp, len); 596 if (! vflag) { 597 printf(" (encap)"); 598 return; 599 } 600 break; 601 #endif /*INET6*/ 602 603 604 #ifndef IPPROTO_GRE 605 #define IPPROTO_GRE 47 606 #endif 607 case IPPROTO_GRE: 608 if (vflag) 609 (void)printf("gre %s > %s: ", 610 ipaddr_string(&ip->ip_src), 611 ipaddr_string(&ip->ip_dst)); 612 /* do it */ 613 gre_print(cp, len); 614 if (! vflag) { 615 printf(" (gre encap)"); 616 return; 617 } 618 break; 619 620 #ifndef IPPROTO_MOBILE 621 #define IPPROTO_MOBILE 55 622 #endif 623 case IPPROTO_MOBILE: 624 if (vflag) 625 (void)printf("mobile %s > %s: ", 626 ipaddr_string(&ip->ip_src), 627 ipaddr_string(&ip->ip_dst)); 628 mobile_print(cp, len); 629 if (! vflag) { 630 printf(" (mobile encap)"); 631 return; 632 } 633 break; 634 635 #ifndef IPPROTO_PIM 636 #define IPPROTO_PIM 103 637 #endif 638 case IPPROTO_PIM: 639 pim_print(cp, len); 640 break; 641 642 default: 643 #if 0 644 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 645 ipaddr_string(&ip->ip_dst)); 646 #endif 647 (void)printf(" ip-proto-%d %d", nh, len); 648 break; 649 } 650 } 651 652 /* Ultra quiet now means that all this stuff should be suppressed */ 653 /* res 3-Nov-98 */ 654 if (qflag > 1) return; 655 656 657 /* 658 * for fragmented datagrams, print id:size@offset. On all 659 * but the last stick a "+". For unfragmented datagrams, note 660 * the don't fragment flag. 661 */ 662 len = len0; /* get the original length */ 663 if (off & 0x3fff) { 664 /* 665 * if this isn't the first frag, we're missing the 666 * next level protocol header. print the ip addr. 667 */ 668 if (off & 0x1fff) 669 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 670 ipaddr_string(&ip->ip_dst)); 671 #ifndef IP_MF 672 #define IP_MF 0x2000 673 #endif /* IP_MF */ 674 #ifndef IP_DF 675 #define IP_DF 0x4000 676 #endif /* IP_DF */ 677 (void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len, 678 (off & 0x1fff) * 8, 679 (off & IP_MF)? "+" : ""); 680 681 } else if (off & IP_DF) 682 (void)printf(" (DF)"); 683 684 if (ip->ip_tos) { 685 (void)printf(" [tos 0x%x", (int)ip->ip_tos); 686 /* ECN bits */ 687 if (ip->ip_tos&0x02) { 688 (void)printf(",ECT"); 689 if (ip->ip_tos&0x01) 690 (void)printf(",CE"); 691 } 692 (void)printf("] "); 693 } 694 695 if (ip->ip_ttl <= 1) 696 (void)printf(" [ttl %d]", (int)ip->ip_ttl); 697 698 if (vflag) { 699 int sum; 700 char *sep = ""; 701 702 printf(" ("); 703 if (ip->ip_ttl > 1) { 704 (void)printf("%sttl %d", sep, (int)ip->ip_ttl); 705 sep = ", "; 706 } 707 if ((off & 0x3fff) == 0) { 708 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); 709 sep = ", "; 710 } 711 if ((u_char *)ip + hlen <= snapend) { 712 sum = in_cksum((const u_short *)ip, hlen, 0); 713 if (sum != 0) { 714 (void)printf("%sbad cksum %x!", sep, 715 ntohs(ip->ip_sum)); 716 sep = ", "; 717 } 718 } 719 if ((hlen -= sizeof(struct ip)) > 0) { 720 (void)printf("%soptlen=%d", sep, hlen); 721 ip_optprint((u_char *)(ip + 1), hlen); 722 } 723 printf(")"); 724 } 725 } 726