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