1 /* $OpenBSD: worker.c,v 1.4 2017/05/28 10:04:27 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, int *last_tos) 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, int curwaittime) 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, curwaittime) > 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(struct tr_conf *conf, 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 + conf->lsrrlen); 257 struct icmp *icmpp = (struct icmp *)(p + conf->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(conf->ident+seq); 264 265 switch (conf->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(conf->ident); 271 op = (struct packetdata *)(icmpp + 1); 272 break; 273 case IPPROTO_UDP: 274 up->uh_sport = htons(conf->ident); 275 if (iflag) 276 up->uh_dport = htons(conf->port+seq); 277 else 278 up->uh_dport = htons(conf->port); 279 up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - 280 conf->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 (conf->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) - conf->lsrrlen); 312 if (icmpp->icmp_cksum == 0) 313 icmpp->icmp_cksum = 0xffff; 314 } 315 } 316 317 void 318 build_probe6(struct tr_conf *conf, int seq, u_int8_t hops, int iflag, 319 struct sockaddr *to) 320 { 321 struct timeval tv; 322 struct packetdata *op; 323 int i; 324 325 i = hops; 326 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 327 (char *)&i, sizeof(i)) < 0) 328 warn("setsockopt IPV6_UNICAST_HOPS"); 329 330 if (iflag) 331 ((struct sockaddr_in6*)to)->sin6_port = htons(conf->port + seq); 332 else 333 ((struct sockaddr_in6*)to)->sin6_port = htons(conf->port); 334 gettime(&tv); 335 336 if (conf->proto == IPPROTO_ICMP) { 337 struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket; 338 339 icp->icmp6_type = ICMP6_ECHO_REQUEST; 340 icp->icmp6_code = 0; 341 icp->icmp6_cksum = 0; 342 icp->icmp6_id = conf->ident; 343 icp->icmp6_seq = htons(seq); 344 op = (struct packetdata *)(outpacket + 345 sizeof(struct icmp6_hdr)); 346 } else 347 op = (struct packetdata *)outpacket; 348 op->seq = seq; 349 op->ttl = hops; 350 op->sec = htonl(tv.tv_sec); 351 op->usec = htonl(tv.tv_usec); 352 } 353 354 void 355 send_probe(struct tr_conf *conf, int seq, u_int8_t ttl, int iflag, 356 struct sockaddr *to) 357 { 358 int i; 359 360 switch (to->sa_family) { 361 case AF_INET: 362 build_probe4(conf, seq, ttl, iflag); 363 break; 364 case AF_INET6: 365 build_probe6(conf, seq, ttl, iflag, to); 366 break; 367 default: 368 errx(1, "unsupported AF: %d", to->sa_family); 369 break; 370 } 371 372 if (conf->dump) 373 dump_packet(); 374 375 i = sendto(sndsock, outpacket, datalen, 0, to, to->sa_len); 376 if (i < 0 || i != datalen) { 377 if (i < 0) 378 warn("sendto"); 379 printf("%s: wrote %s %d chars, ret=%d\n", __progname, hostname, 380 datalen, i); 381 (void) fflush(stdout); 382 } 383 } 384 385 double 386 deltaT(struct timeval *t1p, struct timeval *t2p) 387 { 388 double dt; 389 390 dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + 391 (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; 392 return (dt); 393 } 394 395 static char *ttab[] = { 396 "Echo Reply", 397 "ICMP 1", 398 "ICMP 2", 399 "Dest Unreachable", 400 "Source Quench", 401 "Redirect", 402 "ICMP 6", 403 "ICMP 7", 404 "Echo", 405 "Router Advert", 406 "Router Solicit", 407 "Time Exceeded", 408 "Param Problem", 409 "Timestamp", 410 "Timestamp Reply", 411 "Info Request", 412 "Info Reply", 413 "Mask Request", 414 "Mask Reply" 415 }; 416 417 /* 418 * Convert an ICMP "type" field to a printable string. 419 */ 420 char * 421 pr_type(u_int8_t t) 422 { 423 if (t > 18) 424 return ("OUT-OF-RANGE"); 425 return (ttab[t]); 426 } 427 428 int 429 packet_ok(struct tr_conf *conf, int af, struct msghdr *mhdr, int cc, int seq, 430 int iflag) 431 { 432 switch (af) { 433 case AF_INET: 434 return packet_ok4(conf, mhdr, cc, seq, iflag); 435 break; 436 case AF_INET6: 437 return packet_ok6(conf, mhdr, cc, seq, iflag); 438 break; 439 default: 440 errx(1, "unsupported AF: %d", af); 441 break; 442 } 443 } 444 445 int 446 packet_ok4(struct tr_conf *conf, struct msghdr *mhdr, int cc,int seq, int iflag) 447 { 448 struct sockaddr_in *from = (struct sockaddr_in *)mhdr->msg_name; 449 struct icmp *icp; 450 u_char code; 451 char *buf = (char *)mhdr->msg_iov[0].iov_base; 452 u_int8_t type; 453 int hlen; 454 struct ip *ip; 455 456 ip = (struct ip *) buf; 457 hlen = ip->ip_hl << 2; 458 if (cc < hlen + ICMP_MINLEN) { 459 if (conf->verbose) 460 printf("packet too short (%d bytes) from %s\n", cc, 461 inet_ntoa(from->sin_addr)); 462 return (0); 463 } 464 cc -= hlen; 465 icp = (struct icmp *)(buf + hlen); 466 type = icp->icmp_type; 467 code = icp->icmp_code; 468 if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || 469 type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { 470 struct ip *hip; 471 struct udphdr *up; 472 struct icmp *icmpp; 473 474 hip = &icp->icmp_ip; 475 hlen = hip->ip_hl << 2; 476 477 switch (conf->proto) { 478 case IPPROTO_ICMP: 479 if (icmp_type == ICMP_ECHO && 480 type == ICMP_ECHOREPLY && 481 icp->icmp_id == htons(conf->ident) && 482 icp->icmp_seq == htons(seq)) 483 return (-2); /* we got there */ 484 485 icmpp = (struct icmp *)((u_char *)hip + hlen); 486 if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && 487 icmpp->icmp_id == htons(conf->ident) && 488 icmpp->icmp_seq == htons(seq)) 489 return (type == ICMP_TIMXCEED? -1 : code + 1); 490 break; 491 492 case IPPROTO_UDP: 493 up = (struct udphdr *)((u_char *)hip + hlen); 494 if (hlen + 12 <= cc && hip->ip_p == conf->proto && 495 up->uh_sport == htons(conf->ident) && 496 ((iflag && up->uh_dport == htons(conf->port + 497 seq)) || 498 (!iflag && up->uh_dport == htons(conf->port)))) 499 return (type == ICMP_TIMXCEED? -1 : code + 1); 500 break; 501 default: 502 /* this is some odd, user specified proto, 503 * how do we check it? 504 */ 505 if (hip->ip_p == conf->proto) 506 return (type == ICMP_TIMXCEED? -1 : code + 1); 507 } 508 } 509 if (conf->verbose) { 510 int i; 511 in_addr_t *lp = (in_addr_t *)&icp->icmp_ip; 512 513 printf("\n%d bytes from %s", cc, inet_ntoa(from->sin_addr)); 514 printf(" to %s", inet_ntoa(ip->ip_dst)); 515 printf(": icmp type %u (%s) code %d\n", type, pr_type(type), 516 icp->icmp_code); 517 for (i = 4; i < cc ; i += sizeof(in_addr_t)) 518 printf("%2d: x%8.8lx\n", i, (unsigned long)*lp++); 519 } 520 return (0); 521 } 522 523 int 524 packet_ok6(struct tr_conf *conf, struct msghdr *mhdr, int cc, int seq, 525 int iflag) 526 { 527 struct icmp6_hdr *icp; 528 struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; 529 u_char type, code; 530 char *buf = (char *)mhdr->msg_iov[0].iov_base; 531 struct cmsghdr *cm; 532 int *hlimp; 533 char hbuf[NI_MAXHOST]; 534 int useicmp = (conf->proto == IPPROTO_ICMP); 535 536 if (cc < sizeof(struct icmp6_hdr)) { 537 if (conf->verbose) { 538 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 539 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 540 strlcpy(hbuf, "invalid", sizeof(hbuf)); 541 printf("data too short (%d bytes) from %s\n", cc, hbuf); 542 } 543 return(0); 544 } 545 icp = (struct icmp6_hdr *)buf; 546 /* get optional information via advanced API */ 547 rcvpktinfo = NULL; 548 hlimp = NULL; 549 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; 550 cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { 551 if (cm->cmsg_level == IPPROTO_IPV6 && 552 cm->cmsg_type == IPV6_PKTINFO && 553 cm->cmsg_len == 554 CMSG_LEN(sizeof(struct in6_pktinfo))) 555 rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm)); 556 557 if (cm->cmsg_level == IPPROTO_IPV6 && 558 cm->cmsg_type == IPV6_HOPLIMIT && 559 cm->cmsg_len == CMSG_LEN(sizeof(int))) 560 hlimp = (int *)CMSG_DATA(cm); 561 } 562 if (rcvpktinfo == NULL || hlimp == NULL) { 563 warnx("failed to get received hop limit or packet info"); 564 rcvhlim = 0; /*XXX*/ 565 } else 566 rcvhlim = *hlimp; 567 568 type = icp->icmp6_type; 569 code = icp->icmp6_code; 570 if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) 571 || type == ICMP6_DST_UNREACH) { 572 struct ip6_hdr *hip; 573 struct udphdr *up; 574 575 hip = (struct ip6_hdr *)(icp + 1); 576 if ((up = get_udphdr(conf, hip, (u_char *)(buf + cc))) == 577 NULL) { 578 if (conf->verbose) 579 warnx("failed to get upper layer header"); 580 return(0); 581 } 582 if (useicmp && 583 ((struct icmp6_hdr *)up)->icmp6_id == conf->ident && 584 ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq)) 585 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 586 else if (!useicmp && 587 up->uh_sport == htons(srcport) && 588 ((iflag && up->uh_dport == htons(conf->port + seq)) || 589 (!iflag && up->uh_dport == htons(conf->port)))) 590 return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); 591 } else if (useicmp && type == ICMP6_ECHO_REPLY) { 592 if (icp->icmp6_id == conf->ident && 593 icp->icmp6_seq == htons(seq)) 594 return (ICMP6_DST_UNREACH_NOPORT + 1); 595 } 596 if (conf->verbose) { 597 char sbuf[NI_MAXHOST], dbuf[INET6_ADDRSTRLEN]; 598 u_int8_t *p; 599 int i; 600 601 if (getnameinfo((struct sockaddr *)from, from->sin6_len, 602 sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) 603 strlcpy(sbuf, "invalid", sizeof(sbuf)); 604 printf("\n%d bytes from %s to %s", cc, sbuf, 605 rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, 606 dbuf, sizeof(dbuf)) : "?"); 607 printf(": icmp type %d (%s) code %d\n", type, pr_type(type), 608 icp->icmp6_code); 609 p = (u_int8_t *)(icp + 1); 610 #define WIDTH 16 611 for (i = 0; i < cc; i++) { 612 if (i % WIDTH == 0) 613 printf("%04x:", i); 614 if (i % 4 == 0) 615 printf(" "); 616 printf("%02x", p[i]); 617 if (i % WIDTH == WIDTH - 1) 618 printf("\n"); 619 } 620 if (cc % WIDTH != 0) 621 printf("\n"); 622 } 623 return(0); 624 } 625 626 void 627 print(struct tr_conf *conf, struct sockaddr *from, int cc, const char *to) 628 { 629 char hbuf[NI_MAXHOST]; 630 if (getnameinfo(from, from->sa_len, 631 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 632 strlcpy(hbuf, "invalid", sizeof(hbuf)); 633 if (conf->nflag) 634 printf(" %s", hbuf); 635 else 636 printf(" %s (%s)", inetname(from), hbuf); 637 638 if (conf->Aflag) 639 print_asn((struct sockaddr_storage *)from); 640 641 if (conf->verbose) 642 printf(" %d bytes to %s", cc, to); 643 } 644 645 /* 646 * Increment pointer until find the UDP or ICMP header. 647 */ 648 struct udphdr * 649 get_udphdr(struct tr_conf *conf, struct ip6_hdr *ip6, u_char *lim) 650 { 651 u_char *cp = (u_char *)ip6, nh; 652 int hlen; 653 int useicmp = (conf->proto == IPPROTO_ICMP); 654 655 if (cp + sizeof(*ip6) >= lim) 656 return(NULL); 657 658 nh = ip6->ip6_nxt; 659 cp += sizeof(struct ip6_hdr); 660 661 while (lim - cp >= 8) { 662 switch (nh) { 663 case IPPROTO_ESP: 664 case IPPROTO_TCP: 665 return(NULL); 666 case IPPROTO_ICMPV6: 667 return(useicmp ? (struct udphdr *)cp : NULL); 668 case IPPROTO_UDP: 669 return(useicmp ? NULL : (struct udphdr *)cp); 670 case IPPROTO_FRAGMENT: 671 hlen = sizeof(struct ip6_frag); 672 nh = ((struct ip6_frag *)cp)->ip6f_nxt; 673 break; 674 case IPPROTO_AH: 675 hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2; 676 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 677 break; 678 default: 679 hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3; 680 nh = ((struct ip6_ext *)cp)->ip6e_nxt; 681 break; 682 } 683 684 cp += hlen; 685 } 686 687 return(NULL); 688 } 689 690 void 691 icmp_code(int af, int code, int *got_there, int *unreachable) 692 { 693 switch (af) { 694 case AF_INET: 695 icmp4_code(code, got_there, unreachable); 696 break; 697 case AF_INET6: 698 icmp6_code(code, got_there, unreachable); 699 break; 700 default: 701 errx(1, "unsupported AF: %d", af); 702 break; 703 } 704 } 705 706 void 707 icmp4_code(int code, int *got_there, int *unreachable) 708 { 709 struct ip *ip = (struct ip *)packet; 710 711 switch (code) { 712 case ICMP_UNREACH_PORT: 713 if (ip->ip_ttl <= 1) 714 printf(" !"); 715 ++(*got_there); 716 break; 717 case ICMP_UNREACH_NET: 718 ++(*unreachable); 719 printf(" !N"); 720 break; 721 case ICMP_UNREACH_HOST: 722 ++(*unreachable); 723 printf(" !H"); 724 break; 725 case ICMP_UNREACH_PROTOCOL: 726 ++(*got_there); 727 printf(" !P"); 728 break; 729 case ICMP_UNREACH_NEEDFRAG: 730 ++(*unreachable); 731 printf(" !F"); 732 break; 733 case ICMP_UNREACH_SRCFAIL: 734 ++(*unreachable); 735 printf(" !S"); 736 break; 737 case ICMP_UNREACH_FILTER_PROHIB: 738 ++(*unreachable); 739 printf(" !X"); 740 break; 741 case ICMP_UNREACH_NET_PROHIB: /*misuse*/ 742 ++(*unreachable); 743 printf(" !A"); 744 break; 745 case ICMP_UNREACH_HOST_PROHIB: 746 ++(*unreachable); 747 printf(" !C"); 748 break; 749 case ICMP_UNREACH_NET_UNKNOWN: 750 case ICMP_UNREACH_HOST_UNKNOWN: 751 ++(*unreachable); 752 printf(" !U"); 753 break; 754 case ICMP_UNREACH_ISOLATED: 755 ++(*unreachable); 756 printf(" !I"); 757 break; 758 case ICMP_UNREACH_TOSNET: 759 case ICMP_UNREACH_TOSHOST: 760 ++(*unreachable); 761 printf(" !T"); 762 break; 763 default: 764 ++(*unreachable); 765 printf(" !<%d>", code); 766 break; 767 } 768 } 769 770 void 771 icmp6_code(int code, int *got_there, int *unreachable) 772 { 773 switch (code) { 774 case ICMP6_DST_UNREACH_NOROUTE: 775 ++(*unreachable); 776 printf(" !N"); 777 break; 778 case ICMP6_DST_UNREACH_ADMIN: 779 ++(*unreachable); 780 printf(" !P"); 781 break; 782 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 783 ++(*unreachable); 784 printf(" !S"); 785 break; 786 case ICMP6_DST_UNREACH_ADDR: 787 ++(*unreachable); 788 printf(" !A"); 789 break; 790 case ICMP6_DST_UNREACH_NOPORT: 791 if (rcvhlim >= 0 && rcvhlim <= 1) 792 printf(" !"); 793 ++(*got_there); 794 break; 795 default: 796 ++(*unreachable); 797 printf(" !<%d>", code); 798 break; 799 } 800 } 801 802 /* 803 * Checksum routine for Internet Protocol family headers (C Version) 804 */ 805 u_short 806 in_cksum(u_short *addr, int len) 807 { 808 u_short *w = addr, answer; 809 int nleft = len, sum = 0; 810 811 /* 812 * Our algorithm is simple, using a 32 bit accumulator (sum), 813 * we add sequential 16 bit words to it, and at the end, fold 814 * back all the carry bits from the top 16 bits into the lower 815 * 16 bits. 816 */ 817 while (nleft > 1) { 818 sum += *w++; 819 nleft -= 2; 820 } 821 822 /* mop up an odd byte, if necessary */ 823 if (nleft == 1) 824 sum += *(u_char *)w; 825 826 /* 827 * add back carry outs from top 16 bits to low 16 bits 828 */ 829 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 830 sum += (sum >> 16); /* add carry */ 831 answer = ~sum; /* truncate to 16 bits */ 832 return (answer); 833 } 834 835 /* 836 * Construct an Internet address representation. 837 */ 838 const char * 839 inetname(struct sockaddr *sa) 840 { 841 static char line[NI_MAXHOST], domain[HOST_NAME_MAX + 1]; 842 static int first = 1; 843 char *cp; 844 845 if (first) { 846 first = 0; 847 if (gethostname(domain, sizeof(domain)) == 0 && 848 (cp = strchr(domain, '.')) != NULL) 849 memmove(domain, cp + 1, strlen(cp + 1) + 1); 850 else 851 domain[0] = 0; 852 } 853 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 854 NI_NAMEREQD) == 0) { 855 if ((cp = strchr(line, '.')) != NULL && strcmp(cp + 1, 856 domain) == 0) 857 *cp = '\0'; 858 return (line); 859 } 860 861 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, 862 NI_NUMERICHOST) != 0) 863 return ("invalid"); 864 return (line); 865 } 866 867 void 868 print_asn(struct sockaddr_storage *ss) 869 { 870 struct rrsetinfo *answers = NULL; 871 int counter; 872 const u_char *uaddr; 873 char qbuf[MAXDNAME]; 874 875 switch (ss->ss_family) { 876 case AF_INET: 877 uaddr = (const u_char *)&((struct sockaddr_in *) ss)->sin_addr; 878 if (snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u." 879 "origin.asn.cymru.com", 880 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 881 (uaddr[1] & 0xff), (uaddr[0] & 0xff)) >= sizeof (qbuf)) 882 return; 883 break; 884 case AF_INET6: 885 uaddr = (const u_char *)&((struct sockaddr_in6 *) ss)->sin6_addr; 886 if (snprintf(qbuf, sizeof qbuf, 887 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 888 "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." 889 "origin6.asn.cymru.com", 890 (uaddr[15] & 0x0f), ((uaddr[15] >>4)& 0x0f), 891 (uaddr[14] & 0x0f), ((uaddr[14] >>4)& 0x0f), 892 (uaddr[13] & 0x0f), ((uaddr[13] >>4)& 0x0f), 893 (uaddr[12] & 0x0f), ((uaddr[12] >>4)& 0x0f), 894 (uaddr[11] & 0x0f), ((uaddr[11] >>4)& 0x0f), 895 (uaddr[10] & 0x0f), ((uaddr[10] >>4)& 0x0f), 896 (uaddr[9] & 0x0f), ((uaddr[9] >>4)& 0x0f), 897 (uaddr[8] & 0x0f), ((uaddr[8] >>4)& 0x0f), 898 (uaddr[7] & 0x0f), ((uaddr[7] >>4)& 0x0f), 899 (uaddr[6] & 0x0f), ((uaddr[6] >>4)& 0x0f), 900 (uaddr[5] & 0x0f), ((uaddr[5] >>4)& 0x0f), 901 (uaddr[4] & 0x0f), ((uaddr[4] >>4)& 0x0f), 902 (uaddr[3] & 0x0f), ((uaddr[3] >>4)& 0x0f), 903 (uaddr[2] & 0x0f), ((uaddr[2] >>4)& 0x0f), 904 (uaddr[1] & 0x0f), ((uaddr[1] >>4)& 0x0f), 905 (uaddr[0] & 0x0f), ((uaddr[0] >>4)& 0x0f)) >= sizeof (qbuf)) 906 return; 907 break; 908 default: 909 return; 910 } 911 912 if (getrrsetbyname(qbuf, C_IN, T_TXT, 0, &answers) != 0) 913 return; 914 for (counter = 0; counter < answers->rri_nrdatas; counter++) { 915 char *p, *as = answers->rri_rdatas[counter].rdi_data; 916 as++; /* skip first byte, it contains length */ 917 if ((p = strchr(as,'|'))) { 918 printf(counter ? ", " : " ["); 919 p[-1] = 0; 920 printf("AS%s", as); 921 } 922 } 923 if (counter) 924 printf("]"); 925 926 freerrset(answers); 927 } 928 929 int 930 map_tos(char *s, int *val) 931 { 932 /* DiffServ Codepoints and other TOS mappings */ 933 const struct toskeywords { 934 const char *keyword; 935 int val; 936 } *t, toskeywords[] = { 937 { "af11", IPTOS_DSCP_AF11 }, 938 { "af12", IPTOS_DSCP_AF12 }, 939 { "af13", IPTOS_DSCP_AF13 }, 940 { "af21", IPTOS_DSCP_AF21 }, 941 { "af22", IPTOS_DSCP_AF22 }, 942 { "af23", IPTOS_DSCP_AF23 }, 943 { "af31", IPTOS_DSCP_AF31 }, 944 { "af32", IPTOS_DSCP_AF32 }, 945 { "af33", IPTOS_DSCP_AF33 }, 946 { "af41", IPTOS_DSCP_AF41 }, 947 { "af42", IPTOS_DSCP_AF42 }, 948 { "af43", IPTOS_DSCP_AF43 }, 949 { "critical", IPTOS_PREC_CRITIC_ECP }, 950 { "cs0", IPTOS_DSCP_CS0 }, 951 { "cs1", IPTOS_DSCP_CS1 }, 952 { "cs2", IPTOS_DSCP_CS2 }, 953 { "cs3", IPTOS_DSCP_CS3 }, 954 { "cs4", IPTOS_DSCP_CS4 }, 955 { "cs5", IPTOS_DSCP_CS5 }, 956 { "cs6", IPTOS_DSCP_CS6 }, 957 { "cs7", IPTOS_DSCP_CS7 }, 958 { "ef", IPTOS_DSCP_EF }, 959 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, 960 { "lowdelay", IPTOS_LOWDELAY }, 961 { "netcontrol", IPTOS_PREC_NETCONTROL }, 962 { "reliability", IPTOS_RELIABILITY }, 963 { "throughput", IPTOS_THROUGHPUT }, 964 { NULL, -1 }, 965 }; 966 967 for (t = toskeywords; t->keyword != NULL; t++) { 968 if (strcmp(s, t->keyword) == 0) { 969 *val = t->val; 970 return (1); 971 } 972 } 973 974 return (0); 975 } 976 977 void 978 gettime(struct timeval *tv) 979 { 980 struct timespec ts; 981 982 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) 983 err(1, "clock_gettime(CLOCK_MONOTONIC)"); 984 985 TIMESPEC_TO_TIMEVAL(tv, &ts); 986 } 987