1 /* $OpenBSD: worker.c,v 1.1 2016/09/03 22:00:06 benno Exp $ */ 2 /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /*- 34 * Copyright (c) 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * Van Jacobson. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 #include <arpa/inet.h> 66 #include <arpa/nameser.h> 67 #include <endian.h> 68 #include <err.h> 69 #include <limits.h> 70 #include <netdb.h> 71 #include <netinet/icmp6.h> 72 #include <netinet/in.h> 73 #include <netinet/ip.h> 74 #include <netinet/ip6.h> 75 #include <netinet/ip_icmp.h> 76 #include <netinet/udp.h> 77 #include <poll.h> 78 #include <stdio.h> 79 #include <string.h> 80 #include <sys/socket.h> 81 #include <sys/time.h> 82 #include <sys/types.h> 83 #include <sys/uio.h> 84 #include <time.h> 85 #include <unistd.h> 86 87 #include "traceroute.h" 88 89 static u_int8_t icmp_type = ICMP_ECHO; /* default ICMP code/type */ 90 91 void 92 print_exthdr(u_char *buf, int cc) 93 { 94 struct icmp_ext_hdr exthdr; 95 struct icmp_ext_obj_hdr objhdr; 96 struct ip *ip; 97 struct icmp *icp; 98 int hlen, first; 99 u_int32_t label; 100 u_int16_t off, olen; 101 u_int8_t type; 102 103 ip = (struct ip *)buf; 104 hlen = ip->ip_hl << 2; 105 if (cc < hlen + ICMP_MINLEN) 106 return; 107 icp = (struct icmp *)(buf + hlen); 108 cc -= hlen + ICMP_MINLEN; 109 buf += hlen + ICMP_MINLEN; 110 111 type = icp->icmp_type; 112 if (type != ICMP_TIMXCEED && type != ICMP_UNREACH && 113 type != ICMP_PARAMPROB) 114 /* Wrong ICMP type for extension */ 115 return; 116 117 off = icp->icmp_length * sizeof(u_int32_t); 118 if (off == 0) 119 /* 120 * rfc 4884 Section 5.5: traceroute MUST try to parse 121 * broken ext headers. Again IETF bent over to please 122 * idotic corporations. 123 */ 124 off = ICMP_EXT_OFFSET; 125 else if (off < ICMP_EXT_OFFSET) 126 /* rfc 4884 requires an offset of at least 128 bytes */ 127 return; 128 129 /* make sure that at least one extension is present */ 130 if (cc < off + sizeof(exthdr) + sizeof(objhdr)) 131 /* Not enough space for ICMP extensions */ 132 return; 133 134 cc -= off; 135 buf += off; 136 memcpy(&exthdr, buf, sizeof(exthdr)); 137 138 /* verify version */ 139 if ((exthdr.ieh_version & ICMP_EXT_HDR_VMASK) != ICMP_EXT_HDR_VERSION) 140 return; 141 142 /* verify checksum */ 143 if (exthdr.ieh_cksum && in_cksum((u_short *)buf, cc)) 144 return; 145 146 buf += sizeof(exthdr); 147 cc -= sizeof(exthdr); 148 149 while (cc > sizeof(objhdr)) { 150 memcpy(&objhdr, buf, sizeof(objhdr)); 151 olen = ntohs(objhdr.ieo_length); 152 153 /* Sanity check the length field */ 154 if (olen < sizeof(objhdr) || olen > cc) 155 return; 156 157 cc -= olen; 158 159 /* Move past the object header */ 160 buf += sizeof(objhdr); 161 olen -= sizeof(objhdr); 162 163 switch (objhdr.ieo_cnum) { 164 case ICMP_EXT_MPLS: 165 /* RFC 4950: ICMP Extensions for MPLS */ 166 switch (objhdr.ieo_ctype) { 167 case 1: 168 first = 0; 169 while (olen >= sizeof(u_int32_t)) { 170 memcpy(&label, buf, sizeof(u_int32_t)); 171 label = htonl(label); 172 buf += sizeof(u_int32_t); 173 olen -= sizeof(u_int32_t); 174 175 if (first == 0) { 176 printf(" [MPLS Label "); 177 first++; 178 } else 179 printf(", "); 180 printf("%d", MPLS_LABEL(label)); 181 if (MPLS_EXP(label)) 182 printf(" (Exp %x)", 183 MPLS_EXP(label)); 184 } 185 if (olen > 0) { 186 printf("|]"); 187 return; 188 } 189 if (first != 0) 190 printf("]"); 191 break; 192 default: 193 buf += olen; 194 break; 195 } 196 break; 197 case ICMP_EXT_IFINFO: 198 default: 199 buf += olen; 200 break; 201 } 202 } 203 } 204 205 void 206 check_tos(struct ip *ip) 207 { 208 struct icmp *icp; 209 struct ip *inner_ip; 210 211 icp = (struct icmp *) (((u_char *)ip)+(ip->ip_hl<<2)); 212 inner_ip = (struct ip *) (((u_char *)icp)+8); 213 214 if (inner_ip->ip_tos != last_tos) 215 printf (" (TOS=%d!)", inner_ip->ip_tos); 216 217 last_tos = inner_ip->ip_tos; 218 } 219 220 int 221 wait_for_reply(int sock, struct msghdr *mhdr) 222 { 223 struct pollfd pfd[1]; 224 int cc = 0; 225 226 pfd[0].fd = sock; 227 pfd[0].events = POLLIN; 228 pfd[0].revents = 0; 229 230 if (poll(pfd, 1, waittime * 1000) > 0) 231 cc = recvmsg(rcvsock, mhdr, 0); 232 233 return (cc); 234 } 235 236 void 237 dump_packet(void) 238 { 239 u_char *p; 240 int i; 241 242 fprintf(stderr, "packet data:"); 243 for (p = outpacket, i = 0; i < datalen; i++) { 244 if ((i % 24) == 0) 245 fprintf(stderr, "\n "); 246 fprintf(stderr, " %02x", *p++); 247 } 248 fprintf(stderr, "\n"); 249 } 250 251 void 252 build_probe4(int seq, u_int8_t ttl, int iflag) 253 { 254 struct ip *ip = (struct ip *)outpacket; 255 u_char *p = (u_char *)(ip + 1); 256 struct udphdr *up = (struct udphdr *)(p + lsrrlen); 257 struct icmp *icmpp = (struct icmp *)(p + lsrrlen); 258 struct packetdata *op; 259 struct timeval tv; 260 261 ip->ip_len = htons(datalen); 262 ip->ip_ttl = ttl; 263 ip->ip_id = htons(ident+seq); 264 265 switch (proto) { 266 case IPPROTO_ICMP: 267 icmpp->icmp_type = icmp_type; 268 icmpp->icmp_code = ICMP_CODE; 269 icmpp->icmp_seq = htons(seq); 270 icmpp->icmp_id = htons(ident); 271 op = (struct packetdata *)(icmpp + 1); 272 break; 273 case IPPROTO_UDP: 274 up->uh_sport = htons(ident); 275 if (iflag) 276 up->uh_dport = htons(port+seq); 277 else 278 up->uh_dport = htons(port); 279 up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - 280 lsrrlen)); 281 up->uh_sum = 0; 282 op = (struct packetdata *)(up + 1); 283 break; 284 default: 285 op = (struct packetdata *)(ip + 1); 286 break; 287 } 288 op->seq = seq; 289 op->ttl = ttl; 290 gettime(&tv); 291 292 /* 293 * We don't want hostiles snooping the net to get any useful 294 * information about us. Send the timestamp in network byte order, 295 * and perturb the timestamp enough that they won't know our 296 * real clock ticker. We don't want to perturb the time by too 297 * much: being off by a suspiciously large amount might indicate 298 * OpenBSD. 299 * 300 * The timestamps in the packet are currently unused. If future 301 * work wants to use them they will have to subtract out the 302 * perturbation first. 303 */ 304 gettime(&tv); 305 op->sec = htonl(tv.tv_sec + sec_perturb); 306 op->usec = htonl((tv.tv_usec + usec_perturb) % 1000000); 307 308 if (proto == IPPROTO_ICMP && icmp_type == ICMP_ECHO) { 309 icmpp->icmp_cksum = 0; 310 icmpp->icmp_cksum = in_cksum((u_short *)icmpp, 311 datalen - sizeof(struct ip) - lsrrlen); 312 if (icmpp->icmp_cksum == 0) 313 icmpp->icmp_cksum = 0xffff; 314 } 315 } 316 317 void 318 build_probe6(int seq, u_int8_t hops, int iflag, struct sockaddr *to) 319 { 320 struct timeval tv; 321 struct packetdata *op; 322 int i; 323 324 i = hops; 325 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 326 (char *)&i, sizeof(i)) < 0) 327 warn("setsockopt IPV6_UNICAST_HOPS"); 328 329 if (iflag) 330 ((struct sockaddr_in6*)to)->sin6_port = htons(port + seq); 331 else 332 ((struct sockaddr_in6*)to)->sin6_port = htons(port); 333 gettime(&tv); 334 335 if (proto == IPPROTO_ICMP) { 336 struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket; 337 338 icp->icmp6_type = ICMP6_ECHO_REQUEST; 339 icp->icmp6_code = 0; 340 icp->icmp6_cksum = 0; 341 icp->icmp6_id = ident; 342 icp->icmp6_seq = htons(seq); 343 op = (struct packetdata *)(outpacket + 344 sizeof(struct icmp6_hdr)); 345 } else 346 op = (struct packetdata *)outpacket; 347 op->seq = seq; 348 op->ttl = hops; 349 op->sec = htonl(tv.tv_sec); 350 op->usec = htonl(tv.tv_usec); 351 } 352 353 void 354 send_probe(int seq, u_int8_t ttl, int iflag, struct sockaddr *to) 355 { 356 int i; 357 358 switch (to->sa_family) { 359 case AF_INET: 360 build_probe4(seq, ttl, iflag); 361 break; 362 case AF_INET6: 363 build_probe6(seq, ttl, iflag, to); 364 break; 365 default: 366 errx(1, "unsupported AF: %d", to->sa_family); 367 break; 368 } 369 370 if (dump) 371 dump_packet(); 372 373 i = sendto(sndsock, outpacket, datalen, 0, to, to->sa_len); 374 if (i < 0 || i != datalen) { 375 if (i < 0) 376 warn("sendto"); 377 printf("%s: wrote %s %d chars, ret=%d\n", __progname, hostname, 378 datalen, i); 379 (void) fflush(stdout); 380 } 381 } 382 383 double 384 deltaT(struct timeval *t1p, struct timeval *t2p) 385 { 386 double dt; 387 388 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 389 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 390 return (dt); 391 } 392 393 static char *ttab[] = { 394 "Echo Reply", 395 "ICMP 1", 396 "ICMP 2", 397 "Dest Unreachable", 398 "Source Quench", 399 "Redirect", 400 "ICMP 6", 401 "ICMP 7", 402 "Echo", 403 "Router Advert", 404 "Router Solicit", 405 "Time Exceeded", 406 "Param Problem", 407 "Timestamp", 408 "Timestamp Reply", 409 "Info Request", 410 "Info Reply", 411 "Mask Request", 412 "Mask Reply" 413 }; 414 415 /* 416 * Convert an ICMP "type" field to a printable string. 417 */ 418 char * 419 pr_type(u_int8_t t) 420 { 421 if (t > 18) 422 return ("OUT-OF-RANGE"); 423 return (ttab[t]); 424 } 425 426 int 427 packet_ok(int af, struct msghdr *mhdr, int cc, int seq, int iflag) 428 { 429 switch (af) { 430 case AF_INET: 431 return packet_ok4(mhdr, cc, seq, iflag); 432 break; 433 case AF_INET6: 434 return packet_ok6(mhdr, cc, seq, iflag); 435 break; 436 default: 437 errx(1, "unsupported AF: %d", af); 438 break; 439 } 440 } 441 442 int 443 packet_ok4(struct msghdr *mhdr, int cc,int seq, int iflag) 444 { 445 struct sockaddr_in *from = (struct sockaddr_in *)mhdr->msg_name; 446 struct icmp *icp; 447 u_char code; 448 char *buf = (char *)mhdr->msg_iov[0].iov_base; 449 u_int8_t type; 450 int hlen; 451 struct ip *ip; 452 453 ip = (struct ip *) buf; 454 hlen = ip->ip_hl << 2; 455 if (cc < hlen + ICMP_MINLEN) { 456 if (verbose) 457 printf("packet too short (%d bytes) from %s\n", cc, 458 inet_ntoa(from->sin_addr)); 459 return (0); 460 } 461 cc -= hlen; 462 icp = (struct icmp *)(buf + hlen); 463 type = icp->icmp_type; 464 code = icp->icmp_code; 465 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 466 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { 467 struct ip *hip; 468 struct udphdr *up; 469 struct icmp *icmpp; 470 471 hip = &icp->icmp_ip; 472 hlen = hip->ip_hl << 2; 473 474 switch (proto) { 475 case IPPROTO_ICMP: 476 if (icmp_type == ICMP_ECHO && 477 type == ICMP_ECHOREPLY && 478 icp->icmp_id == htons(ident) && 479 icp->icmp_seq == htons(seq)) 480 return (-2); /* we got there */ 481 482 icmpp = (struct icmp *)((u_char *)hip + hlen); 483 if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && 484 icmpp->icmp_id == htons(ident) && 485 icmpp->icmp_seq == htons(seq)) 486 return (type == ICMP_TIMXCEED? -1 : code + 1); 487 break; 488 489 case IPPROTO_UDP: 490 up = (struct udphdr *)((u_char *)hip + hlen); 491 if (hlen + 12 <= cc && hip->ip_p == proto && 492 up->uh_sport == htons(ident) && 493 ((iflag && up->uh_dport == htons(port + seq)) || 494 (!iflag && up->uh_dport == htons(port)))) 495 return (type == ICMP_TIMXCEED? -1 : code + 1); 496 break; 497 default: 498 /* this is some odd, user specified proto, 499 * how do we check it? 500 */ 501 if (hip->ip_p == proto) 502 return (type == ICMP_TIMXCEED? -1 : code + 1); 503 } 504 } 505 if (verbose) { 506 int i; 507 in_addr_t *lp = (in_addr_t *)&icp->icmp_ip; 508 509 printf("\n%d bytes from %s", cc, inet_ntoa(from->sin_addr)); 510 printf(" to %s", inet_ntoa(ip->ip_dst)); 511 printf(": icmp type %u (%s) code %d\n", type, pr_type(type), 512 icp->icmp_code); 513 for (i = 4; i < cc ; i += sizeof(in_addr_t)) 514 printf("%2d: x%8.8lx\n", i, (unsigned long)*lp++); 515 } 516 return (0); 517 } 518 519 int 520 packet_ok6(struct msghdr *mhdr, int cc, int seq, int iflag) 521 { 522 struct icmp6_hdr *icp; 523 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 524 u_char type, code; 525 char *buf = (char *)mhdr->msg_iov[0].iov_base; 526 struct cmsghdr *cm; 527 int *hlimp; 528 char hbuf[NI_MAXHOST]; 529 int useicmp = (proto == IPPROTO_ICMP); 530 531 if (cc < sizeof(struct icmp6_hdr)) { 532 if (verbose) { 533 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 534 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 535 strlcpy(hbuf, "invalid", sizeof(hbuf)); 536 printf("data too short (%d bytes) from %s\n", cc, hbuf); 537 } 538 return(0); 539 } 540 icp = (struct icmp6_hdr *)buf; 541 /* get optional information via advanced API */ 542 rcvpktinfo = NULL; 543 hlimp = NULL; 544 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 545 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 546 if (cm->cmsg_level == IPPROTO_IPV6 && 547 cm->cmsg_type == IPV6_PKTINFO && 548 cm->cmsg_len == 549 CMSG_LEN(sizeof(struct in6_pktinfo))) 550 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 551 552 if (cm->cmsg_level == IPPROTO_IPV6 && 553 cm->cmsg_type == IPV6_HOPLIMIT && 554 cm->cmsg_len == CMSG_LEN(sizeof(int))) 555 hlimp = (int *)CMSG_DATA(cm); 556 } 557 if (rcvpktinfo == NULL || hlimp == NULL) { 558 warnx("failed to get received hop limit or packet info"); 559 rcvhlim = 0; /*XXX*/ 560 } else 561 rcvhlim = *hlimp; 562 563 type = icp->icmp6_type; 564 code = icp->icmp6_code; 565 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 566 || type == ICMP6_DST_UNREACH) { 567 struct ip6_hdr *hip; 568 struct udphdr *up; 569 570 hip = (struct ip6_hdr *)(icp + 1); 571 if ((up = get_udphdr(hip, (u_char *)(buf + cc))) == NULL) { 572 if (verbose) 573 warnx("failed to get upper layer header"); 574 return(0); 575 } 576 if (useicmp && 577 ((struct icmp6_hdr *)up)->icmp6_id == ident && 578 ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq)) 579 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 580 else if (!useicmp && 581 up->uh_sport == htons(srcport) && 582 ((iflag && up->uh_dport == htons(port + seq)) || 583 (!iflag && up->uh_dport == htons(port)))) 584 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 585 } else if (useicmp && type == ICMP6_ECHO_REPLY) { 586 if (icp->icmp6_id == ident && 587 icp->icmp6_seq == htons(seq)) 588 return (ICMP6_DST_UNREACH_NOPORT + 1); 589 } 590 if (verbose) { 591 char sbuf[NI_MAXHOST], dbuf[INET6_ADDRSTRLEN]; 592 u_int8_t *p; 593 int i; 594 595 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 596 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 597 strlcpy(sbuf, "invalid", sizeof(sbuf)); 598 printf("\n%d bytes from %s to %s", cc, sbuf, 599 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 600 dbuf, sizeof(dbuf)) : "?"); 601 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 602 icp->icmp6_code); 603 p = (u_int8_t *)(icp + 1); 604 #define WIDTH 16 605 for (i = 0; i < cc; i++) { 606 if (i % WIDTH == 0) 607 printf("%04x:", i); 608 if (i % 4 == 0) 609 printf(" "); 610 printf("%02x", p[i]); 611 if (i % WIDTH == WIDTH - 1) 612 printf("\n"); 613 } 614 if (cc % WIDTH != 0) 615 printf("\n"); 616 } 617 return(0); 618 } 619 620 void 621 print(struct sockaddr *from, int cc, const char *to) 622 { 623 char hbuf[NI_MAXHOST]; 624 if (getnameinfo(from, from->sa_len, 625 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 626 strlcpy(hbuf, "invalid", sizeof(hbuf)); 627 if (nflag) 628 printf(" %s", hbuf); 629 else 630 printf(" %s (%s)", inetname(from), hbuf); 631 632 if (Aflag) 633 print_asn((struct sockaddr_storage *)from); 634 635 if (verbose) 636 printf(" %d bytes to %s", cc, to); 637 } 638 639 /* 640 * Increment pointer until find the UDP or ICMP header. 641 */ 642 struct udphdr * 643 get_udphdr(struct ip6_hdr *ip6, u_char *lim) 644 { 645 u_char *cp = (u_char *)ip6, nh; 646 int hlen; 647 int useicmp = (proto == IPPROTO_ICMP); 648 649 if (cp + sizeof(*ip6) >= lim) 650 return(NULL); 651 652 nh = ip6->ip6_nxt; 653 cp += sizeof(struct ip6_hdr); 654 655 while (lim - cp >= 8) { 656 switch (nh) { 657 case IPPROTO_ESP: 658 case IPPROTO_TCP: 659 return(NULL); 660 case IPPROTO_ICMPV6: 661 return(useicmp ? (struct udphdr *)cp : NULL); 662 case IPPROTO_UDP: 663 return(useicmp ? NULL : (struct udphdr *)cp); 664 case IPPROTO_FRAGMENT: 665 hlen = sizeof(struct ip6_frag); 666 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 667 break; 668 case IPPROTO_AH: 669 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 670 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 671 break; 672 default: 673 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 674 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 675 break; 676 } 677 678 cp += hlen; 679 } 680 681 return(NULL); 682 } 683 684 void 685 icmp_code(int af, int code, int *got_there, int *unreachable) 686 { 687 switch (af) { 688 case AF_INET: 689 icmp4_code(code, got_there, unreachable); 690 break; 691 case AF_INET6: 692 icmp6_code(code, got_there, unreachable); 693 break; 694 default: 695 errx(1, "unsupported AF: %d", af); 696 break; 697 } 698 } 699 700 void 701 icmp4_code(int code, int *got_there, int *unreachable) 702 { 703 struct ip *ip = (struct ip *)packet; 704 705 switch (code) { 706 case ICMP_UNREACH_PORT: 707 if (ip->ip_ttl <= 1) 708 printf(" !"); 709 ++(*got_there); 710 break; 711 case ICMP_UNREACH_NET: 712 ++(*unreachable); 713 printf(" !N"); 714 break; 715 case ICMP_UNREACH_HOST: 716 ++(*unreachable); 717 printf(" !H"); 718 break; 719 case ICMP_UNREACH_PROTOCOL: 720 ++(*got_there); 721 printf(" !P"); 722 break; 723 case ICMP_UNREACH_NEEDFRAG: 724 ++(*unreachable); 725 printf(" !F"); 726 break; 727 case ICMP_UNREACH_SRCFAIL: 728 ++(*unreachable); 729 printf(" !S"); 730 break; 731 case ICMP_UNREACH_FILTER_PROHIB: 732 ++(*unreachable); 733 printf(" !X"); 734 break; 735 case ICMP_UNREACH_NET_PROHIB: /*misuse*/ 736 ++(*unreachable); 737 printf(" !A"); 738 break; 739 case ICMP_UNREACH_HOST_PROHIB: 740 ++(*unreachable); 741 printf(" !C"); 742 break; 743 case ICMP_UNREACH_NET_UNKNOWN: 744 case ICMP_UNREACH_HOST_UNKNOWN: 745 ++(*unreachable); 746 printf(" !U"); 747 break; 748 case ICMP_UNREACH_ISOLATED: 749 ++(*unreachable); 750 printf(" !I"); 751 break; 752 case ICMP_UNREACH_TOSNET: 753 case ICMP_UNREACH_TOSHOST: 754 ++(*unreachable); 755 printf(" !T"); 756 break; 757 default: 758 ++(*unreachable); 759 printf(" !<%d>", code); 760 break; 761 } 762 } 763 764 void 765 icmp6_code(int code, int *got_there, int *unreachable) 766 { 767 switch (code) { 768 case ICMP6_DST_UNREACH_NOROUTE: 769 ++(*unreachable); 770 printf(" !N"); 771 break; 772 case ICMP6_DST_UNREACH_ADMIN: 773 ++(*unreachable); 774 printf(" !P"); 775 break; 776 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 777 ++(*unreachable); 778 printf(" !S"); 779 break; 780 case ICMP6_DST_UNREACH_ADDR: 781 ++(*unreachable); 782 printf(" !A"); 783 break; 784 case ICMP6_DST_UNREACH_NOPORT: 785 if (rcvhlim >= 0 && rcvhlim <= 1) 786 printf(" !"); 787 ++(*got_there); 788 break; 789 default: 790 ++(*unreachable); 791 printf(" !<%d>", code); 792 break; 793 } 794 } 795 796 /* 797 * Checksum routine for Internet Protocol family headers (C Version) 798 */ 799 u_short 800 in_cksum(u_short *addr, int len) 801 { 802 u_short *w = addr, answer; 803 int nleft = len, sum = 0; 804 805 /* 806 * Our algorithm is simple, using a 32 bit accumulator (sum), 807 * we add sequential 16 bit words to it, and at the end, fold 808 * back all the carry bits from the top 16 bits into the lower 809 * 16 bits. 810 */ 811 while (nleft > 1) { 812 sum += *w++; 813 nleft -= 2; 814 } 815 816 /* mop up an odd byte, if necessary */ 817 if (nleft == 1) 818 sum += *(u_char *)w; 819 820 /* 821 * add back carry outs from top 16 bits to low 16 bits 822 */ 823 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 824 sum += (sum >> 16); /* add carry */ 825 answer = ~sum; /* truncate to 16 bits */ 826 return (answer); 827 } 828 829 /* 830 * Construct an Internet address representation. 831 */ 832 const char * 833 inetname(struct sockaddr *sa) 834 { 835 static char line[NI_MAXHOST], domain[HOST_NAME_MAX + 1]; 836 static int first = 1; 837 char *cp; 838 839 if (first) { 840 first = 0; 841 if (gethostname(domain, sizeof(domain)) == 0 && 842 (cp = strchr(domain, '.')) != NULL) 843 memmove(domain, cp + 1, strlen(cp + 1) + 1); 844 else 845 domain[0] = 0; 846 } 847 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 848 NI_NAMEREQD) == 0) { 849 if ((cp = strchr(line, '.')) != NULL && strcmp(cp + 1, 850 domain) == 0) 851 *cp = '\0'; 852 return (line); 853 } 854 855 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 856 NI_NUMERICHOST) != 0) 857 return ("invalid"); 858 return (line); 859 } 860 861 void 862 print_asn(struct sockaddr_storage *ss) 863 { 864 struct rrsetinfo *answers = NULL; 865 int counter; 866 const u_char *uaddr; 867 char qbuf[MAXDNAME]; 868 869 switch (ss->ss_family) { 870 case AF_INET: 871 uaddr = (const u_char *)&((struct sockaddr_in *) ss)->sin_addr; 872 if (snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u." 873 "origin.asn.cymru.com", 874 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 875 (uaddr[1] & 0xff), (uaddr[0] & 0xff)) >= sizeof (qbuf)) 876 return; 877 break; 878 case AF_INET6: 879 uaddr = (const u_char *)&((struct sockaddr_in6 *) ss)->sin6_addr; 880 if (snprintf(qbuf, sizeof qbuf, 881 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 882 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 883 "origin6.asn.cymru.com", 884 (uaddr[15] & 0x0f), ((uaddr[15] >>4)& 0x0f), 885 (uaddr[14] & 0x0f), ((uaddr[14] >>4)& 0x0f), 886 (uaddr[13] & 0x0f), ((uaddr[13] >>4)& 0x0f), 887 (uaddr[12] & 0x0f), ((uaddr[12] >>4)& 0x0f), 888 (uaddr[11] & 0x0f), ((uaddr[11] >>4)& 0x0f), 889 (uaddr[10] & 0x0f), ((uaddr[10] >>4)& 0x0f), 890 (uaddr[9] & 0x0f), ((uaddr[9] >>4)& 0x0f), 891 (uaddr[8] & 0x0f), ((uaddr[8] >>4)& 0x0f), 892 (uaddr[7] & 0x0f), ((uaddr[7] >>4)& 0x0f), 893 (uaddr[6] & 0x0f), ((uaddr[6] >>4)& 0x0f), 894 (uaddr[5] & 0x0f), ((uaddr[5] >>4)& 0x0f), 895 (uaddr[4] & 0x0f), ((uaddr[4] >>4)& 0x0f), 896 (uaddr[3] & 0x0f), ((uaddr[3] >>4)& 0x0f), 897 (uaddr[2] & 0x0f), ((uaddr[2] >>4)& 0x0f), 898 (uaddr[1] & 0x0f), ((uaddr[1] >>4)& 0x0f), 899 (uaddr[0] & 0x0f), ((uaddr[0] >>4)& 0x0f)) >= sizeof (qbuf)) 900 return; 901 break; 902 default: 903 return; 904 } 905 906 if (getrrsetbyname(qbuf, C_IN, T_TXT, 0, &answers) != 0) 907 return; 908 for (counter = 0; counter < answers->rri_nrdatas; counter++) { 909 char *p, *as = answers->rri_rdatas[counter].rdi_data; 910 as++; /* skip first byte, it contains length */ 911 if ((p = strchr(as,'|'))) { 912 printf(counter ? ", " : " ["); 913 p[-1] = 0; 914 printf("AS%s", as); 915 } 916 } 917 if (counter) 918 printf("]"); 919 920 freerrset(answers); 921 } 922 923 int 924 map_tos(char *s, int *val) 925 { 926 /* DiffServ Codepoints and other TOS mappings */ 927 const struct toskeywords { 928 const char *keyword; 929 int val; 930 } *t, toskeywords[] = { 931 { "af11", IPTOS_DSCP_AF11 }, 932 { "af12", IPTOS_DSCP_AF12 }, 933 { "af13", IPTOS_DSCP_AF13 }, 934 { "af21", IPTOS_DSCP_AF21 }, 935 { "af22", IPTOS_DSCP_AF22 }, 936 { "af23", IPTOS_DSCP_AF23 }, 937 { "af31", IPTOS_DSCP_AF31 }, 938 { "af32", IPTOS_DSCP_AF32 }, 939 { "af33", IPTOS_DSCP_AF33 }, 940 { "af41", IPTOS_DSCP_AF41 }, 941 { "af42", IPTOS_DSCP_AF42 }, 942 { "af43", IPTOS_DSCP_AF43 }, 943 { "critical", IPTOS_PREC_CRITIC_ECP }, 944 { "cs0", IPTOS_DSCP_CS0 }, 945 { "cs1", IPTOS_DSCP_CS1 }, 946 { "cs2", IPTOS_DSCP_CS2 }, 947 { "cs3", IPTOS_DSCP_CS3 }, 948 { "cs4", IPTOS_DSCP_CS4 }, 949 { "cs5", IPTOS_DSCP_CS5 }, 950 { "cs6", IPTOS_DSCP_CS6 }, 951 { "cs7", IPTOS_DSCP_CS7 }, 952 { "ef", IPTOS_DSCP_EF }, 953 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 954 { "lowdelay", IPTOS_LOWDELAY }, 955 { "netcontrol", IPTOS_PREC_NETCONTROL }, 956 { "reliability", IPTOS_RELIABILITY }, 957 { "throughput", IPTOS_THROUGHPUT }, 958 { NULL, -1 }, 959 }; 960 961 for (t = toskeywords; t->keyword != NULL; t++) { 962 if (strcmp(s, t->keyword) == 0) { 963 *val = t->val; 964 return (1); 965 } 966 } 967 968 return (0); 969 } 970 971 void 972 gettime(struct timeval *tv) 973 { 974 struct timespec ts; 975 976 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) 977 err(1, "clock_gettime(CLOCK_MONOTONIC)"); 978 979 TIMESPEC_TO_TIMEVAL(tv, &ts); 980 } 981