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