xref: /openbsd-src/sbin/ping/ping.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ping.c,v 1.214 2016/09/20 15:21:34 deraadt Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1989, 1993
34  *	The Regents of the University of California.  All rights reserved.
35  *
36  * This code is derived from software contributed to Berkeley by
37  * Mike Muuss.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. Neither the name of the University nor the names of its contributors
48  *    may be used to endorse or promote products derived from this software
49  *    without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  */
63 
64 /*
65  * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
66  * measure round-trip-delays and packet loss across network paths.
67  *
68  * Author -
69  *	Mike Muuss
70  *	U. S. Army Ballistic Research Laboratory
71  *	December, 1983
72  *
73  * Status -
74  *	Public Domain.  Distribution Unlimited.
75  * Bugs -
76  *	More statistics could always be gathered.
77  *	This program has to run SUID to ROOT to access the ICMP socket.
78  */
79 
80 #include <sys/types.h>
81 #include <sys/socket.h>
82 #include <sys/time.h>
83 #include <sys/uio.h>
84 
85 #include <netinet/in.h>
86 #include <netinet/ip.h>
87 #include <netinet/ip_icmp.h>
88 #include <netinet/ip_var.h>
89 #include <netinet/ip6.h>
90 #include <netinet/icmp6.h>
91 #include <netinet/ip_ah.h>
92 #include <arpa/inet.h>
93 #include <netdb.h>
94 
95 #include <ctype.h>
96 #include <err.h>
97 #include <errno.h>
98 #include <limits.h>
99 #include <math.h>
100 #include <poll.h>
101 #include <signal.h>
102 #include <siphash.h>
103 #include <stdint.h>
104 #include <stdio.h>
105 #include <stdlib.h>
106 #include <string.h>
107 #include <time.h>
108 #include <unistd.h>
109 
110 struct tv64 {
111 	u_int64_t	tv64_sec;
112 	u_int64_t	tv64_nsec;
113 };
114 
115 struct payload {
116 	struct tv64	tv64;
117 	u_int8_t	mac[SIPHASH_DIGEST_LENGTH];
118 };
119 
120 #define	ECHOLEN		8	/* icmp echo header len excluding time */
121 #define	ECHOTMLEN	sizeof(struct payload)
122 #define	DEFDATALEN	(64 - ECHOLEN)		/* default data length */
123 #define	MAXIPLEN	60
124 #define	MAXICMPLEN	76
125 #define	MAXPAYLOAD	(IP_MAXPACKET - MAXIPLEN - ECHOLEN)
126 #define	IP6LEN		40
127 #define	EXTRA		256	/* for AH and various other headers. weird. */
128 #define	MAXPAYLOAD6	IPV6_MAXPACKET - IP6LEN - ECHOLEN
129 #define	MAXWAIT_DEFAULT	10			/* secs to wait for response */
130 #define	NROUTES		9			/* number of record route slots */
131 
132 #define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
133 #define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
134 #define	SET(bit)	(A(bit) |= B(bit))
135 #define	CLR(bit)	(A(bit) &= (~B(bit)))
136 #define	TST(bit)	(A(bit) & B(bit))
137 
138 /* various options */
139 int options;
140 #define	F_FLOOD		0x0001
141 #define	F_INTERVAL	0x0002
142 #define	F_HOSTNAME	0x0004
143 #define	F_PINGFILLED	0x0008
144 #define	F_QUIET		0x0010
145 #define	F_RROUTE	0x0020
146 #define	F_SO_DEBUG	0x0040
147 /*			0x0080 */
148 #define	F_VERBOSE	0x0100
149 /*			0x0200 */
150 #define	F_HDRINCL	0x0400
151 #define	F_TTL		0x0800
152 /*			0x1000 */
153 #define	F_AUD_RECV	0x2000
154 #define	F_AUD_MISS	0x4000
155 
156 /* multicast options */
157 int moptions;
158 #define	MULTICAST_NOLOOP	0x001
159 #define	MULTICAST_TTL		0x002
160 
161 #define DUMMY_PORT	10101
162 
163 /*
164  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
165  * number of received sequence numbers we can keep track of.  Change 128
166  * to 8192 for complete accuracy...
167  */
168 #define	MAX_DUP_CHK	(8 * 8192)
169 int mx_dup_ck = MAX_DUP_CHK;
170 char rcvd_tbl[MAX_DUP_CHK / 8];
171 
172 int datalen = DEFDATALEN;
173 int maxpayload = MAXPAYLOAD;
174 u_char outpackhdr[IP_MAXPACKET+sizeof(struct ip)];
175 u_char *outpack = outpackhdr+sizeof(struct ip);
176 char BSPACE = '\b';		/* characters written for flood */
177 char DOT = '.';
178 char *hostname;
179 int ident;			/* process id to identify our packets */
180 int v6flag = 0;			/* are we ping6? */
181 
182 /* counters */
183 int64_t npackets;		/* max packets to transmit */
184 int64_t nreceived;		/* # of packets we got back */
185 int64_t nrepeats;		/* number of duplicates */
186 int64_t ntransmitted;		/* sequence # for outbound packets = #sent */
187 int64_t nmissedmax = 1;		/* max value of ntransmitted - nreceived - 1 */
188 struct timeval interval = {1, 0}; /* interval between packets */
189 
190 /* timing */
191 int timing = 0;			/* flag to do timing */
192 int timinginfo = 0;
193 unsigned int maxwait = MAXWAIT_DEFAULT;	/* max seconds to wait for response */
194 double tmin = 999999999.0;	/* minimum round trip time */
195 double tmax = 0.0;		/* maximum round trip time */
196 double tsum = 0.0;		/* sum of all times, for doing average */
197 double tsumsq = 0.0;		/* sum of all times squared, for std. dev. */
198 
199 struct tv64 tv64_offset;
200 SIPHASH_KEY mac_key;
201 
202 struct msghdr smsghdr;
203 struct iovec smsgiov;
204 
205 volatile sig_atomic_t seenalrm;
206 volatile sig_atomic_t seenint;
207 volatile sig_atomic_t seeninfo;
208 
209 void			 fill(char *, char *);
210 void			 summary(void);
211 void			 onsignal(int);
212 void			 retransmit(int);
213 int			 pinger(int);
214 const char		*pr_addr(struct sockaddr *, socklen_t);
215 void			 pr_pack(u_char *, int, struct msghdr *);
216 __dead void		 usage(void);
217 
218 /* IPv4 specific functions */
219 void			 pr_ipopt(int, u_char *);
220 int			 in_cksum(u_short *, int);
221 void			 pr_icmph(struct icmp *);
222 void			 pr_retip(struct ip *);
223 void			 pr_iph(struct ip *);
224 #ifndef SMALL
225 int			 map_tos(char *, int *);
226 #endif	/* SMALL */
227 
228 /* IPv6 specific functions */
229 int			 get_hoplim(struct msghdr *);
230 int			 get_pathmtu(struct msghdr *, struct sockaddr_in6 *);
231 void			 pr_icmph6(struct icmp6_hdr *, u_char *);
232 void			 pr_iph6(struct ip6_hdr *);
233 void			 pr_exthdrs(struct msghdr *);
234 void			 pr_ip6opt(void *);
235 void			 pr_rthdr(void *);
236 void			 pr_retip6(struct ip6_hdr *, u_char *);
237 
238 int
239 main(int argc, char *argv[])
240 {
241 	struct addrinfo hints, *res;
242 	struct itimerval itimer;
243 	struct sockaddr *from, *dst;
244 	struct sockaddr_in from4, dst4;
245 	struct sockaddr_in6 from6, dst6;
246 	struct cmsghdr *scmsg = NULL;
247 	struct in6_pktinfo *pktinfo = NULL;
248 	struct icmp6_filter filt;
249 	socklen_t maxsizelen;
250 	int64_t preload;
251 	int ch, i, optval = 1, packlen, maxsize, error, s;
252 	int df = 0, tos = 0, bufspace = IP_MAXPACKET, hoplimit = -1, mflag = 0;
253 	u_char *datap, *packet, loop = 1;
254 	u_char ttl = MAXTTL;
255 	char *e, *target, hbuf[NI_MAXHOST], *source = NULL;
256 	char rspace[3 + 4 * NROUTES + 1];	/* record route space */
257 	const char *errstr;
258 	double intval;
259 	uid_t uid;
260 	u_int rtableid = 0;
261 	extern char *__progname;
262 
263 	if (strcmp("ping6", __progname) == 0) {
264 		v6flag = 1;
265 		maxpayload = MAXPAYLOAD6;
266 		if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1)
267 			err(1, "socket");
268 	} else {
269 		if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
270 			err(1, "socket");
271 	}
272 
273 	/* revoke privs */
274 	uid = getuid();
275 	if (setresuid(uid, uid, uid) == -1)
276 		err(1, "setresuid");
277 
278 	preload = 0;
279 	datap = &outpack[ECHOLEN + ECHOTMLEN];
280 	while ((ch = getopt(argc, argv, v6flag ?
281 	    "c:dEefHh:I:i:Ll:mNnp:qS:s:V:vw:" :
282 	    "DEI:LRS:c:defHi:l:np:qs:T:t:V:vw:")) != -1) {
283 		switch(ch) {
284 		case 'c':
285 			npackets = strtonum(optarg, 0, INT64_MAX, &errstr);
286 			if (errstr)
287 				errx(1,
288 				    "number of packets to transmit is %s: %s",
289 				    errstr, optarg);
290 			break;
291 		case 'D':
292 			options |= F_HDRINCL;
293 			df = 1;
294 			break;
295 		case 'd':
296 			options |= F_SO_DEBUG;
297 			break;
298 		case 'E':
299 			options |= F_AUD_MISS;
300 			break;
301 		case 'e':
302 			options |= F_AUD_RECV;
303 			break;
304 		case 'f':
305 			if (getuid())
306 				errx(1, "%s", strerror(EPERM));
307 			options |= F_FLOOD;
308 			setvbuf(stdout, NULL, _IONBF, 0);
309 			break;
310 		case 'H':
311 			options |= F_HOSTNAME;
312 			break;
313 		case 'h':		/* hoplimit */
314 			hoplimit = strtonum(optarg, 0, IPV6_MAXHLIM, &errstr);
315 			if (errstr)
316 				errx(1, "hoplimit is %s: %s", errstr, optarg);
317 			break;
318 		case 'I':
319 		case 'S':	/* deprecated */
320 			source = optarg;
321 			break;
322 		case 'i':		/* wait between sending packets */
323 			intval = strtod(optarg, &e);
324 			if (*optarg == '\0' || *e != '\0')
325 				errx(1, "illegal timing interval %s", optarg);
326 			if (intval < 1 && getuid()) {
327 				errx(1, "%s: only root may use interval < 1s",
328 				    strerror(EPERM));
329 			}
330 			interval.tv_sec = (time_t)intval;
331 			interval.tv_usec =
332 			    (long)((intval - interval.tv_sec) * 1000000);
333 			if (interval.tv_sec < 0)
334 				errx(1, "illegal timing interval %s", optarg);
335 			/* less than 1/Hz does not make sense */
336 			if (interval.tv_sec == 0 && interval.tv_usec < 10000) {
337 				warnx("too small interval, raised to 0.01");
338 				interval.tv_usec = 10000;
339 			}
340 			options |= F_INTERVAL;
341 			break;
342 		case 'L':
343 			moptions |= MULTICAST_NOLOOP;
344 			loop = 0;
345 			break;
346 		case 'l':
347 			if (getuid())
348 				errx(1, "%s", strerror(EPERM));
349 			preload = strtonum(optarg, 1, INT64_MAX, &errstr);
350 			if (errstr)
351 				errx(1, "preload value is %s: %s", errstr,
352 				    optarg);
353 			break;
354 		case 'm':
355 			mflag++;
356 			break;
357 		case 'n':
358 			options &= ~F_HOSTNAME;
359 			break;
360 		case 'p':		/* fill buffer with user pattern */
361 			options |= F_PINGFILLED;
362 			fill((char *)datap, optarg);
363 				break;
364 		case 'q':
365 			options |= F_QUIET;
366 			break;
367 		case 'R':
368 			options |= F_RROUTE;
369 			break;
370 		case 's':		/* size of packet to send */
371 			datalen = strtonum(optarg, 0, maxpayload, &errstr);
372 			if (errstr)
373 				errx(1, "packet size is %s: %s", errstr,
374 				    optarg);
375 			break;
376 #ifndef SMALL
377 		case 'T':
378 			options |= F_HDRINCL;
379 			errno = 0;
380 			errstr = NULL;
381 			if (map_tos(optarg, &tos))
382 				break;
383 			if (strlen(optarg) > 1 && optarg[0] == '0' &&
384 			    optarg[1] == 'x')
385 				tos = (int)strtol(optarg, NULL, 16);
386 			else
387 				tos = strtonum(optarg, 0, 255, &errstr);
388 			if (tos < 0 || tos > 255 || errstr || errno)
389 				errx(1, "illegal tos value %s", optarg);
390 			break;
391 #endif	/* SMALL */
392 		case 't':
393 			options |= F_TTL;
394 			ttl = strtonum(optarg, 0, MAXTTL, &errstr);
395 			if (errstr)
396 				errx(1, "ttl value is %s: %s", errstr, optarg);
397 			break;
398 		case 'V':
399 			rtableid = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr);
400 			if (errstr)
401 				errx(1, "rtable value is %s: %s", errstr,
402 				    optarg);
403 			if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
404 			    sizeof(rtableid)) == -1)
405 				err(1, "setsockopt SO_RTABLE");
406 			break;
407 		case 'v':
408 			options |= F_VERBOSE;
409 			break;
410 		case 'w':
411 			maxwait = strtonum(optarg, 1, INT_MAX, &errstr);
412 			if (errstr)
413 				errx(1, "maxwait value is %s: %s",
414 				    errstr, optarg);
415 			break;
416 		default:
417 			usage();
418 		}
419 	}
420 
421 	argc -= optind;
422 	argv += optind;
423 
424 	if (argc != 1)
425 		usage();
426 
427 	memset(&dst4, 0, sizeof(dst4));
428 	memset(&dst6, 0, sizeof(dst6));
429 
430 	target = *argv;
431 
432 	memset(&hints, 0, sizeof(hints));
433 	hints.ai_family = v6flag ? AF_INET6 : AF_INET;
434 	hints.ai_socktype = SOCK_RAW;
435 	hints.ai_protocol = 0;
436 	hints.ai_flags = AI_CANONNAME;
437 	if ((error = getaddrinfo(target, NULL, &hints, &res)))
438 		errx(1, "%s", gai_strerror(error));
439 
440 	switch (res->ai_family) {
441 	case AF_INET:
442 		if (res->ai_addrlen != sizeof(dst4))
443 			errx(1, "size of sockaddr mismatch");
444 		dst = (struct sockaddr *)&dst4;
445 		from = (struct sockaddr *)&from4;
446 		break;
447 	case AF_INET6:
448 		if (res->ai_addrlen != sizeof(dst6))
449 			errx(1, "size of sockaddr mismatch");
450 		dst = (struct sockaddr *)&dst6;
451 		from = (struct sockaddr *)&from6;
452 		break;
453 	default:
454 		errx(1, "unsupported AF: %d", res->ai_family);
455 		break;
456 	}
457 
458 	memcpy(dst, res->ai_addr, res->ai_addrlen);
459 
460 	if (!hostname) {
461 		hostname = res->ai_canonname ? strdup(res->ai_canonname) :
462 		    target;
463 		if (!hostname)
464 			err(1, "malloc");
465 	}
466 
467 	if (res->ai_next) {
468 		if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
469 		    sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
470 			strlcpy(hbuf, "?", sizeof(hbuf));
471 		warnx("Warning: %s has multiple "
472 		    "addresses; using %s", hostname, hbuf);
473 	}
474 	freeaddrinfo(res);
475 
476 	if (source) {
477 		memset(&hints, 0, sizeof(hints));
478 		hints.ai_family = dst->sa_family;
479 		if ((error = getaddrinfo(source, NULL, &hints, &res)))
480 			errx(1, "%s: %s", source, gai_strerror(error));
481 		if (res->ai_addrlen != dst->sa_len)
482 			errx(1, "size of sockaddr mismatch");
483 		memcpy(from, res->ai_addr, res->ai_addrlen);
484 		freeaddrinfo(res);
485 
486 		if (!v6flag && IN_MULTICAST(ntohl(dst4.sin_addr.s_addr))) {
487 			if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
488 			    &from4.sin_addr, sizeof(from4.sin_addr)) < 0)
489 				err(1, "setsockopt IP_MULTICAST_IF");
490 		} else {
491 			if (bind(s, from, from->sa_len) < 0)
492 				err(1, "bind");
493 		}
494 	} else if (options & F_VERBOSE) {
495 		/*
496 		 * get the source address. XXX since we revoked the root
497 		 * privilege, we cannot use a raw socket for this.
498 		 */
499 		int dummy;
500 		socklen_t len = dst->sa_len;
501 
502 		if ((dummy = socket(dst->sa_family, SOCK_DGRAM, 0)) < 0)
503 			err(1, "UDP socket");
504 
505 		memcpy(from, dst, dst->sa_len);
506 		if (v6flag) {
507 			from6.sin6_port = ntohs(DUMMY_PORT);
508 			if (pktinfo &&
509 			    setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,
510 			    (void *)pktinfo, sizeof(*pktinfo)))
511 				err(1, "UDP setsockopt(IPV6_PKTINFO)");
512 
513 			if (hoplimit != -1 &&
514 			    setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
515 			    (void *)&hoplimit, sizeof(hoplimit)))
516 				err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)");
517 
518 			if (hoplimit != -1 &&
519 			    setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
520 			    (void *)&hoplimit, sizeof(hoplimit)))
521 				err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)");
522 		} else {
523 			from4.sin_port = ntohs(DUMMY_PORT);
524 
525 			if ((moptions & MULTICAST_NOLOOP) && setsockopt(dummy,
526 			    IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
527 			    sizeof(loop)) < 0)
528 				err(1, "setsockopt IP_MULTICAST_LOOP");
529 			if ((moptions & MULTICAST_TTL) && setsockopt(dummy,
530 			    IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
531 			    sizeof(ttl)) < 0)
532 				err(1, "setsockopt IP_MULTICAST_TTL");
533 		}
534 
535 		if (rtableid > 0 &&
536 		    setsockopt(dummy, SOL_SOCKET, SO_RTABLE, &rtableid,
537 		    sizeof(rtableid)) < 0)
538 			err(1, "setsockopt(SO_RTABLE)");
539 
540 		if (connect(dummy, from, len) < 0)
541 			err(1, "UDP connect");
542 
543 		if (getsockname(dummy, from, &len) < 0)
544 			err(1, "getsockname");
545 
546 		close(dummy);
547 	}
548 
549 	if (options & F_SO_DEBUG)
550 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &optval,
551 		    sizeof(optval));
552 
553 	if ((options & F_FLOOD) && (options & F_INTERVAL))
554 		errx(1, "-f and -i options are incompatible");
555 
556 	if ((options & F_FLOOD) && (options & (F_AUD_RECV | F_AUD_MISS)))
557 		warnx("No audible output for flood pings");
558 
559 	if (datalen >= sizeof(struct payload))	/* can we time transfer */
560 		timing = 1;
561 
562 	if (v6flag) {
563 		/* in F_VERBOSE case, we may get non-echoreply packets*/
564 		if (options & F_VERBOSE && datalen < 2048) /* XXX 2048? */
565 			packlen = 2048 + IP6LEN + ECHOLEN + EXTRA;
566 		else
567 			packlen = datalen + IP6LEN + ECHOLEN + EXTRA;
568 	} else
569 		packlen = datalen + MAXIPLEN + MAXICMPLEN;
570 	if (!(packet = malloc(packlen)))
571 		err(1, "malloc");
572 
573 	if (!(options & F_PINGFILLED))
574 		for (i = ECHOTMLEN; i < datalen; ++i)
575 			*datap++ = i;
576 
577 	ident = getpid() & 0xFFFF;
578 
579 	/*
580 	 * When trying to send large packets, you must increase the
581 	 * size of both the send and receive buffers...
582 	 */
583 	maxsizelen = sizeof maxsize;
584 	if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &maxsize, &maxsizelen) < 0)
585 		err(1, "getsockopt");
586 	if (maxsize < packlen &&
587 	    setsockopt(s, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(maxsize)) < 0)
588 		err(1, "setsockopt");
589 
590 	/*
591 	 * When pinging the broadcast address, you can get a lot of answers.
592 	 * Doing something so evil is useful if you are trying to stress the
593 	 * ethernet, or just want to fill the arp cache to get some stuff for
594 	 * /etc/ethers.
595 	 */
596 	while (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
597 	    (void*)&bufspace, sizeof(bufspace)) < 0) {
598 		if ((bufspace -= 1024) <= 0)
599 			err(1, "Cannot set the receive buffer size");
600 	}
601 	if (bufspace < IP_MAXPACKET)
602 		warnx("Could only allocate a receive buffer of %d bytes "
603 		    "(default %d)", bufspace, IP_MAXPACKET);
604 
605 	if (v6flag) {
606 		/*
607 		 * let the kernel pass extension headers of incoming packets,
608 		 * for privileged socket options
609 		 */
610 		if ((options & F_VERBOSE) != 0) {
611 			int opton = 1;
612 
613 			if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS,
614 			    &opton, (socklen_t)sizeof(opton)))
615 				err(1, "setsockopt(IPV6_RECVHOPOPTS)");
616 			if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS,
617 			    &opton, (socklen_t)sizeof(opton)))
618 				err(1, "setsockopt(IPV6_RECVDSTOPTS)");
619 			if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
620 			    sizeof(opton)))
621 				err(1, "setsockopt(IPV6_RECVRTHDR)");
622 			ICMP6_FILTER_SETPASSALL(&filt);
623 		} else {
624 			ICMP6_FILTER_SETBLOCKALL(&filt);
625 			ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
626 		}
627 
628 		if ((moptions & MULTICAST_NOLOOP) &&
629 		    setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop,
630 		    sizeof(loop)) < 0)
631 			err(1, "setsockopt IP6_MULTICAST_LOOP");
632 
633 		optval = IPV6_DEFHLIM;
634 		if (IN6_IS_ADDR_MULTICAST(&dst6.sin6_addr))
635 			if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
636 			    &optval, (socklen_t)sizeof(optval)) == -1)
637 				err(1, "IPV6_MULTICAST_HOPS");
638 		if (mflag != 1) {
639 			optval = mflag > 1 ? 0 : 1;
640 
641 			if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
642 			    &optval, (socklen_t)sizeof(optval)) == -1)
643 				err(1, "setsockopt(IPV6_USE_MIN_MTU)");
644 		} else {
645 			optval = 1;
646 			if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU,
647 			    &optval, sizeof(optval)) == -1)
648 				err(1, "setsockopt(IPV6_RECVPATHMTU)");
649 		}
650 
651 		if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
652 		    (socklen_t)sizeof(filt)) < 0)
653 			err(1, "setsockopt(ICMP6_FILTER)");
654 
655 		if (hoplimit != -1) {
656 			/* set IP6 packet options */
657 			if ((scmsg = malloc( CMSG_SPACE(sizeof(int)))) == NULL)
658 				err(1, "malloc");
659 			smsghdr.msg_control = (caddr_t)scmsg;
660 			smsghdr.msg_controllen = CMSG_SPACE(sizeof(int));
661 
662 			scmsg->cmsg_len = CMSG_LEN(sizeof(int));
663 			scmsg->cmsg_level = IPPROTO_IPV6;
664 			scmsg->cmsg_type = IPV6_HOPLIMIT;
665 			*(int *)(CMSG_DATA(scmsg)) = hoplimit;
666 		}
667 
668 		optval = 1;
669 		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
670 		    (socklen_t)sizeof(optval)) < 0)
671 			warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
672 		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,
673 		    (socklen_t)sizeof(optval)) < 0)
674 			warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
675 	} else {
676 		if (options & F_TTL) {
677 			if (IN_MULTICAST(ntohl(dst4.sin_addr.s_addr)))
678 				moptions |= MULTICAST_TTL;
679 			else
680 				options |= F_HDRINCL;
681 		}
682 
683 		if (options & F_RROUTE && options & F_HDRINCL)
684 			errx(1, "-R option and -D or -T, or -t to unicast"
685 			    " destinations are incompatible");
686 
687 		if (options & F_HDRINCL) {
688 			struct ip *ip = (struct ip *)outpackhdr;
689 
690 			setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval,
691 			    sizeof(optval));
692 			ip->ip_v = IPVERSION;
693 			ip->ip_hl = sizeof(struct ip) >> 2;
694 			ip->ip_tos = tos;
695 			ip->ip_id = 0;
696 			ip->ip_off = htons(df ? IP_DF : 0);
697 			ip->ip_ttl = ttl;
698 			ip->ip_p = IPPROTO_ICMP;
699 			if (source)
700 				ip->ip_src = from4.sin_addr;
701 			else
702 				ip->ip_src.s_addr = INADDR_ANY;
703 			ip->ip_dst = dst4.sin_addr;
704 		}
705 
706 		/* record route option */
707 		if (options & F_RROUTE) {
708 			if (IN_MULTICAST(ntohl(dst4.sin_addr.s_addr)))
709 				errx(1, "record route not valid to multicast"
710 				    " destinations");
711 			memset(rspace, 0, sizeof(rspace));
712 			rspace[IPOPT_OPTVAL] = IPOPT_RR;
713 			rspace[IPOPT_OLEN] = sizeof(rspace)-1;
714 			rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
715 			if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
716 			    sizeof(rspace)) < 0) {
717 				perror("ping: record route");
718 				exit(1);
719 			}
720 		}
721 
722 		if ((moptions & MULTICAST_NOLOOP) &&
723 		    setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
724 		    sizeof(loop)) < 0)
725 			err(1, "setsockopt IP_MULTICAST_LOOP");
726 		if ((moptions & MULTICAST_TTL) &&
727 		    setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
728 		    sizeof(ttl)) < 0)
729 			err(1, "setsockopt IP_MULTICAST_TTL");
730 	}
731 
732 	if (options & F_HOSTNAME) {
733 		if (pledge("stdio inet dns", NULL) == -1)
734 			err(1, "pledge");
735 	} else {
736 		if (pledge("stdio inet", NULL) == -1)
737 			err(1, "pledge");
738 	}
739 
740 	arc4random_buf(&tv64_offset, sizeof(tv64_offset));
741 	arc4random_buf(&mac_key, sizeof(mac_key));
742 
743 	printf("PING %s (", hostname);
744 	if (options & F_VERBOSE)
745 		printf("%s --> ", pr_addr(from, from->sa_len));
746 	printf("%s): %d data bytes\n", pr_addr(dst, dst->sa_len), datalen);
747 
748 	smsghdr.msg_name = dst;
749 	smsghdr.msg_namelen = dst->sa_len;
750 	smsgiov.iov_base = (caddr_t)outpack;
751 	smsghdr.msg_iov = &smsgiov;
752 	smsghdr.msg_iovlen = 1;
753 
754 	while (preload--)		/* Fire off them quickies. */
755 		pinger(s);
756 
757 	(void)signal(SIGINT, onsignal);
758 	(void)signal(SIGINFO, onsignal);
759 
760 	if ((options & F_FLOOD) == 0) {
761 		(void)signal(SIGALRM, onsignal);
762 		itimer.it_interval = interval;
763 		itimer.it_value = interval;
764 		(void)setitimer(ITIMER_REAL, &itimer, NULL);
765 		if (ntransmitted == 0)
766 			retransmit(s);
767 	}
768 
769 	seenalrm = seenint = 0;
770 	seeninfo = 0;
771 
772 	for (;;) {
773 		struct msghdr		m;
774 		union {
775 			struct cmsghdr hdr;
776 			u_char buf[CMSG_SPACE(1024)];
777 		}			cmsgbuf;
778 		struct iovec		iov[1];
779 		struct pollfd		pfd;
780 		struct sockaddr_in	peer4;
781 		struct sockaddr_in6	peer6;
782 		ssize_t			cc;
783 		int			timeout;
784 
785 		/* signal handling */
786 		if (seenint)
787 			break;
788 		if (seenalrm) {
789 			retransmit(s);
790 			seenalrm = 0;
791 			if (ntransmitted - nreceived - 1 > nmissedmax) {
792 				nmissedmax = ntransmitted - nreceived - 1;
793 				if (!(options & F_FLOOD) &&
794 				    (options & F_AUD_MISS))
795 					(void)fputc('\a', stderr);
796 			}
797 			continue;
798 		}
799 		if (seeninfo) {
800 			summary();
801 			seeninfo = 0;
802 			continue;
803 		}
804 
805 		if (options & F_FLOOD) {
806 			(void)pinger(s);
807 			timeout = 10;
808 		} else
809 			timeout = INFTIM;
810 
811 		pfd.fd = s;
812 		pfd.events = POLLIN;
813 
814 		if (poll(&pfd, 1, timeout) <= 0)
815 			continue;
816 
817 		if (v6flag) {
818 			m.msg_name = &peer6;
819 			m.msg_namelen = sizeof(peer6);
820 		} else {
821 			m.msg_name = &peer4;
822 			m.msg_namelen = sizeof(peer4);
823 		}
824 		memset(&iov, 0, sizeof(iov));
825 		iov[0].iov_base = (caddr_t)packet;
826 		iov[0].iov_len = packlen;
827 		m.msg_iov = iov;
828 		m.msg_iovlen = 1;
829 		m.msg_control = (caddr_t)&cmsgbuf.buf;
830 		m.msg_controllen = sizeof(cmsgbuf.buf);
831 
832 		cc = recvmsg(s, &m, 0);
833 		if (cc < 0) {
834 			if (errno != EINTR) {
835 				warn("recvmsg");
836 				sleep(1);
837 			}
838 			continue;
839 		} else if (cc == 0) {
840 			int mtu;
841 
842 			/*
843 			 * receive control messages only. Process the
844 			 * exceptions (currently the only possibility is
845 			 * a path MTU notification.)
846 			 */
847 			if ((mtu = get_pathmtu(&m, &dst6)) > 0) {
848 				if ((options & F_VERBOSE) != 0) {
849 					printf("new path MTU (%d) is "
850 					    "notified\n", mtu);
851 				}
852 			}
853 			continue;
854 		} else
855 			pr_pack(packet, cc, &m);
856 
857 		if (npackets && nreceived >= npackets)
858 			break;
859 	}
860 	summary();
861 	exit(nreceived == 0);
862 }
863 
864 void
865 onsignal(int sig)
866 {
867 	switch (sig) {
868 	case SIGALRM:
869 		seenalrm++;
870 		break;
871 	case SIGINT:
872 		seenint++;
873 		break;
874 	case SIGINFO:
875 		seeninfo++;
876 		break;
877 	}
878 }
879 
880 void
881 fill(char *bp, char *patp)
882 {
883 	int ii, jj, kk;
884 	int pat[16];
885 	char *cp;
886 
887 	for (cp = patp; *cp; cp++)
888 		if (!isxdigit((unsigned char)*cp))
889 			errx(1, "patterns must be specified as hex digits");
890 	ii = sscanf(patp,
891 	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
892 	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
893 	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
894 	    &pat[13], &pat[14], &pat[15]);
895 
896 	if (ii > 0)
897 		for (kk = 0;
898 		    kk <= maxpayload - (ECHOLEN + ECHOTMLEN + ii);
899 		    kk += ii)
900 			for (jj = 0; jj < ii; ++jj)
901 				bp[jj + kk] = pat[jj];
902 	if (!(options & F_QUIET)) {
903 		(void)printf("PATTERN: 0x");
904 		for (jj = 0; jj < ii; ++jj)
905 			(void)printf("%02x", bp[jj] & 0xFF);
906 		(void)printf("\n");
907 	}
908 }
909 
910 void
911 summary(void)
912 {
913 	printf("\n--- %s ping statistics ---\n", hostname);
914 	printf("%lld packets transmitted, ", ntransmitted);
915 	printf("%lld packets received, ", nreceived);
916 
917 	if (nrepeats)
918 		printf("%lld duplicates, ", nrepeats);
919 	if (ntransmitted) {
920 		if (nreceived > ntransmitted)
921 			printf("-- somebody's duplicating packets!");
922 		else
923 			printf("%.1f%% packet loss",
924 			    ((((double)ntransmitted - nreceived) * 100) /
925 			    ntransmitted));
926 	}
927 	printf("\n");
928 	if (timinginfo) {
929 		/* Only display average to microseconds */
930 		double num = nreceived + nrepeats;
931 		double avg = tsum / num;
932 		double dev = sqrt(fmax(0, tsumsq / num - avg * avg));
933 		printf("round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
934 		    tmin, avg, tmax, dev);
935 	}
936 }
937 
938 /*
939  * pr_addr --
940  *	Return address in numeric form or a host name
941  */
942 const char *
943 pr_addr(struct sockaddr *addr, socklen_t addrlen)
944 {
945 	static char buf[NI_MAXHOST];
946 	int flag = 0;
947 
948 	if ((options & F_HOSTNAME) == 0)
949 		flag |= NI_NUMERICHOST;
950 
951 	if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0)
952 		return (buf);
953 	else
954 		return "?";
955 }
956 
957 /*
958  * retransmit --
959  *	This routine transmits another ping.
960  */
961 void
962 retransmit(int s)
963 {
964 	struct itimerval itimer;
965 	static int last_time = 0;
966 
967 	if (last_time) {
968 		seenint = 1;	/* break out of ping event loop */
969 		return;
970 	}
971 
972 	if (pinger(s) == 0)
973 		return;
974 
975 	/*
976 	 * If we're not transmitting any more packets, change the timer
977 	 * to wait two round-trip times if we've received any packets or
978 	 * maxwait seconds if we haven't.
979 	 */
980 	if (nreceived) {
981 		itimer.it_value.tv_sec = 2 * tmax / 1000;
982 		if (itimer.it_value.tv_sec == 0)
983 			itimer.it_value.tv_sec = 1;
984 	} else
985 		itimer.it_value.tv_sec = maxwait;
986 	itimer.it_interval.tv_sec = 0;
987 	itimer.it_interval.tv_usec = 0;
988 	itimer.it_value.tv_usec = 0;
989 	(void)setitimer(ITIMER_REAL, &itimer, NULL);
990 
991 	/* When the alarm goes off we are done. */
992 	last_time = 1;
993 }
994 
995 /*
996  * pinger --
997  *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
998  * will be added on by the kernel.  The ID field is our UNIX process ID,
999  * and the sequence number is an ascending integer.  The first 8 bytes
1000  * of the data portion are used to hold a UNIX "timeval" struct in VAX
1001  * byte-order, to compute the round-trip time.
1002  */
1003 int
1004 pinger(int s)
1005 {
1006 	struct icmp *icp = NULL;
1007 	struct icmp6_hdr *icp6 = NULL;
1008 	int cc, i;
1009 	u_int16_t seq;
1010 
1011 	if (npackets && ntransmitted >= npackets)
1012 		return(-1);	/* no more transmission */
1013 
1014 	seq = htons(ntransmitted++);
1015 
1016 	if (v6flag) {
1017 		icp6 = (struct icmp6_hdr *)outpack;
1018 		memset(icp6, 0, sizeof(*icp6));
1019 		icp6->icmp6_cksum = 0;
1020 		icp6->icmp6_type = ICMP6_ECHO_REQUEST;
1021 		icp6->icmp6_code = 0;
1022 		icp6->icmp6_id = htons(ident);
1023 		icp6->icmp6_seq = seq;
1024 	} else {
1025 		icp = (struct icmp *)outpack;
1026 		icp->icmp_type = ICMP_ECHO;
1027 		icp->icmp_code = 0;
1028 		icp->icmp_cksum = 0;
1029 		icp->icmp_seq = seq;
1030 		icp->icmp_id = ident;			/* ID */
1031 	}
1032 	CLR(ntohs(seq) % mx_dup_ck);
1033 
1034 	if (timing) {
1035 		SIPHASH_CTX ctx;
1036 		struct timespec ts;
1037 		struct payload payload;
1038 		struct tv64 *tv64 = &payload.tv64;
1039 
1040 		if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
1041 			err(1, "clock_gettime(CLOCK_MONOTONIC)");
1042 		tv64->tv64_sec = htobe64((u_int64_t)ts.tv_sec +
1043 		    tv64_offset.tv64_sec);
1044 		tv64->tv64_nsec = htobe64((u_int64_t)ts.tv_nsec +
1045 		    tv64_offset.tv64_nsec);
1046 
1047 		SipHash24_Init(&ctx, &mac_key);
1048 		SipHash24_Update(&ctx, tv64, sizeof(*tv64));
1049 		SipHash24_Update(&ctx, &ident, sizeof(ident));
1050 		SipHash24_Update(&ctx, &seq, sizeof(seq));
1051 		SipHash24_Final(&payload.mac, &ctx);
1052 
1053 		memcpy(&outpack[ECHOLEN], &payload, sizeof(payload));
1054 	}
1055 
1056 	cc = ECHOLEN + datalen;
1057 
1058 	if (!v6flag) {
1059 		/* compute ICMP checksum here */
1060 		icp->icmp_cksum = in_cksum((u_short *)icp, cc);
1061 
1062 		if (options & F_HDRINCL) {
1063 			struct ip *ip = (struct ip *)outpackhdr;
1064 
1065 			smsgiov.iov_base = (caddr_t)outpackhdr;
1066 			cc += sizeof(struct ip);
1067 			ip->ip_len = htons(cc);
1068 			ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
1069 		}
1070 	}
1071 
1072 	smsgiov.iov_len = cc;
1073 
1074 	i = sendmsg(s, &smsghdr, 0);
1075 
1076 	if (i < 0 || i != cc) {
1077 		if (i < 0)
1078 			warn("sendmsg");
1079 		printf("ping: wrote %s %d chars, ret=%d\n", hostname, cc, i);
1080 	}
1081 	if (!(options & F_QUIET) && options & F_FLOOD)
1082 		(void)write(STDOUT_FILENO, &DOT, 1);
1083 
1084 	return (0);
1085 }
1086 
1087 /*
1088  * pr_pack --
1089  *	Print out the packet, if it came from us.  This logic is necessary
1090  * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
1091  * which arrive ('tis only fair).  This permits multiple copies of this
1092  * program to be run without having intermingled output (or statistics!).
1093  */
1094 void
1095 pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
1096 {
1097 	struct ip *ip = NULL;
1098 	struct icmp *icp = NULL;
1099 	struct icmp6_hdr *icp6 = NULL;
1100 	struct timespec ts, tp;
1101 	struct payload payload;
1102 	struct sockaddr *from;
1103 	socklen_t fromlen;
1104 	double triptime = 0;
1105 	int i, dupflag;
1106 	int hlen = -1, hoplim = -1, echo_reply = 0;
1107 	u_int16_t seq;
1108 	u_char *cp, *dp;
1109 	char* pkttime;
1110 
1111 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
1112 		err(1, "clock_gettime(CLOCK_MONOTONIC)");
1113 
1114 	if (v6flag) {
1115 		if (!mhdr || !mhdr->msg_name ||
1116 		    mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
1117 		    ((struct sockaddr *)mhdr->msg_name)->sa_family !=
1118 		    AF_INET6) {
1119 			if (options & F_VERBOSE)
1120 				warnx("invalid peername");
1121 			return;
1122 		}
1123 		from = (struct sockaddr *)mhdr->msg_name;
1124 		fromlen = mhdr->msg_namelen;
1125 
1126 		if (cc < sizeof(struct icmp6_hdr)) {
1127 			if (options & F_VERBOSE)
1128 				warnx("packet too short (%d bytes) from %s", cc,
1129 				    pr_addr(from, fromlen));
1130 			return;
1131 		}
1132 		icp6 = (struct icmp6_hdr *)buf;
1133 
1134 		if ((hoplim = get_hoplim(mhdr)) == -1) {
1135 			warnx("failed to get receiving hop limit");
1136 			return;
1137 		}
1138 
1139 		if (icp6->icmp6_type == ICMP6_ECHO_REPLY) {
1140 			if (ntohs(icp6->icmp6_id) != ident)
1141 				return;			/* 'Twas not our ECHO */
1142 			seq = icp6->icmp6_seq;
1143 			echo_reply = 1;
1144 			pkttime = (char *)(icp6 + 1);
1145 		}
1146 	} else {
1147 		if (!mhdr || !mhdr->msg_name ||
1148 		    mhdr->msg_namelen != sizeof(struct sockaddr_in) ||
1149 		    ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET) {
1150 			if (options & F_VERBOSE)
1151 				warnx("invalid peername");
1152 			return;
1153 		}
1154 
1155 		from = (struct sockaddr *)mhdr->msg_name;
1156 		fromlen = mhdr->msg_namelen;
1157 
1158 		/* Check the IP header */
1159 		ip = (struct ip *)buf;
1160 		hlen = ip->ip_hl << 2;
1161 		if (cc < hlen + ICMP_MINLEN) {
1162 			if (options & F_VERBOSE)
1163 				warnx("packet too short (%d bytes) from %s", cc,
1164 				    pr_addr(from, fromlen));
1165 			return;
1166 		}
1167 
1168 		/* Now the ICMP part */
1169 		cc -= hlen;
1170 		icp = (struct icmp *)(buf + hlen);
1171 		if (icp->icmp_type == ICMP_ECHOREPLY) {
1172 			if (icp->icmp_id != ident)
1173 				return;			/* 'Twas not our ECHO */
1174 			seq = icp->icmp_seq;
1175 			echo_reply = 1;
1176 			pkttime = (char *)icp->icmp_data;
1177 		}
1178 	}
1179 
1180 	if (echo_reply) {
1181 		++nreceived;
1182 		if (cc >= ECHOLEN + ECHOTMLEN) {
1183 			SIPHASH_CTX ctx;
1184 			struct tv64 *tv64;
1185 			u_int8_t mac[SIPHASH_DIGEST_LENGTH];
1186 
1187 			memcpy(&payload, pkttime, sizeof(payload));
1188 			tv64 = &payload.tv64;
1189 
1190 			SipHash24_Init(&ctx, &mac_key);
1191 			SipHash24_Update(&ctx, tv64, sizeof(*tv64));
1192 			SipHash24_Update(&ctx, &ident, sizeof(ident));
1193 			SipHash24_Update(&ctx, &seq, sizeof(seq));
1194 			SipHash24_Final(mac, &ctx);
1195 
1196 			if (timingsafe_memcmp(mac, &payload.mac,
1197 			    sizeof(mac)) != 0) {
1198 				(void)printf("signature mismatch!\n");
1199 				return;
1200 			}
1201 			timinginfo=1;
1202 
1203 			tp.tv_sec = betoh64(tv64->tv64_sec) -
1204 			    tv64_offset.tv64_sec;
1205 			tp.tv_nsec = betoh64(tv64->tv64_nsec) -
1206 			    tv64_offset.tv64_nsec;
1207 
1208 			timespecsub(&ts, &tp, &ts);
1209 			triptime = ((double)ts.tv_sec) * 1000.0 +
1210 			    ((double)ts.tv_nsec) / 1000000.0;
1211 			tsum += triptime;
1212 			tsumsq += triptime * triptime;
1213 			if (triptime < tmin)
1214 				tmin = triptime;
1215 			if (triptime > tmax)
1216 				tmax = triptime;
1217 		}
1218 
1219 		if (TST(ntohs(seq) % mx_dup_ck)) {
1220 			++nrepeats;
1221 			--nreceived;
1222 			dupflag = 1;
1223 		} else {
1224 			SET(ntohs(seq) % mx_dup_ck);
1225 			dupflag = 0;
1226 		}
1227 
1228 		if (options & F_QUIET)
1229 			return;
1230 
1231 		if (options & F_FLOOD)
1232 			(void)write(STDOUT_FILENO, &BSPACE, 1);
1233 		else {
1234 			(void)printf("%d bytes from %s: icmp_seq=%u", cc,
1235 			    pr_addr(from, fromlen), ntohs(seq));
1236 			if (v6flag)
1237 				(void)printf(" hlim=%d", hoplim);
1238 			else
1239 				(void)printf(" ttl=%d", ip->ip_ttl);
1240 			if (cc >= ECHOLEN + ECHOTMLEN)
1241 				(void)printf(" time=%.3f ms", triptime);
1242 			if (dupflag)
1243 				(void)printf(" (DUP!)");
1244 			/* check the data */
1245 			if (cc - ECHOLEN < datalen)
1246 				(void)printf(" (TRUNC!)");
1247 			if (v6flag)
1248 				cp = buf + ECHOLEN + ECHOTMLEN;
1249 			else
1250 				cp = (u_char *)&icp->icmp_data[ECHOTMLEN];
1251 			dp = &outpack[ECHOLEN + ECHOTMLEN];
1252 			for (i = ECHOLEN + ECHOTMLEN;
1253 			    i < cc && i < datalen;
1254 			    ++i, ++cp, ++dp) {
1255 				if (*cp != *dp) {
1256 					(void)printf("\nwrong data byte #%d "
1257 					    "should be 0x%x but was 0x%x",
1258 					    i - ECHOLEN, *dp, *cp);
1259 					if (v6flag)
1260 						cp = buf + ECHOLEN;
1261 					else
1262 						cp = (u_char *)
1263 						    &icp->icmp_data[0];
1264 					for (i = ECHOLEN; i < cc && i < datalen;
1265 					    ++i, ++cp) {
1266 						if ((i % 32) == 8)
1267 							(void)printf("\n\t");
1268 						(void)printf("%x ", *cp);
1269 					}
1270 					break;
1271 				}
1272 			}
1273 		}
1274 	} else {
1275 		/* We've got something other than an ECHOREPLY */
1276 		if (!(options & F_VERBOSE))
1277 			return;
1278 		(void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
1279 		if (v6flag)
1280 			pr_icmph6(icp6, buf + cc);
1281 		else
1282 			pr_icmph(icp);
1283 	}
1284 
1285 	/* Display any IP options */
1286 	if (!v6flag && hlen > sizeof(struct ip))
1287 		pr_ipopt(hlen, buf);
1288 
1289 	if (!(options & F_FLOOD)) {
1290 		(void)putchar('\n');
1291 		if (v6flag && (options & F_VERBOSE))
1292 			pr_exthdrs(mhdr);
1293 		(void)fflush(stdout);
1294 		if (options & F_AUD_RECV)
1295 			(void)fputc('\a', stderr);
1296 	}
1297 }
1298 
1299 void
1300 pr_ipopt(int hlen, u_char *buf)
1301 {
1302 	static int old_rrlen;
1303 	static char old_rr[MAX_IPOPTLEN];
1304 	struct sockaddr_in s_in;
1305 	in_addr_t l;
1306 	u_int i, j;
1307 	u_char *cp;
1308 
1309 	cp = buf + sizeof(struct ip);
1310 
1311 	s_in.sin_len = sizeof(s_in);
1312 	s_in.sin_family = AF_INET;
1313 
1314 	for (; hlen > sizeof(struct ip); --hlen, ++cp) {
1315 		switch (*cp) {
1316 		case IPOPT_EOL:
1317 			hlen = 0;
1318 			break;
1319 		case IPOPT_LSRR:
1320 			(void)printf("\nLSRR: ");
1321 			hlen -= 2;
1322 			j = *++cp;
1323 			++cp;
1324 			i = 0;
1325 			if (j > IPOPT_MINOFF) {
1326 				for (;;) {
1327 					l = *++cp;
1328 					l = (l<<8) + *++cp;
1329 					l = (l<<8) + *++cp;
1330 					l = (l<<8) + *++cp;
1331 					if (l == 0)
1332 						(void)printf("\t0.0.0.0");
1333 					else {
1334 						s_in.sin_addr.s_addr = ntohl(l);
1335 						(void)printf("\t%s",
1336 						    pr_addr((struct sockaddr*)
1337 						    &s_in, sizeof(s_in)));
1338 					}
1339 					hlen -= 4;
1340 					j -= 4;
1341 					i += 4;
1342 					if (j <= IPOPT_MINOFF)
1343 						break;
1344 					if (i >= MAX_IPOPTLEN) {
1345 						(void)printf("\t(truncated route)");
1346 						break;
1347 					}
1348 					(void)putchar('\n');
1349 				}
1350 			}
1351 			break;
1352 		case IPOPT_RR:
1353 			j = *++cp;		/* get length */
1354 			i = *++cp;		/* and pointer */
1355 			hlen -= 2;
1356 			if (i > j)
1357 				i = j;
1358 			i -= IPOPT_MINOFF;
1359 			if (i <= 0)
1360 				continue;
1361 			if (i == old_rrlen &&
1362 			    cp == buf + sizeof(struct ip) + 2 &&
1363 			    !memcmp(cp, old_rr, i) &&
1364 			    !(options & F_FLOOD)) {
1365 				(void)printf("\t(same route)");
1366 				i = ((i + 3) / 4) * 4;
1367 				hlen -= i;
1368 				cp += i;
1369 				break;
1370 			}
1371 			if (i < MAX_IPOPTLEN) {
1372 				old_rrlen = i;
1373 				memcpy(old_rr, cp, i);
1374 			} else
1375 				old_rrlen = 0;
1376 
1377 			(void)printf("\nRR: ");
1378 			j = 0;
1379 			for (;;) {
1380 				l = *++cp;
1381 				l = (l<<8) + *++cp;
1382 				l = (l<<8) + *++cp;
1383 				l = (l<<8) + *++cp;
1384 				if (l == 0)
1385 					(void)printf("\t0.0.0.0");
1386 				else {
1387 					s_in.sin_addr.s_addr = ntohl(l);
1388 					(void)printf("\t%s",
1389 					    pr_addr((struct sockaddr*)&s_in,
1390 					    sizeof(s_in)));
1391 				}
1392 				hlen -= 4;
1393 				i -= 4;
1394 				j += 4;
1395 				if (i <= 0)
1396 					break;
1397 				if (j >= MAX_IPOPTLEN) {
1398 					(void)printf("\t(truncated route)");
1399 					break;
1400 				}
1401 				(void)putchar('\n');
1402 			}
1403 			break;
1404 		case IPOPT_NOP:
1405 			(void)printf("\nNOP");
1406 			break;
1407 		default:
1408 			(void)printf("\nunknown option %x", *cp);
1409 			hlen = hlen - (cp[IPOPT_OLEN] - 1);
1410 			cp = cp + (cp[IPOPT_OLEN] - 1);
1411 			break;
1412 		}
1413 	}
1414 }
1415 
1416 /*
1417  * in_cksum --
1418  *	Checksum routine for Internet Protocol family headers (C Version)
1419  */
1420 int
1421 in_cksum(u_short *addr, int len)
1422 {
1423 	int nleft = len;
1424 	u_short *w = addr;
1425 	int sum = 0;
1426 	u_short answer = 0;
1427 
1428 	/*
1429 	 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
1430 	 * sequential 16 bit words to it, and at the end, fold back all the
1431 	 * carry bits from the top 16 bits into the lower 16 bits.
1432 	 */
1433 	while (nleft > 1) {
1434 		sum += *w++;
1435 		nleft -= 2;
1436 	}
1437 
1438 	/* mop up an odd byte, if necessary */
1439 	if (nleft == 1) {
1440 		*(u_char *)(&answer) = *(u_char *)w ;
1441 		sum += answer;
1442 	}
1443 
1444 	/* add back carry outs from top 16 bits to low 16 bits */
1445 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1446 	sum += (sum >> 16);			/* add carry */
1447 	answer = ~sum;				/* truncate to 16 bits */
1448 	return(answer);
1449 }
1450 
1451 /*
1452  * pr_icmph --
1453  *	Print a descriptive string about an ICMP header.
1454  */
1455 void
1456 pr_icmph(struct icmp *icp)
1457 {
1458 	switch(icp->icmp_type) {
1459 	case ICMP_ECHOREPLY:
1460 		(void)printf("Echo Reply\n");
1461 		/* XXX ID + Seq + Data */
1462 		break;
1463 	case ICMP_UNREACH:
1464 		switch(icp->icmp_code) {
1465 		case ICMP_UNREACH_NET:
1466 			(void)printf("Destination Net Unreachable\n");
1467 			break;
1468 		case ICMP_UNREACH_HOST:
1469 			(void)printf("Destination Host Unreachable\n");
1470 			break;
1471 		case ICMP_UNREACH_PROTOCOL:
1472 			(void)printf("Destination Protocol Unreachable\n");
1473 			break;
1474 		case ICMP_UNREACH_PORT:
1475 			(void)printf("Destination Port Unreachable\n");
1476 			break;
1477 		case ICMP_UNREACH_NEEDFRAG:
1478 			if (icp->icmp_nextmtu != 0)
1479 				(void)printf("frag needed and DF set (MTU %d)\n",
1480 				    ntohs(icp->icmp_nextmtu));
1481 			else
1482 				(void)printf("frag needed and DF set\n");
1483 			break;
1484 		case ICMP_UNREACH_SRCFAIL:
1485 			(void)printf("Source Route Failed\n");
1486 			break;
1487 		case ICMP_UNREACH_NET_UNKNOWN:
1488 			(void)printf("Network Unknown\n");
1489 			break;
1490 		case ICMP_UNREACH_HOST_UNKNOWN:
1491 			(void)printf("Host Unknown\n");
1492 			break;
1493 		case ICMP_UNREACH_ISOLATED:
1494 			(void)printf("Source Isolated\n");
1495 			break;
1496 		case ICMP_UNREACH_NET_PROHIB:
1497 			(void)printf("Dest. Net Administratively Prohibited\n");
1498 			break;
1499 		case ICMP_UNREACH_HOST_PROHIB:
1500 			(void)printf("Dest. Host Administratively Prohibited\n");
1501 			break;
1502 		case ICMP_UNREACH_TOSNET:
1503 			(void)printf("Destination Net Unreachable for TOS\n");
1504 			break;
1505 		case ICMP_UNREACH_TOSHOST:
1506 			(void)printf("Destination Host Unreachable for TOS\n");
1507 			break;
1508 		case ICMP_UNREACH_FILTER_PROHIB:
1509 			(void)printf("Route administratively prohibited\n");
1510 			break;
1511 		case ICMP_UNREACH_HOST_PRECEDENCE:
1512 			(void)printf("Host Precedence Violation\n");
1513 			break;
1514 		case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1515 			(void)printf("Precedence Cutoff\n");
1516 			break;
1517 		default:
1518 			(void)printf("Dest Unreachable, Unknown Code: %d\n",
1519 			    icp->icmp_code);
1520 			break;
1521 		}
1522 		/* Print returned IP header information */
1523 		pr_retip((struct ip *)icp->icmp_data);
1524 		break;
1525 	case ICMP_SOURCEQUENCH:
1526 		(void)printf("Source Quench\n");
1527 		pr_retip((struct ip *)icp->icmp_data);
1528 		break;
1529 	case ICMP_REDIRECT:
1530 		switch(icp->icmp_code) {
1531 		case ICMP_REDIRECT_NET:
1532 			(void)printf("Redirect Network");
1533 			break;
1534 		case ICMP_REDIRECT_HOST:
1535 			(void)printf("Redirect Host");
1536 			break;
1537 		case ICMP_REDIRECT_TOSNET:
1538 			(void)printf("Redirect Type of Service and Network");
1539 			break;
1540 		case ICMP_REDIRECT_TOSHOST:
1541 			(void)printf("Redirect Type of Service and Host");
1542 			break;
1543 		default:
1544 			(void)printf("Redirect, Unknown Code: %d", icp->icmp_code);
1545 			break;
1546 		}
1547 		(void)printf("(New addr: %s)\n",
1548 		    inet_ntoa(icp->icmp_gwaddr));
1549 		pr_retip((struct ip *)icp->icmp_data);
1550 		break;
1551 	case ICMP_ECHO:
1552 		(void)printf("Echo Request\n");
1553 		/* XXX ID + Seq + Data */
1554 		break;
1555 	case ICMP_ROUTERADVERT:
1556 		/* RFC1256 */
1557 		(void)printf("Router Discovery Advertisement\n");
1558 		(void)printf("(%d entries, lifetime %d seconds)\n",
1559 		    icp->icmp_num_addrs, ntohs(icp->icmp_lifetime));
1560 		break;
1561 	case ICMP_ROUTERSOLICIT:
1562 		/* RFC1256 */
1563 		(void)printf("Router Discovery Solicitation\n");
1564 		break;
1565 	case ICMP_TIMXCEED:
1566 		switch(icp->icmp_code) {
1567 		case ICMP_TIMXCEED_INTRANS:
1568 			(void)printf("Time to live exceeded\n");
1569 			break;
1570 		case ICMP_TIMXCEED_REASS:
1571 			(void)printf("Frag reassembly time exceeded\n");
1572 			break;
1573 		default:
1574 			(void)printf("Time exceeded, Unknown Code: %d\n",
1575 			    icp->icmp_code);
1576 			break;
1577 		}
1578 		pr_retip((struct ip *)icp->icmp_data);
1579 		break;
1580 	case ICMP_PARAMPROB:
1581 		switch(icp->icmp_code) {
1582 		case ICMP_PARAMPROB_OPTABSENT:
1583 			(void)printf("Parameter problem, required option "
1584 			    "absent: pointer = 0x%02x\n",
1585 			    ntohs(icp->icmp_hun.ih_pptr));
1586 			break;
1587 		default:
1588 			(void)printf("Parameter problem: pointer = 0x%02x\n",
1589 			    ntohs(icp->icmp_hun.ih_pptr));
1590 			break;
1591 		}
1592 		pr_retip((struct ip *)icp->icmp_data);
1593 		break;
1594 	case ICMP_TSTAMP:
1595 		(void)printf("Timestamp\n");
1596 		/* XXX ID + Seq + 3 timestamps */
1597 		break;
1598 	case ICMP_TSTAMPREPLY:
1599 		(void)printf("Timestamp Reply\n");
1600 		/* XXX ID + Seq + 3 timestamps */
1601 		break;
1602 	case ICMP_IREQ:
1603 		(void)printf("Information Request\n");
1604 		/* XXX ID + Seq */
1605 		break;
1606 	case ICMP_IREQREPLY:
1607 		(void)printf("Information Reply\n");
1608 		/* XXX ID + Seq */
1609 		break;
1610 	case ICMP_MASKREQ:
1611 		(void)printf("Address Mask Request\n");
1612 		break;
1613 	case ICMP_MASKREPLY:
1614 		(void)printf("Address Mask Reply (Mask 0x%08x)\n",
1615 		    ntohl(icp->icmp_mask));
1616 		break;
1617 	default:
1618 		(void)printf("Unknown ICMP type: %d\n", icp->icmp_type);
1619 	}
1620 }
1621 
1622 /*
1623  * pr_iph --
1624  *	Print an IP header with options.
1625  */
1626 void
1627 pr_iph(struct ip *ip)
1628 {
1629 	int hlen;
1630 	u_char *cp;
1631 
1632 	hlen = ip->ip_hl << 2;
1633 	cp = (u_char *)ip + 20;		/* point to options */
1634 
1635 	(void)printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
1636 	(void)printf(" %1x  %1x  %02x %04x %04x",
1637 	    ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
1638 	(void)printf("   %1x %04x", ((ip->ip_off) & 0xe000) >> 13,
1639 	    (ip->ip_off) & 0x1fff);
1640 	(void)printf("  %02x  %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);
1641 	(void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
1642 	(void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
1643 	/* dump and option bytes */
1644 	while (hlen-- > 20) {
1645 		(void)printf("%02x", *cp++);
1646 	}
1647 	(void)putchar('\n');
1648 }
1649 
1650 /*
1651  * pr_retip --
1652  *	Dump some info on a returned (via ICMP) IP packet.
1653  */
1654 void
1655 pr_retip(struct ip *ip)
1656 {
1657 	int hlen;
1658 	u_char *cp;
1659 
1660 	pr_iph(ip);
1661 	hlen = ip->ip_hl << 2;
1662 	cp = (u_char *)ip + hlen;
1663 
1664 	if (ip->ip_p == 6)
1665 		(void)printf("TCP: from port %u, to port %u (decimal)\n",
1666 		    (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
1667 	else if (ip->ip_p == 17)
1668 		(void)printf("UDP: from port %u, to port %u (decimal)\n",
1669 		    (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
1670 }
1671 
1672 #ifndef SMALL
1673 int
1674 map_tos(char *key, int *val)
1675 {
1676 	/* DiffServ Codepoints and other TOS mappings */
1677 	const struct toskeywords {
1678 		const char	*keyword;
1679 		int		 val;
1680 	} *t, toskeywords[] = {
1681 		{ "af11",		IPTOS_DSCP_AF11 },
1682 		{ "af12",		IPTOS_DSCP_AF12 },
1683 		{ "af13",		IPTOS_DSCP_AF13 },
1684 		{ "af21",		IPTOS_DSCP_AF21 },
1685 		{ "af22",		IPTOS_DSCP_AF22 },
1686 		{ "af23",		IPTOS_DSCP_AF23 },
1687 		{ "af31",		IPTOS_DSCP_AF31 },
1688 		{ "af32",		IPTOS_DSCP_AF32 },
1689 		{ "af33",		IPTOS_DSCP_AF33 },
1690 		{ "af41",		IPTOS_DSCP_AF41 },
1691 		{ "af42",		IPTOS_DSCP_AF42 },
1692 		{ "af43",		IPTOS_DSCP_AF43 },
1693 		{ "critical",		IPTOS_PREC_CRITIC_ECP },
1694 		{ "cs0",		IPTOS_DSCP_CS0 },
1695 		{ "cs1",		IPTOS_DSCP_CS1 },
1696 		{ "cs2",		IPTOS_DSCP_CS2 },
1697 		{ "cs3",		IPTOS_DSCP_CS3 },
1698 		{ "cs4",		IPTOS_DSCP_CS4 },
1699 		{ "cs5",		IPTOS_DSCP_CS5 },
1700 		{ "cs6",		IPTOS_DSCP_CS6 },
1701 		{ "cs7",		IPTOS_DSCP_CS7 },
1702 		{ "ef",			IPTOS_DSCP_EF },
1703 		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
1704 		{ "lowdelay",		IPTOS_LOWDELAY },
1705 		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
1706 		{ "reliability",	IPTOS_RELIABILITY },
1707 		{ "throughput",		IPTOS_THROUGHPUT },
1708 		{ NULL,			-1 },
1709 	};
1710 
1711 	for (t = toskeywords; t->keyword != NULL; t++) {
1712 		if (strcmp(key, t->keyword) == 0) {
1713 			*val = t->val;
1714 			return (1);
1715 		}
1716 	}
1717 
1718 	return (0);
1719 }
1720 #endif	/* SMALL */
1721 
1722 void
1723 pr_exthdrs(struct msghdr *mhdr)
1724 {
1725 	struct cmsghdr *cm;
1726 
1727 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1728 	    cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1729 		if (cm->cmsg_level != IPPROTO_IPV6)
1730 			continue;
1731 
1732 		switch (cm->cmsg_type) {
1733 		case IPV6_HOPOPTS:
1734 			printf("  HbH Options: ");
1735 			pr_ip6opt(CMSG_DATA(cm));
1736 			break;
1737 		case IPV6_DSTOPTS:
1738 		case IPV6_RTHDRDSTOPTS:
1739 			printf("  Dst Options: ");
1740 			pr_ip6opt(CMSG_DATA(cm));
1741 			break;
1742 		case IPV6_RTHDR:
1743 			printf("  Routing: ");
1744 			pr_rthdr(CMSG_DATA(cm));
1745 			break;
1746 		}
1747 	}
1748 }
1749 
1750 void
1751 pr_ip6opt(void *extbuf)
1752 {
1753 	struct ip6_hbh *ext;
1754 	int currentlen;
1755 	u_int8_t type;
1756 	size_t extlen;
1757 	socklen_t len;
1758 	void *databuf;
1759 	u_int16_t value2;
1760 	u_int32_t value4;
1761 
1762 	ext = (struct ip6_hbh *)extbuf;
1763 	extlen = (ext->ip6h_len + 1) * 8;
1764 	printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
1765 	    (unsigned int)ext->ip6h_len, (unsigned long)extlen);
1766 
1767 	currentlen = 0;
1768 	while (1) {
1769 		currentlen = inet6_opt_next(extbuf, extlen, currentlen,
1770 		    &type, &len, &databuf);
1771 		if (currentlen == -1)
1772 			break;
1773 		switch (type) {
1774 		/*
1775 		 * Note that inet6_opt_next automatically skips any padding
1776 		 * options.
1777 		 */
1778 		case IP6OPT_JUMBO:
1779 			inet6_opt_get_val(databuf, 0, &value4, sizeof(value4));
1780 			printf("    Jumbo Payload Opt: Length %u\n",
1781 			    (u_int32_t)ntohl(value4));
1782 			break;
1783 		case IP6OPT_ROUTER_ALERT:
1784 			inet6_opt_get_val(databuf, 0, &value2, sizeof(value2));
1785 			printf("    Router Alert Opt: Type %u\n",
1786 			    ntohs(value2));
1787 			break;
1788 		default:
1789 			printf("    Received Opt %u len %lu\n",
1790 			    type, (unsigned long)len);
1791 			break;
1792 		}
1793 	}
1794 	return;
1795 }
1796 
1797 void
1798 pr_rthdr(void *extbuf)
1799 {
1800 	struct in6_addr *in6;
1801 	char ntopbuf[INET6_ADDRSTRLEN];
1802 	struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
1803 	int i, segments;
1804 
1805 	/* print fixed part of the header */
1806 	printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
1807 	    rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
1808 	if ((segments = inet6_rth_segments(extbuf)) >= 0)
1809 		printf("%d segments, ", segments);
1810 	else
1811 		printf("segments unknown, ");
1812 	printf("%d left\n", rh->ip6r_segleft);
1813 
1814 	for (i = 0; i < segments; i++) {
1815 		in6 = inet6_rth_getaddr(extbuf, i);
1816 		if (in6 == NULL)
1817 			printf("   [%d]<NULL>\n", i);
1818 		else {
1819 			if (!inet_ntop(AF_INET6, in6, ntopbuf,
1820 			    sizeof(ntopbuf)))
1821 				strncpy(ntopbuf, "?", sizeof(ntopbuf));
1822 			printf("   [%d]%s\n", i, ntopbuf);
1823 		}
1824 	}
1825 
1826 	return;
1827 
1828 }
1829 
1830 int
1831 get_hoplim(struct msghdr *mhdr)
1832 {
1833 	struct cmsghdr *cm;
1834 
1835 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1836 	     cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1837 		if (cm->cmsg_len == 0)
1838 			return(-1);
1839 
1840 		if (cm->cmsg_level == IPPROTO_IPV6 &&
1841 		    cm->cmsg_type == IPV6_HOPLIMIT &&
1842 		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
1843 			return(*(int *)CMSG_DATA(cm));
1844 	}
1845 
1846 	return(-1);
1847 }
1848 
1849 int
1850 get_pathmtu(struct msghdr *mhdr, struct sockaddr_in6 *dst)
1851 {
1852 	struct cmsghdr *cm;
1853 	struct ip6_mtuinfo *mtuctl = NULL;
1854 
1855 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1856 	    cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1857 		if (cm->cmsg_len == 0)
1858 			return(0);
1859 
1860 		if (cm->cmsg_level == IPPROTO_IPV6 &&
1861 		    cm->cmsg_type == IPV6_PATHMTU &&
1862 		    cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {
1863 			mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm);
1864 
1865 			/*
1866 			 * If the notified destination is different from
1867 			 * the one we are pinging, just ignore the info.
1868 			 * We check the scope ID only when both notified value
1869 			 * and our own value have non-0 values, because we may
1870 			 * have used the default scope zone ID for sending,
1871 			 * in which case the scope ID value is 0.
1872 			 */
1873 			if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr,
1874 			    &dst->sin6_addr) ||
1875 			    (mtuctl->ip6m_addr.sin6_scope_id &&
1876 			    dst->sin6_scope_id &&
1877 			    mtuctl->ip6m_addr.sin6_scope_id !=
1878 			    dst->sin6_scope_id)) {
1879 				if ((options & F_VERBOSE) != 0) {
1880 					printf("path MTU for %s is notified. "
1881 					    "(ignored)\n",
1882 					    pr_addr((struct sockaddr *)
1883 					    &mtuctl->ip6m_addr,
1884 					    sizeof(mtuctl->ip6m_addr)));
1885 				}
1886 				return(0);
1887 			}
1888 
1889 			/*
1890 			 * Ignore an invalid MTU. XXX: can we just believe
1891 			 * the kernel check?
1892 			 */
1893 			if (mtuctl->ip6m_mtu < IPV6_MMTU)
1894 				return(0);
1895 
1896 			/* notification for our destination. return the MTU. */
1897 			return((int)mtuctl->ip6m_mtu);
1898 		}
1899 	}
1900 	return(0);
1901 }
1902 
1903 /*
1904  * pr_icmph6 --
1905  *	Print a descriptive string about an ICMP header.
1906  */
1907 void
1908 pr_icmph6(struct icmp6_hdr *icp, u_char *end)
1909 {
1910 	char ntop_buf[INET6_ADDRSTRLEN];
1911 	struct nd_redirect *red;
1912 
1913 	switch (icp->icmp6_type) {
1914 	case ICMP6_DST_UNREACH:
1915 		switch (icp->icmp6_code) {
1916 		case ICMP6_DST_UNREACH_NOROUTE:
1917 			(void)printf("No Route to Destination\n");
1918 			break;
1919 		case ICMP6_DST_UNREACH_ADMIN:
1920 			(void)printf("Destination Administratively "
1921 			    "Unreachable\n");
1922 			break;
1923 		case ICMP6_DST_UNREACH_BEYONDSCOPE:
1924 			(void)printf("Destination Unreachable Beyond Scope\n");
1925 			break;
1926 		case ICMP6_DST_UNREACH_ADDR:
1927 			(void)printf("Destination Host Unreachable\n");
1928 			break;
1929 		case ICMP6_DST_UNREACH_NOPORT:
1930 			(void)printf("Destination Port Unreachable\n");
1931 			break;
1932 		default:
1933 			(void)printf("Destination Unreachable, Bad Code: %d\n",
1934 			    icp->icmp6_code);
1935 			break;
1936 		}
1937 		/* Print returned IP header information */
1938 		pr_retip6((struct ip6_hdr *)(icp + 1), end);
1939 		break;
1940 	case ICMP6_PACKET_TOO_BIG:
1941 		(void)printf("Packet too big mtu = %d\n",
1942 		    (int)ntohl(icp->icmp6_mtu));
1943 		pr_retip6((struct ip6_hdr *)(icp + 1), end);
1944 		break;
1945 	case ICMP6_TIME_EXCEEDED:
1946 		switch (icp->icmp6_code) {
1947 		case ICMP6_TIME_EXCEED_TRANSIT:
1948 			(void)printf("Time to live exceeded\n");
1949 			break;
1950 		case ICMP6_TIME_EXCEED_REASSEMBLY:
1951 			(void)printf("Frag reassembly time exceeded\n");
1952 			break;
1953 		default:
1954 			(void)printf("Time exceeded, Bad Code: %d\n",
1955 			    icp->icmp6_code);
1956 			break;
1957 		}
1958 		pr_retip6((struct ip6_hdr *)(icp + 1), end);
1959 		break;
1960 	case ICMP6_PARAM_PROB:
1961 		(void)printf("Parameter problem: ");
1962 		switch (icp->icmp6_code) {
1963 		case ICMP6_PARAMPROB_HEADER:
1964 			(void)printf("Erroneous Header ");
1965 			break;
1966 		case ICMP6_PARAMPROB_NEXTHEADER:
1967 			(void)printf("Unknown Nextheader ");
1968 			break;
1969 		case ICMP6_PARAMPROB_OPTION:
1970 			(void)printf("Unrecognized Option ");
1971 			break;
1972 		default:
1973 			(void)printf("Bad code(%d) ", icp->icmp6_code);
1974 			break;
1975 		}
1976 		(void)printf("pointer = 0x%02x\n",
1977 		    (u_int32_t)ntohl(icp->icmp6_pptr));
1978 		pr_retip6((struct ip6_hdr *)(icp + 1), end);
1979 		break;
1980 	case ICMP6_ECHO_REQUEST:
1981 		(void)printf("Echo Request");
1982 		/* XXX ID + Seq + Data */
1983 		break;
1984 	case ICMP6_ECHO_REPLY:
1985 		(void)printf("Echo Reply");
1986 		/* XXX ID + Seq + Data */
1987 		break;
1988 	case ICMP6_MEMBERSHIP_QUERY:
1989 		(void)printf("Listener Query");
1990 		break;
1991 	case ICMP6_MEMBERSHIP_REPORT:
1992 		(void)printf("Listener Report");
1993 		break;
1994 	case ICMP6_MEMBERSHIP_REDUCTION:
1995 		(void)printf("Listener Done");
1996 		break;
1997 	case ND_ROUTER_SOLICIT:
1998 		(void)printf("Router Solicitation");
1999 		break;
2000 	case ND_ROUTER_ADVERT:
2001 		(void)printf("Router Advertisement");
2002 		break;
2003 	case ND_NEIGHBOR_SOLICIT:
2004 		(void)printf("Neighbor Solicitation");
2005 		break;
2006 	case ND_NEIGHBOR_ADVERT:
2007 		(void)printf("Neighbor Advertisement");
2008 		break;
2009 	case ND_REDIRECT:
2010 		red = (struct nd_redirect *)icp;
2011 		(void)printf("Redirect\n");
2012 		if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf,
2013 		    sizeof(ntop_buf)))
2014 			strncpy(ntop_buf, "?", sizeof(ntop_buf));
2015 		(void)printf("Destination: %s", ntop_buf);
2016 		if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf,
2017 		    sizeof(ntop_buf)))
2018 			strncpy(ntop_buf, "?", sizeof(ntop_buf));
2019 		(void)printf(" New Target: %s", ntop_buf);
2020 		break;
2021 	default:
2022 		(void)printf("Bad ICMP type: %d", icp->icmp6_type);
2023 	}
2024 }
2025 
2026 /*
2027  * pr_iph6 --
2028  *	Print an IP6 header.
2029  */
2030 void
2031 pr_iph6(struct ip6_hdr *ip6)
2032 {
2033 	u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
2034 	u_int8_t tc;
2035 	char ntop_buf[INET6_ADDRSTRLEN];
2036 
2037 	tc = *(&ip6->ip6_vfc + 1); /* XXX */
2038 	tc = (tc >> 4) & 0x0f;
2039 	tc |= (ip6->ip6_vfc << 4);
2040 
2041 	printf("Vr TC  Flow Plen Nxt Hlim\n");
2042 	printf(" %1x %02x %05x %04x  %02x   %02x\n",
2043 	    (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow),
2044 	    ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim);
2045 	if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf)))
2046 		strncpy(ntop_buf, "?", sizeof(ntop_buf));
2047 	printf("%s->", ntop_buf);
2048 	if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf)))
2049 		strncpy(ntop_buf, "?", sizeof(ntop_buf));
2050 	printf("%s\n", ntop_buf);
2051 }
2052 
2053 /*
2054  * pr_retip6 --
2055  *	Dump some info on a returned (via ICMPv6) IPv6 packet.
2056  */
2057 void
2058 pr_retip6(struct ip6_hdr *ip6, u_char *end)
2059 {
2060 	u_char *cp = (u_char *)ip6, nh;
2061 	int hlen;
2062 
2063 	if (end - (u_char *)ip6 < sizeof(*ip6)) {
2064 		printf("IP6");
2065 		goto trunc;
2066 	}
2067 	pr_iph6(ip6);
2068 	hlen = sizeof(*ip6);
2069 
2070 	nh = ip6->ip6_nxt;
2071 	cp += hlen;
2072 	while (end - cp >= 8) {
2073 		switch (nh) {
2074 		case IPPROTO_HOPOPTS:
2075 			printf("HBH ");
2076 			hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
2077 			nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
2078 			break;
2079 		case IPPROTO_DSTOPTS:
2080 			printf("DSTOPT ");
2081 			hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
2082 			nh = ((struct ip6_dest *)cp)->ip6d_nxt;
2083 			break;
2084 		case IPPROTO_FRAGMENT:
2085 			printf("FRAG ");
2086 			hlen = sizeof(struct ip6_frag);
2087 			nh = ((struct ip6_frag *)cp)->ip6f_nxt;
2088 			break;
2089 		case IPPROTO_ROUTING:
2090 			printf("RTHDR ");
2091 			hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
2092 			nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
2093 			break;
2094 		case IPPROTO_AH:
2095 			printf("AH ");
2096 			hlen = (((struct ah *)cp)->ah_hl+2) << 2;
2097 			nh = ((struct ah *)cp)->ah_nh;
2098 			break;
2099 		case IPPROTO_ICMPV6:
2100 			printf("ICMP6: type = %d, code = %d\n",
2101 			    *cp, *(cp + 1));
2102 			return;
2103 		case IPPROTO_ESP:
2104 			printf("ESP\n");
2105 			return;
2106 		case IPPROTO_TCP:
2107 			printf("TCP: from port %u, to port %u (decimal)\n",
2108 			    (*cp * 256 + *(cp + 1)),
2109 			    (*(cp + 2) * 256 + *(cp + 3)));
2110 			return;
2111 		case IPPROTO_UDP:
2112 			printf("UDP: from port %u, to port %u (decimal)\n",
2113 			    (*cp * 256 + *(cp + 1)),
2114 			    (*(cp + 2) * 256 + *(cp + 3)));
2115 			return;
2116 		default:
2117 			printf("Unknown Header(%d)\n", nh);
2118 			return;
2119 		}
2120 
2121 		if ((cp += hlen) >= end)
2122 			goto trunc;
2123 	}
2124 	if (end - cp < 8)
2125 		goto trunc;
2126 
2127 	putchar('\n');
2128 	return;
2129 
2130   trunc:
2131 	printf("...\n");
2132 	return;
2133 }
2134 
2135 __dead void
2136 usage(void)
2137 {
2138 	if (v6flag) {
2139 		(void)fprintf(stderr,
2140 		    "usage: ping6 [-dEefHLmnqv] [-c count] [-h hoplimit] "
2141 		    "[-I sourceaddr]\n\t[-i wait] [-l preload] [-p pattern] "
2142 		    "[-s packetsize] [-V rtable]\n\t[-w maxwait] host\n");
2143 	} else {
2144 		(void)fprintf(stderr,
2145 		    "usage: ping [-DdEefHLnqRv] [-c count] [-I ifaddr]"
2146 		    " [-i wait]\n\t[-l preload] [-p pattern] [-s packetsize]"
2147 #ifndef	SMALL
2148 		    " [-T toskeyword]"
2149 #endif	/* SMALL */
2150 		    "\n\t[-t ttl] [-V rtable] [-w maxwait] host\n");
2151 	}
2152 	exit(1);
2153 }
2154