1 /* $OpenBSD: print-ip.c,v 1.36 2010/01/12 06:10:33 naddy Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #include <sys/param.h> 25 #include <sys/time.h> 26 #include <sys/socket.h> 27 28 #include <netinet/in.h> 29 #include <netinet/in_systm.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip_var.h> 32 #include <netinet/udp.h> 33 #include <netinet/udp_var.h> 34 #include <netinet/tcp.h> 35 #include <netinet/tcpip.h> 36 37 #include <inttypes.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "addrtoname.h" 44 #include "interface.h" 45 #include "extract.h" /* must come after interface.h */ 46 47 /* Compatibility */ 48 #ifndef IPPROTO_ND 49 #define IPPROTO_ND 77 50 #endif 51 52 #ifndef IN_CLASSD 53 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) 54 #endif 55 56 /* Definitions required for ECN 57 for use if the OS running tcpdump does not have ECN */ 58 #ifndef IPTOS_ECT 59 #define IPTOS_ECT 0x02 /* ECN Capable Transport in IP header*/ 60 #endif 61 #ifndef IPTOS_CE 62 #define IPTOS_CE 0x01 /* ECN Cong. Experienced in IP header*/ 63 #endif 64 65 /* (following from ipmulti/mrouted/prune.h) */ 66 67 /* 68 * The packet format for a traceroute request. 69 */ 70 struct tr_query { 71 u_int tr_src; /* traceroute source */ 72 u_int tr_dst; /* traceroute destination */ 73 u_int tr_raddr; /* traceroute response address */ 74 #if BYTE_ORDER == BIG_ENDIAN 75 struct { 76 u_int ttl : 8; /* traceroute response ttl */ 77 u_int qid : 24; /* traceroute query id */ 78 } q; 79 #else 80 struct { 81 u_int qid : 24; /* traceroute query id */ 82 u_int ttl : 8; /* traceroute response ttl */ 83 } q; 84 #endif 85 }; 86 87 #define tr_rttl q.ttl 88 #define tr_qid q.qid 89 90 /* 91 * Traceroute response format. A traceroute response has a tr_query at the 92 * beginning, followed by one tr_resp for each hop taken. 93 */ 94 struct tr_resp { 95 u_int tr_qarr; /* query arrival time */ 96 u_int tr_inaddr; /* incoming interface address */ 97 u_int tr_outaddr; /* outgoing interface address */ 98 u_int tr_rmtaddr; /* parent address in source tree */ 99 u_int tr_vifin; /* input packet count on interface */ 100 u_int tr_vifout; /* output packet count on interface */ 101 u_int tr_pktcnt; /* total incoming packets for src-grp */ 102 u_char tr_rproto; /* routing proto deployed on router */ 103 u_char tr_fttl; /* ttl required to forward on outvif */ 104 u_char tr_smask; /* subnet mask for src addr */ 105 u_char tr_rflags; /* forwarding error codes */ 106 }; 107 108 /* defs within mtrace */ 109 #define TR_QUERY 1 110 #define TR_RESP 2 111 112 /* fields for tr_rflags (forwarding error codes) */ 113 #define TR_NO_ERR 0 114 #define TR_WRONG_IF 1 115 #define TR_PRUNED 2 116 #define TR_OPRUNED 3 117 #define TR_SCOPED 4 118 #define TR_NO_RTE 5 119 #define TR_NO_FWD 7 120 #define TR_NO_SPACE 0x81 121 #define TR_OLD_ROUTER 0x82 122 123 /* fields for tr_rproto (routing protocol) */ 124 #define TR_PROTO_DVMRP 1 125 #define TR_PROTO_MOSPF 2 126 #define TR_PROTO_PIM 3 127 #define TR_PROTO_CBT 4 128 129 static void print_mtrace(register const u_char *bp, register u_int len) 130 { 131 register struct tr_query *tr = (struct tr_query *)(bp + 8); 132 133 printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid, 134 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 135 ipaddr_string(&tr->tr_raddr)); 136 if (IN_CLASSD(ntohl(tr->tr_raddr))) 137 printf(" with-ttl %d", tr->tr_rttl); 138 } 139 140 static void print_mresp(register const u_char *bp, register u_int len) 141 { 142 register struct tr_query *tr = (struct tr_query *)(bp + 8); 143 144 printf("mresp %d: %s to %s reply-to %s", tr->tr_qid, 145 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 146 ipaddr_string(&tr->tr_raddr)); 147 if (IN_CLASSD(ntohl(tr->tr_raddr))) 148 printf(" with-ttl %d", tr->tr_rttl); 149 } 150 151 static void 152 igmp_print(register const u_char *bp, register u_int len, 153 register const u_char *bp2) 154 { 155 register const struct ip *ip; 156 157 ip = (const struct ip *)bp2; 158 (void)printf("%s > %s: ", 159 ipaddr_string(&ip->ip_src), 160 ipaddr_string(&ip->ip_dst)); 161 162 TCHECK2(bp[0], 8); 163 switch (bp[0]) { 164 case 0x11: 165 (void)printf("igmp query"); 166 if (*(int *)&bp[4]) 167 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4])); 168 if (len != 8) 169 (void)printf(" [len %d]", len); 170 break; 171 case 0x12: 172 (void)printf("igmp report %s", ipaddr_string(&bp[4])); 173 if (len != 8) 174 (void)printf(" [len %d]", len); 175 break; 176 case 0x16: 177 (void)printf("igmp nreport %s", ipaddr_string(&bp[4])); 178 break; 179 case 0x17: 180 (void)printf("igmp leave %s", ipaddr_string(&bp[4])); 181 break; 182 case 0x13: 183 (void)printf("igmp dvmrp"); 184 if (len < 8) 185 (void)printf(" [len %d]", len); 186 else 187 dvmrp_print(bp, len); 188 break; 189 case 0x14: 190 (void)printf("igmp pim"); 191 pim_print(bp, len); 192 break; 193 case 0x1e: 194 print_mresp(bp, len); 195 break; 196 case 0x1f: 197 print_mtrace(bp, len); 198 break; 199 default: 200 (void)printf("igmp-%d", bp[0] & 0xf); 201 break; 202 } 203 if ((bp[0] >> 4) != 1) 204 (void)printf(" [v%d]", bp[0] >> 4); 205 206 TCHECK2(bp[0], len); 207 if (vflag) { 208 /* Check the IGMP checksum */ 209 u_int32_t sum = 0; 210 int count; 211 const u_short *sp = (u_short *)bp; 212 213 for (count = len / 2; --count >= 0; ) 214 sum += *sp++; 215 if (len & 1) 216 sum += ntohs(*(u_char *) sp << 8); 217 while (sum >> 16) 218 sum = (sum & 0xffff) + (sum >> 16); 219 sum = 0xffff & ~sum; 220 if (sum != 0) 221 printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2])); 222 } 223 return; 224 trunc: 225 fputs("[|igmp]", stdout); 226 } 227 228 /* 229 * print the recorded route in an IP RR, LSRR or SSRR option. 230 */ 231 static void 232 ip_printroute(const char *type, register const u_char *cp, u_int length) 233 { 234 register u_int ptr = cp[2] - 1; 235 register u_int len; 236 237 printf(" %s{", type); 238 if ((length + 1) & 3) 239 printf(" [bad length %d]", length); 240 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 241 printf(" [bad ptr %d]", cp[2]); 242 243 type = ""; 244 for (len = 3; len < length; len += 4) { 245 if (ptr == len) 246 type = "#"; 247 printf("%s%s", type, ipaddr_string(&cp[len])); 248 type = " "; 249 } 250 printf("%s}", ptr == len? "#" : ""); 251 } 252 253 /* 254 * print IP options. 255 */ 256 static void 257 ip_optprint(register const u_char *cp, u_int length) 258 { 259 register u_int len; 260 int tt; 261 262 for (; length > 0; cp += len, length -= len) { 263 TCHECK(cp[1]); 264 tt = *cp; 265 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; 266 if (len <= 0) { 267 printf("[|ip op len %d]", len); 268 return; 269 } 270 if (&cp[1] >= snapend || cp + len > snapend) { 271 printf("[|ip]"); 272 return; 273 } 274 switch (tt) { 275 276 case IPOPT_EOL: 277 printf(" EOL"); 278 if (length > 1) 279 printf("-%d", length - 1); 280 return; 281 282 case IPOPT_NOP: 283 printf(" NOP"); 284 break; 285 286 case IPOPT_TS: 287 printf(" TS{%d}", len); 288 break; 289 290 case IPOPT_SECURITY: 291 printf(" SECURITY{%d}", len); 292 break; 293 294 case IPOPT_RR: 295 printf(" RR{%d}=", len); 296 ip_printroute("RR", cp, len); 297 break; 298 299 case IPOPT_SSRR: 300 ip_printroute("SSRR", cp, len); 301 break; 302 303 case IPOPT_LSRR: 304 ip_printroute("LSRR", cp, len); 305 break; 306 307 default: 308 printf(" IPOPT-%d{%d}", cp[0], len); 309 break; 310 } 311 } 312 return; 313 314 trunc: 315 printf("[|ip]"); 316 } 317 318 /* 319 * compute an IP header checksum. 320 * don't modifiy the packet. 321 */ 322 u_short 323 in_cksum(const u_short *addr, register int len, int csum) 324 { 325 int nleft = len; 326 const u_short *w = addr; 327 u_short answer; 328 int sum = csum; 329 330 /* 331 * Our algorithm is simple, using a 32 bit accumulator (sum), 332 * we add sequential 16 bit words to it, and at the end, fold 333 * back all the carry bits from the top 16 bits into the lower 334 * 16 bits. 335 */ 336 while (nleft > 1) { 337 sum += *w++; 338 nleft -= 2; 339 } 340 if (nleft == 1) 341 sum += htons(*(u_char *)w<<8); 342 343 /* 344 * add back carry outs from top 16 bits to low 16 bits 345 */ 346 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 347 sum += (sum >> 16); /* add carry */ 348 answer = ~sum; /* truncate to 16 bits */ 349 return (answer); 350 } 351 352 /* 353 * print an IP datagram. 354 */ 355 void 356 ip_print(register const u_char *bp, register u_int length) 357 { 358 register const struct ip *ip; 359 register u_int hlen, len, off; 360 register const u_char *cp; 361 362 ip = (const struct ip *)bp; 363 /* 364 * If the IP header is not aligned, copy into abuf. 365 * This will never happen with BPF. It does happen with raw packet 366 * dumps from -r. 367 */ 368 if ((intptr_t)ip & (sizeof(long)-1)) { 369 static u_char *abuf = NULL; 370 static int didwarn = 0; 371 int clen = snapend - bp; 372 373 if (clen > snaplen) 374 clen = snaplen; 375 if (abuf == NULL) { 376 abuf = (u_char *)malloc(snaplen); 377 if (abuf == NULL) 378 error("ip_print: malloc"); 379 } 380 memmove((char *)abuf, (char *)ip, min(length, clen)); 381 snapend = abuf + clen; 382 packetp = abuf; 383 ip = (struct ip *)abuf; 384 /* We really want libpcap to give us aligned packets */ 385 if (!didwarn) { 386 warning("compensating for unaligned libpcap packets"); 387 ++didwarn; 388 } 389 } 390 391 TCHECK(*ip); 392 if (ip->ip_v != IPVERSION) { 393 (void)printf("bad-ip-version %u", ip->ip_v); 394 return; 395 } 396 397 len = ntohs(ip->ip_len); 398 if (length < len) { 399 (void)printf("truncated-ip - %d bytes missing!", 400 len - length); 401 len = length; 402 } 403 404 hlen = ip->ip_hl * 4; 405 if (hlen < sizeof(struct ip) || hlen > len) { 406 (void)printf("bad-hlen %d", hlen); 407 return; 408 } 409 410 len -= hlen; 411 412 /* 413 * If this is fragment zero, hand it to the next higher 414 * level protocol. 415 */ 416 off = ntohs(ip->ip_off); 417 if ((off & 0x1fff) == 0) { 418 cp = (const u_char *)ip + hlen; 419 switch (ip->ip_p) { 420 421 case IPPROTO_TCP: 422 tcp_print(cp, len, (const u_char *)ip); 423 break; 424 425 case IPPROTO_UDP: 426 udp_print(cp, len, (const u_char *)ip); 427 break; 428 429 case IPPROTO_ICMP: 430 icmp_print(cp, (const u_char *)ip); 431 break; 432 433 #ifndef IPPROTO_IGRP 434 #define IPPROTO_IGRP 9 435 #endif 436 case IPPROTO_IGRP: 437 igrp_print(cp, len, (const u_char *)ip); 438 break; 439 440 case IPPROTO_ND: 441 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 442 ipaddr_string(&ip->ip_dst)); 443 (void)printf(" nd %d", len); 444 break; 445 446 #ifndef IPPROTO_OSPF 447 #define IPPROTO_OSPF 89 448 #endif 449 case IPPROTO_OSPF: 450 ospf_print(cp, len, (const u_char *)ip); 451 break; 452 453 #ifndef IPPROTO_IGMP 454 #define IPPROTO_IGMP 2 455 #endif 456 case IPPROTO_IGMP: 457 igmp_print(cp, len, (const u_char *)ip); 458 break; 459 460 #ifndef IPPROTO_IPIP 461 #define IPPROTO_IPIP 4 462 #endif 463 case IPPROTO_IPIP: 464 /* ip-in-ip encapsulation */ 465 if (vflag) 466 (void)printf("%s > %s: ", 467 ipaddr_string(&ip->ip_src), 468 ipaddr_string(&ip->ip_dst)); 469 ip_print(cp, len); 470 if (! vflag) { 471 printf(" (encap)"); 472 return; 473 } 474 break; 475 476 #ifdef INET6 477 #ifndef IPPROTO_IPV6 478 #define IPPROTO_IPV6 479 #endif 480 case IPPROTO_IPV6: 481 /* ip6-in-ip encapsulation */ 482 if (vflag) 483 (void)printf("%s > %s: ", 484 ipaddr_string(&ip->ip_src), 485 ipaddr_string(&ip->ip_dst)); 486 ip6_print(cp, len); 487 if (! vflag) { 488 printf(" (encap)"); 489 return; 490 } 491 break; 492 #endif /*INET6*/ 493 494 #ifndef IPPROTO_GRE 495 #define IPPROTO_GRE 47 496 #endif 497 case IPPROTO_GRE: 498 if (vflag) 499 (void)printf("gre %s > %s: ", 500 ipaddr_string(&ip->ip_src), 501 ipaddr_string(&ip->ip_dst)); 502 /* do it */ 503 gre_print(cp, len); 504 if (! vflag) { 505 printf(" (gre encap)"); 506 return; 507 } 508 break; 509 510 #ifndef IPPROTO_ESP 511 #define IPPROTO_ESP 50 512 #endif 513 case IPPROTO_ESP: 514 esp_print(cp, len, (const u_char *)ip); 515 break; 516 517 #ifndef IPPROTO_AH 518 #define IPPROTO_AH 51 519 #endif 520 case IPPROTO_AH: 521 ah_print(cp, len, (const u_char *)ip); 522 break; 523 524 #ifndef IPPROTO_MOBILE 525 #define IPPROTO_MOBILE 55 526 #endif 527 case IPPROTO_MOBILE: 528 if (vflag) 529 (void)printf("mobile %s > %s: ", 530 ipaddr_string(&ip->ip_src), 531 ipaddr_string(&ip->ip_dst)); 532 mobile_print(cp, len); 533 if (! vflag) { 534 printf(" (mobile encap)"); 535 return; 536 } 537 break; 538 539 #ifndef IPPROTO_ETHERIP 540 #define IPPROTO_ETHERIP 97 541 #endif 542 case IPPROTO_ETHERIP: 543 etherip_print(cp, snapend - cp, len, 544 (const u_char *)ip); 545 break; 546 547 #ifndef IPPROTO_IPCOMP 548 #define IPPROTO_IPCOMP 108 549 #endif 550 case IPPROTO_IPCOMP: 551 ipcomp_print(cp, len, (const u_char *)ip); 552 break; 553 554 #ifndef IPPROTO_CARP 555 #define IPPROTO_CARP 112 556 #endif 557 case IPPROTO_CARP: 558 if (packettype == PT_VRRP) { 559 if (vflag) 560 (void)printf("vrrp %s > %s: ", 561 ipaddr_string(&ip->ip_src), 562 ipaddr_string(&ip->ip_dst)); 563 vrrp_print(cp, len, ip->ip_ttl); 564 } else { 565 if (vflag) 566 (void)printf("carp %s > %s: ", 567 ipaddr_string(&ip->ip_src), 568 ipaddr_string(&ip->ip_dst)); 569 carp_print(cp, len, ip->ip_ttl); 570 } 571 break; 572 573 #ifndef IPPROTO_PFSYNC 574 #define IPPROTO_PFSYNC 240 575 #endif 576 case IPPROTO_PFSYNC: 577 pfsync_ip_print(cp, 578 (int)(snapend - (u_char *)ip) - hlen, 579 (const u_char *)ip); 580 break; 581 582 default: 583 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 584 ipaddr_string(&ip->ip_dst)); 585 (void)printf(" ip-proto-%d %d", ip->ip_p, len); 586 break; 587 } 588 } 589 /* 590 * for fragmented datagrams, print id:size@offset. On all 591 * but the last stick a "+". For unfragmented datagrams, note 592 * the don't fragment flag. 593 */ 594 if (off & 0x3fff) { 595 /* 596 * if this isn't the first frag, we're missing the 597 * next level protocol header. print the ip addr. 598 */ 599 if (off & 0x1fff) 600 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 601 ipaddr_string(&ip->ip_dst)); 602 (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len, 603 (off & 0x1fff) * 8, 604 (off & IP_MF)? "+" : ""); 605 } 606 if (off & IP_DF) 607 (void)printf(" (DF)"); 608 609 if (ip->ip_tos) { 610 (void)printf(" [tos 0x%x", (int)ip->ip_tos); 611 if (ip->ip_tos & (IPTOS_CE|IPTOS_ECT)) { 612 (void)printf(" ("); 613 if (ip->ip_tos & IPTOS_ECT) { 614 /* ECN-capable transport */ 615 putchar('E'); 616 } 617 if (ip->ip_tos & IPTOS_CE) { 618 /* _C_ongestion experienced (ECN) */ 619 putchar('C'); 620 } 621 (void)printf(")"); 622 } 623 (void)printf("]"); 624 } 625 626 if (ip->ip_ttl <= 1) 627 (void)printf(" [ttl %d]", (int)ip->ip_ttl); 628 629 if (vflag) { 630 int sum; 631 char *sep = ""; 632 633 printf(" ("); 634 if (ip->ip_ttl > 1) { 635 (void)printf("%sttl %d", sep, (int)ip->ip_ttl); 636 sep = ", "; 637 } 638 if ((off & 0x3fff) == 0) { 639 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); 640 sep = ", "; 641 } 642 (void)printf("%slen %u", sep, ntohs(ip->ip_len)); 643 sep = ", "; 644 if ((u_char *)ip + hlen <= snapend) { 645 sum = in_cksum((const u_short *)ip, hlen, 0); 646 if (sum != 0) { 647 (void)printf("%sbad cksum %x!", sep, 648 ntohs(ip->ip_sum)); 649 if (vflag > 1) 650 (void)printf(" differs by %x", htons(sum)); 651 sep = ", "; 652 } 653 } 654 if (hlen > sizeof(struct ip)) { 655 hlen -= sizeof(struct ip); 656 (void)printf("%soptlen=%d", sep, hlen); 657 ip_optprint((u_char *)(ip + 1), hlen); 658 } 659 printf(")"); 660 } 661 return; 662 663 trunc: 664 printf("[|ip]"); 665 } 666