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
print_exthdr(u_char * buf,int cc,struct tr_result * tr_res)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
check_tos(struct ip * ip,int * last_tos,struct tr_result * tr_res)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
dump_packet(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
build_probe4(struct tr_conf * conf,int seq,u_int8_t ttl)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
build_probe6(struct tr_conf * conf,int seq,u_int8_t hops,struct sockaddr * to)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
send_probe(struct tr_conf * conf,int seq,u_int8_t ttl,struct sockaddr * to)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
deltaT(struct timeval * t1p,struct timeval * t2p)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 *
pr_type(u_int8_t t)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
packet_ok(struct tr_conf * conf,int af,struct msghdr * mhdr,int cc,int * seq)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
packet_ok4(struct tr_conf * conf,struct msghdr * mhdr,int cc,int * seq)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
packet_ok6(struct tr_conf * conf,struct msghdr * mhdr,int cc,int * seq)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
print(struct tr_conf * conf,struct sockaddr * from,int cc,const char * to,struct tr_result * tr_res)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 *
get_udphdr(struct tr_conf * conf,struct ip6_hdr * ip6,u_char * lim)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
icmp_code(int af,int code,int * got_there,int * unreachable,struct tr_result * tr_res)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
icmp4_code(int code,int * got_there,int * unreachable,struct tr_result * tr_res)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
icmp6_code(int code,int * got_there,int * unreachable,struct tr_result * tr_res)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
in_cksum(u_short * addr,int len)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
print_asn(struct sockaddr_storage * ss,struct tr_result * tr_res)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
map_tos(char * s,int * val)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
gettime(struct timeval * tv)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
check_timeout(struct tr_result * tr_row,struct tr_conf * conf)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
catchup_result_rows(struct tr_result * tr_results,struct tr_conf * conf)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
print_result_row(struct tr_result * tr_results,struct tr_conf * conf)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
getnameinfo_async_done(struct asr_result * ar,void * arg)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
getrrsetbyname_async_done(struct asr_result * ar,void * arg)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