1 /* $OpenBSD: worker.c,v 1.8 2021/09/03 09:13:00 florian 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 <sys/types.h> 66 #include <sys/socket.h> 67 #include <sys/time.h> 68 #include <sys/uio.h> 69 70 #include <netinet/in.h> 71 #include <netinet/ip.h> 72 #include <netinet/ip6.h> 73 #include <netinet/ip_icmp.h> 74 #include <netinet/icmp6.h> 75 #include <netinet/udp.h> 76 77 #include <arpa/inet.h> 78 #include <arpa/nameser.h> 79 80 #include <asr.h> 81 #include <err.h> 82 #include <event.h> 83 #include <limits.h> 84 #include <netdb.h> 85 #include <stdio.h> 86 #include <stdlib.h> 87 #include <string.h> 88 #include <time.h> 89 #include <unistd.h> 90 91 #include "traceroute.h" 92 93 void build_probe4(struct tr_conf *, int, u_int8_t); 94 void build_probe6(struct tr_conf *, int, u_int8_t, 95 struct sockaddr *); 96 int packet_ok4(struct tr_conf *, struct msghdr *, int, int *); 97 int packet_ok6(struct tr_conf *, struct msghdr *, int, int *); 98 void icmp4_code(int, int *, int *, struct tr_result *); 99 void icmp6_code(int, int *, int *, struct tr_result *); 100 struct udphdr *get_udphdr(struct tr_conf *, struct ip6_hdr *, u_char *); 101 void dump_packet(void); 102 void print_asn(struct sockaddr_storage *, struct tr_result *); 103 u_short in_cksum(u_short *, int); 104 char *pr_type(u_int8_t); 105 double deltaT(struct timeval *, struct timeval *); 106 void check_timeout(struct tr_result *, struct tr_conf *); 107 void print_result_row(struct tr_result *, struct tr_conf *); 108 void getnameinfo_async_done(struct asr_result *, void *); 109 void getrrsetbyname_async_done(struct asr_result *, void *); 110 111 void 112 print_exthdr(u_char *buf, int cc, struct tr_result *tr_res) 113 { 114 struct icmp_ext_hdr exthdr; 115 struct icmp_ext_obj_hdr objhdr; 116 struct ip *ip; 117 struct icmp *icp; 118 size_t exthdr_size, len; 119 int hlen, first; 120 u_int32_t label; 121 u_int16_t off, olen; 122 u_int8_t type; 123 char *exthdr_str; 124 125 ip = (struct ip *)buf; 126 hlen = ip->ip_hl << 2; 127 if (cc < hlen + ICMP_MINLEN) 128 return; 129 icp = (struct icmp *)(buf + hlen); 130 cc -= hlen + ICMP_MINLEN; 131 buf += hlen + ICMP_MINLEN; 132 133 type = icp->icmp_type; 134 if (type != ICMP_TIMXCEED && type != ICMP_UNREACH && 135 type != ICMP_PARAMPROB) 136 /* Wrong ICMP type for extension */ 137 return; 138 139 off = icp->icmp_length * sizeof(u_int32_t); 140 if (off == 0) 141 /* 142 * rfc 4884 Section 5.5: traceroute MUST try to parse 143 * broken ext headers. Again IETF bent over to please 144 * idotic corporations. 145 */ 146 off = ICMP_EXT_OFFSET; 147 else if (off < ICMP_EXT_OFFSET) 148 /* rfc 4884 requires an offset of at least 128 bytes */ 149 return; 150 151 /* make sure that at least one extension is present */ 152 if (cc < off + sizeof(exthdr) + sizeof(objhdr)) 153 /* Not enough space for ICMP extensions */ 154 return; 155 156 cc -= off; 157 buf += off; 158 memcpy(&exthdr, buf, sizeof(exthdr)); 159 160 /* verify version */ 161 if ((exthdr.ieh_version & ICMP_EXT_HDR_VMASK) != ICMP_EXT_HDR_VERSION) 162 return; 163 164 /* verify checksum */ 165 if (exthdr.ieh_cksum && in_cksum((u_short *)buf, cc)) 166 return; 167 168 buf += sizeof(exthdr); 169 cc -= sizeof(exthdr); 170 171 /* rough estimate of needed space */ 172 exthdr_size = sizeof("[MPLS Label 1048576 (Exp 3)]") * 173 (cc / sizeof(u_int32_t)); 174 if ((tr_res->exthdr = calloc(1, exthdr_size)) == NULL) 175 err(1, NULL); 176 exthdr_str = tr_res->exthdr; 177 178 while (cc > sizeof(objhdr)) { 179 memcpy(&objhdr, buf, sizeof(objhdr)); 180 olen = ntohs(objhdr.ieo_length); 181 182 /* Sanity check the length field */ 183 if (olen < sizeof(objhdr) || olen > cc) 184 return; 185 186 cc -= olen; 187 188 /* Move past the object header */ 189 buf += sizeof(objhdr); 190 olen -= sizeof(objhdr); 191 192 switch (objhdr.ieo_cnum) { 193 case ICMP_EXT_MPLS: 194 /* RFC 4950: ICMP Extensions for MPLS */ 195 switch (objhdr.ieo_ctype) { 196 case 1: 197 first = 0; 198 while (olen >= sizeof(u_int32_t)) { 199 memcpy(&label, buf, sizeof(u_int32_t)); 200 label = htonl(label); 201 buf += sizeof(u_int32_t); 202 olen -= sizeof(u_int32_t); 203 204 if (first == 0) { 205 len = snprintf(exthdr_str, 206 exthdr_size, "%s", 207 " [MPLS Label "); 208 if (len != -1 && len < 209 exthdr_size) { 210 exthdr_str += len; 211 exthdr_size -= len; 212 } 213 first++; 214 } else { 215 len = snprintf(exthdr_str, 216 exthdr_size, "%s", 217 ", "); 218 if (len != -1 && len < 219 exthdr_size) { 220 exthdr_str += len; 221 exthdr_size -= len; 222 } 223 } 224 len = snprintf(exthdr_str, 225 exthdr_size, 226 "%d", MPLS_LABEL(label)); 227 if (len != -1 && len < exthdr_size) { 228 exthdr_str += len; 229 exthdr_size -= len; 230 } 231 if (MPLS_EXP(label)) { 232 len = snprintf(exthdr_str, 233 exthdr_size, " (Exp %x)", 234 MPLS_EXP(label)); 235 if (len != -1 && len < 236 exthdr_size) { 237 exthdr_str += len; 238 exthdr_size -= len; 239 } 240 } 241 } 242 if (olen > 0) { 243 len = snprintf(exthdr_str, 244 exthdr_size, "%s", "|]"); 245 if (len != -1 && len < 246 exthdr_size) { 247 exthdr_str += len; 248 exthdr_size -= len; 249 } 250 return; 251 } 252 if (first != 0) { 253 len = snprintf(exthdr_str, 254 exthdr_size, "%s", "]"); 255 if (len != -1 && len < 256 exthdr_size) { 257 exthdr_str += len; 258 exthdr_size -= len; 259 } 260 } 261 break; 262 default: 263 buf += olen; 264 break; 265 } 266 break; 267 case ICMP_EXT_IFINFO: 268 default: 269 buf += olen; 270 break; 271 } 272 } 273 } 274 275 void 276 check_tos(struct ip *ip, int *last_tos, struct tr_result *tr_res) 277 { 278 struct icmp *icp; 279 struct ip *inner_ip; 280 281 icp = (struct icmp *) (((u_char *)ip)+(ip->ip_hl<<2)); 282 inner_ip = (struct ip *) (((u_char *)icp)+8); 283 284 if (inner_ip->ip_tos != *last_tos) 285 snprintf(tr_res->tos, sizeof(tr_res->tos), 286 " (TOS=%d!)", inner_ip->ip_tos); 287 288 *last_tos = inner_ip->ip_tos; 289 } 290 291 void 292 dump_packet(void) 293 { 294 u_char *p; 295 int i; 296 297 fprintf(stderr, "packet data:"); 298 for (p = outpacket, i = 0; i < datalen; i++) { 299 if ((i % 24) == 0) 300 fprintf(stderr, "\n "); 301 fprintf(stderr, " %02x", *p++); 302 } 303 fprintf(stderr, "\n"); 304 } 305 306 void 307 build_probe4(struct tr_conf *conf, int seq, u_int8_t ttl) 308 { 309 struct ip *ip = (struct ip *)outpacket; 310 u_char *p = (u_char *)(ip + 1); 311 struct udphdr *up = (struct udphdr *)(p + conf->lsrrlen); 312 struct icmp *icmpp = (struct icmp *)(p + conf->lsrrlen); 313 struct packetdata *op; 314 struct timeval tv; 315 316 ip->ip_len = htons(datalen); 317 ip->ip_ttl = ttl; 318 ip->ip_id = htons(conf->ident+seq); 319 320 switch (conf->proto) { 321 case IPPROTO_ICMP: 322 icmpp->icmp_type = ICMP_ECHO; 323 icmpp->icmp_code = ICMP_CODE; 324 icmpp->icmp_seq = htons(seq); 325 icmpp->icmp_id = htons(conf->ident); 326 op = (struct packetdata *)(icmpp + 1); 327 break; 328 case IPPROTO_UDP: 329 up->uh_sport = htons(conf->ident); 330 up->uh_dport = htons(conf->port+seq); 331 up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - 332 conf->lsrrlen)); 333 up->uh_sum = 0; 334 op = (struct packetdata *)(up + 1); 335 break; 336 default: 337 op = (struct packetdata *)(ip + 1); 338 break; 339 } 340 op->seq = seq; 341 op->ttl = ttl; 342 gettime(&tv); 343 344 /* 345 * We don't want hostiles snooping the net to get any useful 346 * information about us. Send the timestamp in network byte order, 347 * and perturb the timestamp enough that they won't know our 348 * real clock ticker. We don't want to perturb the time by too 349 * much: being off by a suspiciously large amount might indicate 350 * OpenBSD. 351 * 352 * The timestamps in the packet are currently unused. If future 353 * work wants to use them they will have to subtract out the 354 * perturbation first. 355 */ 356 gettime(&tv); 357 op->sec = htonl(tv.tv_sec + sec_perturb); 358 op->usec = htonl((tv.tv_usec + usec_perturb) % 1000000); 359 360 if (conf->proto == IPPROTO_ICMP) { 361 icmpp->icmp_cksum = 0; 362 icmpp->icmp_cksum = in_cksum((u_short *)icmpp, 363 datalen - sizeof(struct ip) - conf->lsrrlen); 364 if (icmpp->icmp_cksum == 0) 365 icmpp->icmp_cksum = 0xffff; 366 } 367 } 368 369 void 370 build_probe6(struct tr_conf *conf, int seq, u_int8_t hops, 371 struct sockaddr *to) 372 { 373 struct timeval tv; 374 struct packetdata *op; 375 int i; 376 377 i = hops; 378 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 379 (char *)&i, sizeof(i)) == -1) 380 warn("setsockopt IPV6_UNICAST_HOPS"); 381 382 383 ((struct sockaddr_in6*)to)->sin6_port = htons(conf->port + seq); 384 385 gettime(&tv); 386 387 if (conf->proto == IPPROTO_ICMP) { 388 struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket; 389 390 icp->icmp6_type = ICMP6_ECHO_REQUEST; 391 icp->icmp6_code = 0; 392 icp->icmp6_cksum = 0; 393 icp->icmp6_id = conf->ident; 394 icp->icmp6_seq = htons(seq); 395 op = (struct packetdata *)(outpacket + 396 sizeof(struct icmp6_hdr)); 397 } else 398 op = (struct packetdata *)outpacket; 399 op->seq = seq; 400 op->ttl = hops; 401 op->sec = htonl(tv.tv_sec); 402 op->usec = htonl(tv.tv_usec); 403 } 404 405 void 406 send_probe(struct tr_conf *conf, int seq, u_int8_t ttl, struct sockaddr *to) 407 { 408 int i; 409 410 switch (to->sa_family) { 411 case AF_INET: 412 build_probe4(conf, seq, ttl); 413 break; 414 case AF_INET6: 415 build_probe6(conf, seq, ttl, to); 416 break; 417 default: 418 errx(1, "unsupported AF: %d", to->sa_family); 419 break; 420 } 421 422 if (conf->dump) 423 dump_packet(); 424 425 i = sendto(sndsock, outpacket, datalen, 0, to, to->sa_len); 426 if (i == -1 || i != datalen) { 427 if (i == -1) 428 warn("sendto"); 429 printf("%s: wrote %s %d chars, ret=%d\n", __progname, hostname, 430 datalen, i); 431 (void) fflush(stdout); 432 } 433 } 434 435 double 436 deltaT(struct timeval *t1p, struct timeval *t2p) 437 { 438 double dt; 439 440 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 441 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 442 return (dt); 443 } 444 445 static char *ttab[] = { 446 "Echo Reply", 447 "ICMP 1", 448 "ICMP 2", 449 "Dest Unreachable", 450 "Source Quench", 451 "Redirect", 452 "ICMP 6", 453 "ICMP 7", 454 "Echo", 455 "Router Advert", 456 "Router Solicit", 457 "Time Exceeded", 458 "Param Problem", 459 "Timestamp", 460 "Timestamp Reply", 461 "Info Request", 462 "Info Reply", 463 "Mask Request", 464 "Mask Reply" 465 }; 466 467 /* 468 * Convert an ICMP "type" field to a printable string. 469 */ 470 char * 471 pr_type(u_int8_t t) 472 { 473 if (t > 18) 474 return ("OUT-OF-RANGE"); 475 return (ttab[t]); 476 } 477 478 int 479 packet_ok(struct tr_conf *conf, int af, struct msghdr *mhdr, int cc, int *seq) 480 { 481 switch (af) { 482 case AF_INET: 483 return packet_ok4(conf, mhdr, cc, seq); 484 break; 485 case AF_INET6: 486 return packet_ok6(conf, mhdr, cc, seq); 487 break; 488 default: 489 errx(1, "unsupported AF: %d", af); 490 break; 491 } 492 } 493 494 int 495 packet_ok4(struct tr_conf *conf, struct msghdr *mhdr, int cc, int *seq) 496 { 497 struct sockaddr_in *from = (struct sockaddr_in *)mhdr->msg_name; 498 struct icmp *icp; 499 u_char code; 500 char *buf = (char *)mhdr->msg_iov[0].iov_base; 501 u_int8_t type; 502 int hlen; 503 struct ip *ip; 504 505 ip = (struct ip *) buf; 506 hlen = ip->ip_hl << 2; 507 if (cc < hlen + ICMP_MINLEN) { 508 if (conf->verbose) 509 printf("packet too short (%d bytes) from %s\n", cc, 510 inet_ntoa(from->sin_addr)); 511 return (0); 512 } 513 cc -= hlen; 514 icp = (struct icmp *)(buf + hlen); 515 type = icp->icmp_type; 516 code = icp->icmp_code; 517 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 518 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { 519 struct ip *hip; 520 struct udphdr *up; 521 struct icmp *icmpp; 522 523 hip = &icp->icmp_ip; 524 hlen = hip->ip_hl << 2; 525 526 switch (conf->proto) { 527 case IPPROTO_ICMP: 528 if (type == ICMP_ECHOREPLY && 529 icp->icmp_id == htons(conf->ident)) { 530 *seq = ntohs(icp->icmp_seq); 531 return (-2); /* we got there */ 532 } 533 icmpp = (struct icmp *)((u_char *)hip + hlen); 534 if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && 535 icmpp->icmp_id == htons(conf->ident)) { 536 *seq = ntohs(icmpp->icmp_seq); 537 return (type == ICMP_TIMXCEED? -1 : code + 1); 538 } 539 break; 540 541 case IPPROTO_UDP: 542 up = (struct udphdr *)((u_char *)hip + hlen); 543 if (hlen + 12 <= cc && hip->ip_p == conf->proto && 544 up->uh_sport == htons(conf->ident)) { 545 *seq = ntohs(up->uh_dport) - conf->port; 546 return (type == ICMP_TIMXCEED? -1 : code + 1); 547 } 548 break; 549 default: 550 /* this is some odd, user specified proto, 551 * how do we check it? 552 */ 553 if (hip->ip_p == conf->proto) 554 return (type == ICMP_TIMXCEED? -1 : code + 1); 555 } 556 } 557 if (conf->verbose) { 558 int i; 559 in_addr_t *lp = (in_addr_t *)&icp->icmp_ip; 560 561 printf("\n%d bytes from %s", cc, inet_ntoa(from->sin_addr)); 562 printf(" to %s", inet_ntoa(ip->ip_dst)); 563 printf(": icmp type %u (%s) code %d\n", type, pr_type(type), 564 icp->icmp_code); 565 for (i = 4; i < cc ; i += sizeof(in_addr_t)) 566 printf("%2d: x%8.8lx\n", i, (unsigned long)*lp++); 567 } 568 return (0); 569 } 570 571 int 572 packet_ok6(struct tr_conf *conf, struct msghdr *mhdr, int cc, int *seq) 573 { 574 struct icmp6_hdr *icp; 575 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 576 u_char type, code; 577 char *buf = (char *)mhdr->msg_iov[0].iov_base; 578 struct cmsghdr *cm; 579 int *hlimp; 580 char hbuf[NI_MAXHOST]; 581 int useicmp = (conf->proto == IPPROTO_ICMP); 582 583 if (cc < sizeof(struct icmp6_hdr)) { 584 if (conf->verbose) { 585 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 586 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 587 strlcpy(hbuf, "invalid", sizeof(hbuf)); 588 printf("packet too short (%d bytes) from %s\n", cc, 589 hbuf); 590 } 591 return(0); 592 } 593 icp = (struct icmp6_hdr *)buf; 594 /* get optional information via advanced API */ 595 rcvpktinfo = NULL; 596 hlimp = NULL; 597 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 598 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 599 if (cm->cmsg_level == IPPROTO_IPV6 && 600 cm->cmsg_type == IPV6_PKTINFO && 601 cm->cmsg_len == 602 CMSG_LEN(sizeof(struct in6_pktinfo))) 603 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 604 605 if (cm->cmsg_level == IPPROTO_IPV6 && 606 cm->cmsg_type == IPV6_HOPLIMIT && 607 cm->cmsg_len == CMSG_LEN(sizeof(int))) 608 hlimp = (int *)CMSG_DATA(cm); 609 } 610 if (rcvpktinfo == NULL || hlimp == NULL) { 611 warnx("failed to get received hop limit or packet info"); 612 rcvhlim = 0; /*XXX*/ 613 } else 614 rcvhlim = *hlimp; 615 616 type = icp->icmp6_type; 617 code = icp->icmp6_code; 618 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 619 || type == ICMP6_DST_UNREACH) { 620 struct ip6_hdr *hip; 621 struct udphdr *up; 622 623 hip = (struct ip6_hdr *)(icp + 1); 624 if ((up = get_udphdr(conf, hip, (u_char *)(buf + cc))) == 625 NULL) { 626 if (conf->verbose) 627 warnx("failed to get upper layer header"); 628 return(0); 629 } 630 if (useicmp && 631 ((struct icmp6_hdr *)up)->icmp6_id == conf->ident) { 632 *seq = ntohs(((struct icmp6_hdr *)up)->icmp6_seq); 633 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 634 } else if (!useicmp && 635 up->uh_sport == htons(srcport)) { 636 *seq = ntohs(up->uh_dport) - conf->port; 637 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 638 } 639 } else if (useicmp && type == ICMP6_ECHO_REPLY) { 640 if (icp->icmp6_id == conf->ident) { 641 *seq = ntohs(icp->icmp6_seq); 642 return (-2); 643 } 644 } 645 if (conf->verbose) { 646 char sbuf[NI_MAXHOST], dbuf[INET6_ADDRSTRLEN]; 647 u_int8_t *p; 648 int i; 649 650 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 651 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 652 strlcpy(sbuf, "invalid", sizeof(sbuf)); 653 printf("\n%d bytes from %s to %s", cc, sbuf, 654 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 655 dbuf, sizeof(dbuf)) : "?"); 656 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 657 icp->icmp6_code); 658 p = (u_int8_t *)(icp + 1); 659 #define WIDTH 16 660 for (i = 0; i < cc; i++) { 661 if (i % WIDTH == 0) 662 printf("%04x:", i); 663 if (i % 4 == 0) 664 printf(" "); 665 printf("%02x", p[i]); 666 if (i % WIDTH == WIDTH - 1) 667 printf("\n"); 668 } 669 if (cc % WIDTH != 0) 670 printf("\n"); 671 } 672 return(0); 673 } 674 675 void 676 print(struct tr_conf *conf, struct sockaddr *from, int cc, const char *to, 677 struct tr_result *tr_res) 678 { 679 struct asr_query *aq; 680 char hbuf[NI_MAXHOST]; 681 682 if (getnameinfo(from, from->sa_len, 683 tr_res->hbuf, sizeof(tr_res->hbuf), NULL, 0, NI_NUMERICHOST) != 0) 684 strlcpy(tr_res->hbuf, "invalid", sizeof(hbuf)); 685 686 if (!conf->nflag) { 687 aq = getnameinfo_async(from, from->sa_len, tr_res->inetname, 688 sizeof(tr_res->inetname), NULL, 0, NI_NAMEREQD, NULL); 689 if (aq != NULL) 690 event_asr_run(aq, getnameinfo_async_done, tr_res); 691 else { 692 waiting_ttls[tr_res->row]--; 693 tr_res->inetname_done = 1; /* use hbuf */ 694 } 695 } 696 697 if (conf->Aflag) 698 print_asn((struct sockaddr_storage *)from, tr_res); 699 700 strlcpy(tr_res->to, to, sizeof(tr_res->to)); 701 tr_res->cc = cc; 702 } 703 704 /* 705 * Increment pointer until find the UDP or ICMP header. 706 */ 707 struct udphdr * 708 get_udphdr(struct tr_conf *conf, struct ip6_hdr *ip6, u_char *lim) 709 { 710 u_char *cp = (u_char *)ip6, nh; 711 int hlen; 712 int useicmp = (conf->proto == IPPROTO_ICMP); 713 714 if (cp + sizeof(*ip6) >= lim) 715 return(NULL); 716 717 nh = ip6->ip6_nxt; 718 cp += sizeof(struct ip6_hdr); 719 720 while (lim - cp >= 8) { 721 switch (nh) { 722 case IPPROTO_ESP: 723 case IPPROTO_TCP: 724 return(NULL); 725 case IPPROTO_ICMPV6: 726 return(useicmp ? (struct udphdr *)cp : NULL); 727 case IPPROTO_UDP: 728 return(useicmp ? NULL : (struct udphdr *)cp); 729 case IPPROTO_FRAGMENT: 730 hlen = sizeof(struct ip6_frag); 731 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 732 break; 733 case IPPROTO_AH: 734 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 735 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 736 break; 737 default: 738 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 739 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 740 break; 741 } 742 743 cp += hlen; 744 } 745 746 return(NULL); 747 } 748 749 void 750 icmp_code(int af, int code, int *got_there, int *unreachable, 751 struct tr_result *tr_res) 752 { 753 switch (af) { 754 case AF_INET: 755 icmp4_code(code, got_there, unreachable, tr_res); 756 break; 757 case AF_INET6: 758 icmp6_code(code, got_there, unreachable, tr_res); 759 break; 760 default: 761 errx(1, "unsupported AF: %d", af); 762 break; 763 } 764 } 765 766 void 767 icmp4_code(int code, int *got_there, int *unreachable, struct tr_result *tr_res) 768 { 769 struct ip *ip = (struct ip *)packet; 770 771 switch (code) { 772 case ICMP_UNREACH_PORT: 773 if (ip->ip_ttl <= 1) 774 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), 775 "%s", " !"); 776 ++(*got_there); 777 break; 778 case ICMP_UNREACH_NET: 779 ++(*unreachable); 780 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 781 " !N"); 782 break; 783 case ICMP_UNREACH_HOST: 784 ++(*unreachable); 785 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 786 " !H"); 787 break; 788 case ICMP_UNREACH_PROTOCOL: 789 ++(*got_there); 790 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 791 " !P"); 792 break; 793 case ICMP_UNREACH_NEEDFRAG: 794 ++(*unreachable); 795 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 796 " !F"); 797 break; 798 case ICMP_UNREACH_SRCFAIL: 799 ++(*unreachable); 800 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 801 " !S"); 802 break; 803 case ICMP_UNREACH_FILTER_PROHIB: 804 ++(*unreachable); 805 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 806 " !X"); 807 break; 808 case ICMP_UNREACH_NET_PROHIB: /*misuse*/ 809 ++(*unreachable); 810 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 811 " !A"); 812 break; 813 case ICMP_UNREACH_HOST_PROHIB: 814 ++(*unreachable); 815 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 816 " !C"); 817 break; 818 case ICMP_UNREACH_NET_UNKNOWN: 819 case ICMP_UNREACH_HOST_UNKNOWN: 820 ++(*unreachable); 821 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 822 " !U"); 823 break; 824 case ICMP_UNREACH_ISOLATED: 825 ++(*unreachable); 826 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 827 " !I"); 828 break; 829 case ICMP_UNREACH_TOSNET: 830 case ICMP_UNREACH_TOSHOST: 831 ++(*unreachable); 832 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 833 " !T"); 834 break; 835 default: 836 ++(*unreachable); 837 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), " !<%d>", 838 code & 0xff); 839 break; 840 } 841 } 842 843 void 844 icmp6_code(int code, int *got_there, int *unreachable, struct tr_result *tr_res) 845 { 846 switch (code) { 847 case ICMP6_DST_UNREACH_NOROUTE: 848 ++(*unreachable); 849 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 850 " !N"); 851 break; 852 case ICMP6_DST_UNREACH_ADMIN: 853 ++(*unreachable); 854 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 855 " !P"); 856 break; 857 case ICMP6_DST_UNREACH_BEYONDSCOPE: 858 ++(*unreachable); 859 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 860 " !S"); 861 break; 862 case ICMP6_DST_UNREACH_ADDR: 863 ++(*unreachable); 864 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), "%s", 865 " !A"); 866 break; 867 case ICMP6_DST_UNREACH_NOPORT: 868 if (rcvhlim <= 1) 869 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), 870 "%s", " !"); 871 ++(*got_there); 872 break; 873 default: 874 ++(*unreachable); 875 snprintf(tr_res->icmp_code, sizeof(tr_res->icmp_code), " !<%d>", 876 code & 0xff); 877 break; 878 } 879 } 880 881 /* 882 * Checksum routine for Internet Protocol family headers (C Version) 883 */ 884 u_short 885 in_cksum(u_short *addr, int len) 886 { 887 u_short *w = addr, answer; 888 int nleft = len, sum = 0; 889 890 /* 891 * Our algorithm is simple, using a 32 bit accumulator (sum), 892 * we add sequential 16 bit words to it, and at the end, fold 893 * back all the carry bits from the top 16 bits into the lower 894 * 16 bits. 895 */ 896 while (nleft > 1) { 897 sum += *w++; 898 nleft -= 2; 899 } 900 901 /* mop up an odd byte, if necessary */ 902 if (nleft == 1) 903 sum += *(u_char *)w; 904 905 /* 906 * add back carry outs from top 16 bits to low 16 bits 907 */ 908 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 909 sum += (sum >> 16); /* add carry */ 910 answer = ~sum; /* truncate to 16 bits */ 911 return (answer); 912 } 913 914 void 915 print_asn(struct sockaddr_storage *ss, struct tr_result *tr_res) 916 { 917 struct asr_query *aq; 918 const u_char *uaddr; 919 char qbuf[MAXDNAME]; 920 921 switch (ss->ss_family) { 922 case AF_INET: 923 uaddr = (const u_char *)&((struct sockaddr_in *) ss)->sin_addr; 924 if (snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u." 925 "origin.asn.cymru.com", 926 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 927 (uaddr[1] & 0xff), (uaddr[0] & 0xff)) >= sizeof (qbuf)) 928 return; 929 break; 930 case AF_INET6: 931 uaddr = (const u_char *)&((struct sockaddr_in6 *) ss)->sin6_addr; 932 if (snprintf(qbuf, sizeof qbuf, 933 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 934 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 935 "origin6.asn.cymru.com", 936 (uaddr[15] & 0x0f), ((uaddr[15] >>4)& 0x0f), 937 (uaddr[14] & 0x0f), ((uaddr[14] >>4)& 0x0f), 938 (uaddr[13] & 0x0f), ((uaddr[13] >>4)& 0x0f), 939 (uaddr[12] & 0x0f), ((uaddr[12] >>4)& 0x0f), 940 (uaddr[11] & 0x0f), ((uaddr[11] >>4)& 0x0f), 941 (uaddr[10] & 0x0f), ((uaddr[10] >>4)& 0x0f), 942 (uaddr[9] & 0x0f), ((uaddr[9] >>4)& 0x0f), 943 (uaddr[8] & 0x0f), ((uaddr[8] >>4)& 0x0f), 944 (uaddr[7] & 0x0f), ((uaddr[7] >>4)& 0x0f), 945 (uaddr[6] & 0x0f), ((uaddr[6] >>4)& 0x0f), 946 (uaddr[5] & 0x0f), ((uaddr[5] >>4)& 0x0f), 947 (uaddr[4] & 0x0f), ((uaddr[4] >>4)& 0x0f), 948 (uaddr[3] & 0x0f), ((uaddr[3] >>4)& 0x0f), 949 (uaddr[2] & 0x0f), ((uaddr[2] >>4)& 0x0f), 950 (uaddr[1] & 0x0f), ((uaddr[1] >>4)& 0x0f), 951 (uaddr[0] & 0x0f), ((uaddr[0] >>4)& 0x0f)) >= sizeof (qbuf)) 952 return; 953 break; 954 default: 955 return; 956 } 957 958 if ((aq = getrrsetbyname_async(qbuf, C_IN, T_TXT, 0, NULL)) != NULL) 959 event_asr_run(aq, getrrsetbyname_async_done, tr_res); 960 else { 961 waiting_ttls[tr_res->row]--; 962 tr_res->asn_done = 1; 963 } 964 } 965 966 int 967 map_tos(char *s, int *val) 968 { 969 /* DiffServ Codepoints and other TOS mappings */ 970 const struct toskeywords { 971 const char *keyword; 972 int val; 973 } *t, toskeywords[] = { 974 { "af11", IPTOS_DSCP_AF11 }, 975 { "af12", IPTOS_DSCP_AF12 }, 976 { "af13", IPTOS_DSCP_AF13 }, 977 { "af21", IPTOS_DSCP_AF21 }, 978 { "af22", IPTOS_DSCP_AF22 }, 979 { "af23", IPTOS_DSCP_AF23 }, 980 { "af31", IPTOS_DSCP_AF31 }, 981 { "af32", IPTOS_DSCP_AF32 }, 982 { "af33", IPTOS_DSCP_AF33 }, 983 { "af41", IPTOS_DSCP_AF41 }, 984 { "af42", IPTOS_DSCP_AF42 }, 985 { "af43", IPTOS_DSCP_AF43 }, 986 { "critical", IPTOS_PREC_CRITIC_ECP }, 987 { "cs0", IPTOS_DSCP_CS0 }, 988 { "cs1", IPTOS_DSCP_CS1 }, 989 { "cs2", IPTOS_DSCP_CS2 }, 990 { "cs3", IPTOS_DSCP_CS3 }, 991 { "cs4", IPTOS_DSCP_CS4 }, 992 { "cs5", IPTOS_DSCP_CS5 }, 993 { "cs6", IPTOS_DSCP_CS6 }, 994 { "cs7", IPTOS_DSCP_CS7 }, 995 { "ef", IPTOS_DSCP_EF }, 996 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 997 { "lowdelay", IPTOS_LOWDELAY }, 998 { "netcontrol", IPTOS_PREC_NETCONTROL }, 999 { "reliability", IPTOS_RELIABILITY }, 1000 { "throughput", IPTOS_THROUGHPUT }, 1001 { NULL, -1 }, 1002 }; 1003 1004 for (t = toskeywords; t->keyword != NULL; t++) { 1005 if (strcmp(s, t->keyword) == 0) { 1006 *val = t->val; 1007 return (1); 1008 } 1009 } 1010 1011 return (0); 1012 } 1013 1014 void 1015 gettime(struct timeval *tv) 1016 { 1017 struct timespec ts; 1018 1019 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) 1020 err(1, "clock_gettime(CLOCK_MONOTONIC)"); 1021 1022 TIMESPEC_TO_TIMEVAL(tv, &ts); 1023 } 1024 1025 void 1026 check_timeout(struct tr_result *tr_row, struct tr_conf *conf) 1027 { 1028 struct timeval t2; 1029 int i; 1030 1031 gettime(&t2); 1032 1033 for (i = 0; i < conf->nprobes; i++) { 1034 /* we didn't send the probe yet */ 1035 if (tr_row[i].ttl == 0) 1036 return; 1037 /* we got a result, it can no longer timeout */ 1038 if (tr_row[i].dup) 1039 continue; 1040 1041 if (deltaT(&tr_row[i].t1, &t2) > conf->waittime) { 1042 tr_row[i].timeout = 1; 1043 tr_row[i].dup++; /* we "saw" the result */ 1044 waiting_ttls[tr_row[i].row] -= 1045 conf->expected_responses; 1046 } 1047 } 1048 } 1049 1050 void 1051 catchup_result_rows(struct tr_result *tr_results, struct tr_conf *conf) 1052 { 1053 static int timeout_row = 0; 1054 static int print_row = 0; 1055 int i, j, all_timeout = 1; 1056 1057 for (; timeout_row < conf->max_ttl; timeout_row++) { 1058 struct tr_result *tr_row = tr_results + 1059 timeout_row * conf->nprobes; 1060 check_timeout(tr_row, conf); 1061 if (waiting_ttls[timeout_row] > 0) 1062 break; 1063 } 1064 1065 for (i = print_row; i < timeout_row; i++) { 1066 struct tr_result *tr_row = tr_results + i * conf->nprobes; 1067 1068 if (waiting_ttls[i] > 0) 1069 break; 1070 1071 for (j = 0; j < conf->nprobes; j++) { 1072 if (!tr_row[j].timeout) { 1073 all_timeout = 0; 1074 break; 1075 } 1076 } 1077 if (!all_timeout) 1078 break; 1079 } 1080 1081 if (all_timeout && i != conf->max_ttl) 1082 return; 1083 1084 if (i == conf->max_ttl) 1085 print_row = i - 1; /* jump ahead, skip long trail of * * * */ 1086 1087 for (; print_row <= i; print_row++) { 1088 struct tr_result *tr_row = tr_results + 1089 print_row * conf->nprobes; 1090 if (waiting_ttls[print_row] > 0) 1091 break; 1092 print_result_row(tr_row, conf); 1093 } 1094 } 1095 1096 void 1097 print_result_row(struct tr_result *tr_results, struct tr_conf *conf) 1098 { 1099 int i, loss = 0, got_there = 0, unreachable = 0; 1100 char *lastaddr = NULL; 1101 1102 printf("%2u ", tr_results[0].ttl); 1103 for (i = 0; i < conf->nprobes; i++) { 1104 got_there += tr_results[i].got_there; 1105 unreachable += tr_results[i].unreachable; 1106 1107 if (tr_results[i].timeout) { 1108 printf(" %s%s", "*", tr_results[i].icmp_code); 1109 loss++; 1110 continue; 1111 } 1112 1113 if (lastaddr == NULL || strcmp(lastaddr, tr_results[i].hbuf) 1114 != 0) { 1115 if (*tr_results[i].hbuf != '\0') { 1116 if (conf->nflag) 1117 printf(" %s", tr_results[i].hbuf); 1118 else 1119 printf(" %s (%s)", 1120 tr_results[i].inetname[0] == '\0' ? 1121 tr_results[i].hbuf : 1122 tr_results[i].inetname, 1123 tr_results[i].hbuf); 1124 if (conf->Aflag && tr_results[i].asn != NULL) 1125 printf(" %s", tr_results[i].asn); 1126 if (conf->verbose) 1127 printf(" %d bytes to %s", 1128 tr_results[i].cc, 1129 tr_results[i].to); 1130 } 1131 } 1132 lastaddr = tr_results[i].hbuf; 1133 printf(" %g ms%s%s", 1134 deltaT(&tr_results[i].t1, 1135 &tr_results[i].t2), 1136 tr_results[i].tos, 1137 tr_results[i].icmp_code); 1138 if (conf->ttl_flag) 1139 printf(" (%u)", tr_results[i].resp_ttl); 1140 1141 if (tr_results[i].exthdr) 1142 printf("%s", tr_results[i].exthdr); 1143 } 1144 if (conf->sump) 1145 printf(" (%d%% loss)", (loss * 100) / conf->nprobes); 1146 putchar('\n'); 1147 fflush(stdout); 1148 if (got_there || unreachable || tr_results[0].ttl == conf->max_ttl) 1149 exit(0); 1150 } 1151 1152 void 1153 getnameinfo_async_done(struct asr_result *ar, void *arg) 1154 { 1155 static char domain[HOST_NAME_MAX + 1]; 1156 static int first = 1; 1157 struct tr_result *tr_res = arg; 1158 char *cp; 1159 1160 if (first) { 1161 first = 0; 1162 if (gethostname(domain, sizeof(domain)) == 0 && 1163 (cp = strchr(domain, '.')) != NULL) 1164 memmove(domain, cp + 1, strlen(cp + 1) + 1); 1165 else 1166 domain[0] = 0; 1167 } 1168 1169 tr_res->inetname_done = 1; 1170 waiting_ttls[tr_res->row]--; 1171 1172 if (ar->ar_gai_errno == 0) { 1173 if ((cp = strchr(tr_res->inetname, '.')) != NULL && 1174 strcmp(cp + 1, domain) == 0) 1175 *cp = '\0'; 1176 } else 1177 tr_res->inetname[0]='\0'; 1178 } 1179 1180 void 1181 getrrsetbyname_async_done(struct asr_result *ar, void *arg) 1182 { 1183 struct tr_result *tr_res = arg; 1184 struct rrsetinfo *answers; 1185 size_t asn_size = 0, len; 1186 int counter; 1187 char *asn; 1188 1189 tr_res->asn_done = 1; 1190 waiting_ttls[tr_res->row]--; 1191 if (ar->ar_rrset_errno != 0) 1192 return; 1193 1194 answers = ar->ar_rrsetinfo; 1195 1196 if (answers->rri_nrdatas > 0) { 1197 asn_size = answers->rri_nrdatas * sizeof("AS2147483647, ") + 3; 1198 if ((tr_res->asn = calloc(1, asn_size)) == NULL) 1199 err(1, NULL); 1200 asn = tr_res->asn; 1201 } 1202 1203 for (counter = 0; counter < answers->rri_nrdatas; counter++) { 1204 char *p, *as = answers->rri_rdatas[counter].rdi_data; 1205 as++; /* skip first byte, it contains length */ 1206 if ((p = strchr(as,'|'))) { 1207 p[-1] = 0; 1208 len = snprintf(asn, asn_size, "%sAS%s", 1209 counter ? ", " : "[", as); 1210 if (len != -1 && len < asn_size) { 1211 asn += len; 1212 asn_size -= len; 1213 } else 1214 asn_size = 0; 1215 } 1216 } 1217 if (counter && asn_size > 0) 1218 *asn=']'; 1219 1220 freerrset(answers); 1221 } 1222