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