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
93void		 build_probe4(struct tr_conf *, int, u_int8_t);
94void		 build_probe6(struct tr_conf *, int, u_int8_t,
95		     struct sockaddr *);
96int		 packet_ok4(struct tr_conf *, struct msghdr *, int, int *);
97int		 packet_ok6(struct tr_conf *, struct msghdr *, int, int *);
98void		 icmp4_code(int, int *, int *, struct tr_result *);
99void		 icmp6_code(int, int *, int *, struct tr_result *);
100struct udphdr	*get_udphdr(struct tr_conf *, struct ip6_hdr *, u_char *);
101void		 dump_packet(void);
102void		 print_asn(struct sockaddr_storage *, struct tr_result *);
103u_short		 in_cksum(u_short *, int);
104char		*pr_type(u_int8_t);
105double		 deltaT(struct timeval *, struct timeval *);
106void		 check_timeout(struct tr_result *, struct tr_conf *);
107void		 print_result_row(struct tr_result *, struct tr_conf *);
108void		 getnameinfo_async_done(struct asr_result *, void *);
109void		 getrrsetbyname_async_done(struct asr_result *, void *);
110
111void
112print_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
275void
276check_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
291void
292dump_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
306void
307build_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
369void
370build_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
405void
406send_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
435double
436deltaT(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
445static 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 */
470char *
471pr_type(u_int8_t t)
472{
473	if (t > 18)
474		return ("OUT-OF-RANGE");
475	return (ttab[t]);
476}
477
478int
479packet_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
494int
495packet_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
571int
572packet_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
675void
676print(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 */
707struct udphdr *
708get_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
749void
750icmp_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
766void
767icmp4_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
843void
844icmp6_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 */
884u_short
885in_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
914void
915print_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
966int
967map_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
1014void
1015gettime(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
1025void
1026check_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
1050void
1051catchup_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
1096void
1097print_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
1152void
1153getnameinfo_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
1180void
1181getrrsetbyname_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