xref: /openbsd/usr.sbin/traceroute/worker.c (revision 6f40fd34)
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