xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c (revision d656abb5804319b33c85955a73ee450ef7ff9739)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
22  * Use is subject to license terms.
23  */
24 
25 /*
26  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
27  * All Rights Reserved.
28  */
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California.
33  * All Rights Reserved.
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #include <stdio.h>
41 #include <strings.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <signal.h>
46 #include <limits.h>
47 #include <math.h>
48 
49 #include <sys/time.h>
50 #include <sys/param.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 #include <sys/stropts.h>
54 #include <sys/file.h>
55 #include <sys/sysmacros.h>
56 
57 #include <arpa/inet.h>
58 #include <net/if.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/in.h>
61 #include <netinet/ip.h>
62 #include <netinet/ip_icmp.h>
63 #include <netinet/ip_var.h>
64 #include <netinet/ip6.h>
65 #include <netinet/icmp6.h>
66 #include <netinet/udp.h>
67 #include <netdb.h>
68 #include <stdlib.h>
69 #include <priv_utils.h>
70 
71 #include <libinetutil.h>
72 #include "ping.h"
73 
74 /*
75  * This macro is used to compare 16bit, wrapping sequence numbers. Inspired by
76  * TCP's SEQ_LEQ macro.
77  */
78 #define	PINGSEQ_LEQ(a, b)	((int16_t)((a)-(b)) <= 0)
79 
80 #define	MAX_WAIT		10	/* max sec. to wait for response */
81 #define	MAX_TRAFFIC_CLASS	255	/* max traffic class for IPv6 */
82 #define	MAX_FLOW_LABEL		0xFFFFF	/* max flow label for IPv6 */
83 #define	MAX_TOS			255	/* max type-of-service for IPv4 */
84 
85 #define	TIMEOUT			20	/* default timeout value */
86 #define	DEFAULT_DATALEN		56
87 
88 #define	MULTICAST_NOLOOP	1	/* multicast options */
89 #define	MULTICAST_TTL		2
90 #define	MULTICAST_IF		4
91 
92 #define	IF_INDEX		0	/* types of -i argument */
93 #define	IF_NAME			1
94 #define	IF_ADDR			2
95 #define	IF_ADDR6		3
96 
97 #ifdef BSD
98 #define	setbuf(s, b)	setlinebuf((s))
99 #endif /* BSD */
100 
101 
102 /* interface identification */
103 union if_id {
104 	int index;		/* interface index (e.g., 1, 2) */
105 	char *name;		/* interface name (e.g., le0, hme0) */
106 	union any_in_addr addr;	/* interface address (e.g., 10.123.4.5) */
107 };
108 
109 /* stores the interface supplied by the user */
110 struct if_entry {
111 	char *str;		/* unresolved, string input */
112 	int id_type;		/* type of ID (index, name, addr, addr6) */
113 	union if_id id;		/* ID */
114 };
115 
116 char *progname;
117 char *targethost;
118 char *nexthop;
119 
120 static int send_sock;			/* send sockets */
121 static int send_sock6;
122 static struct sockaddr_in to;		/* where to send */
123 static struct sockaddr_in6 to6;
124 static union any_in_addr gw_IP_list[MAX_GWS];	/* gateways */
125 static union any_in_addr gw_IP_list6[MAX_GWS6];
126 static int if_index = 0;		/* outgoing interface index */
127 boolean_t is_alive = _B_FALSE;		/* is target host alive */
128 struct targetaddr *current_targetaddr;	/* current target IP address to probe */
129 static struct targetaddr *targetaddr_list; /* list of IP addresses to probe */
130 static int num_targetaddrs;		/* no of target addresses to probe */
131 static int num_v4 = 0;			/* count of IPv4 addresses */
132 static int num_v6 = 0;			/* count of IPv6 addresses */
133 boolean_t verbose = _B_FALSE;		/* verbose output */
134 boolean_t stats = _B_FALSE;		/* display statistics */
135 static boolean_t settos = _B_FALSE;	/* set type-of-service value */
136 boolean_t rr_option = _B_FALSE;		/* true if using record route */
137 boolean_t send_reply = _B_FALSE;	/* Send an ICMP_{ECHO|TSTAMP}REPLY */
138 					/* that goes to target and comes back */
139 					/* to the the sender via src routing. */
140 boolean_t strict = _B_FALSE;		/* true if using strict source route */
141 boolean_t ts_option = _B_FALSE;		/* true if using timestamp option */
142 boolean_t use_icmp_ts = _B_FALSE;	/* Use ICMP timestamp request */
143 boolean_t use_udp = _B_FALSE;		/* Use UDP instead of ICMP */
144 boolean_t probe_all = _B_FALSE;		/* probe all the IP addresses */
145 boolean_t nflag = _B_FALSE;		/* do not reverse lookup addresses */
146 boolean_t bypass = _B_FALSE;		/* bypass IPsec policy */
147 static int family_input = AF_UNSPEC;	/* address family supplied by user */
148 int datalen = DEFAULT_DATALEN;		/* How much data */
149 int ts_flag;				/* timestamp flag value */
150 static int num_gw;			/* number of gateways */
151 static int eff_num_gw;			/* effective number of gateways */
152 					/* if send_reply, it's 2*num_gw+1 */
153 static int num_wraps = -1;		/* no of times 64K icmp_seq wrapped */
154 static ushort_t dest_port = 32768 + 666; /* starting port for the UDP probes */
155 static char *gw_list[MAXMAX_GWS];	/* list of gateways as user enters */
156 static int interval = 1;		/* interval between transmissions */
157 static int options;			/* socket options */
158 static int moptions;			/* multicast options */
159 int npackets;				/* number of packets to send */
160 static ushort_t tos;			/* type-of-service value */
161 static int hoplimit = -1;		/* time-to-live value */
162 static int timeout = TIMEOUT;		/* timeout value (sec) for probes */
163 static struct if_entry out_if;		/* interface argument */
164 int ident;				/* ID for this ping run */
165 static hrtime_t t_last_probe_sent;	/* the time we sent the last probe */
166 
167 /*
168  * This buffer stores the received packets. Currently it needs to be 32 bit
169  * aligned. In the future, we'll be using 64 bit alignment, so let's use 64 bit
170  * alignment now.
171  */
172 static uint64_t in_pkt[(IP_MAXPACKET + 1)/8];
173 
174 /* Used to store the ancillary data that comes with the received packets */
175 static uint64_t ancillary_data[(IP_MAXPACKET + 1)/8];
176 
177 static int ntransmitted;	/* number of packet sent to single IP address */
178 int nreceived;			/* # of packets we got back from target host */
179 int nreceived_last_target;	/* received from last target IP */
180 /*
181  * These are used for statistics. tmin is initialized to maximum longint value.
182  * The max value is also used for timeouts.   All times are in microseconds.
183  */
184 long long tmin = LLONG_MAX;
185 long long tmax;
186 int64_t tsum;			/* sum of all times, for doing average */
187 int64_t tsum2;			/* sum of squared times, for std. dev. */
188 
189 static struct targetaddr *build_targetaddr_list(struct addrinfo *,
190     union any_in_addr *);
191 extern void check_reply(struct addrinfo *, struct msghdr *, int, ushort_t);
192 extern void check_reply6(struct addrinfo *, struct msghdr *, int, ushort_t);
193 static struct targetaddr *create_targetaddr_item(int, union any_in_addr *,
194     union any_in_addr *);
195 void find_dstaddr(ushort_t, union any_in_addr *);
196 static struct ifaddrlist *find_if(struct ifaddrlist *, int);
197 static void finish();
198 static void get_gwaddrs(char *[], int, union any_in_addr *,
199     union any_in_addr *, int *, int *);
200 static void get_hostinfo(char *, int, struct addrinfo **);
201 static ushort_t in_cksum(ushort_t *, int);
202 static int int_arg(char *s, char *what);
203 boolean_t is_a_target(struct addrinfo *, union any_in_addr *);
204 static void mirror_gws(union any_in_addr *, int);
205 static void pinger(int, struct sockaddr *, struct msghdr *, int);
206 char *pr_name(char *, int);
207 char *pr_protocol(int);
208 static void print_unknown_host_msg(const char *, const char *);
209 static void recv_icmp_packet(struct addrinfo *, int, int, ushort_t, ushort_t);
210 static void resolve_nodes(struct addrinfo **, struct addrinfo **,
211     union any_in_addr **);
212 void schedule_sigalrm();
213 static void select_all_src_addrs(union any_in_addr **, struct addrinfo *,
214     union any_in_addr *, union any_in_addr *);
215 static void select_src_addr(union any_in_addr *, int, union any_in_addr *);
216 void send_scheduled_probe();
217 boolean_t seq_match(ushort_t, int, ushort_t);
218 extern void set_ancillary_data(struct msghdr *, int, union any_in_addr *, int,
219     uint_t);
220 extern void set_IPv4_options(int, union any_in_addr *, int, struct in_addr *,
221     struct in_addr *);
222 static void set_nexthop(int, struct addrinfo *, int);
223 static boolean_t setup_socket(int, int *, int *, int *, ushort_t *,
224     struct addrinfo *);
225 void sigalrm_handler();
226 void tvsub(struct timeval *, struct timeval *);
227 static void usage(char *);
228 
229 /*
230  * main()
231  */
232 int
233 main(int argc, char *argv[])
234 {
235 	struct addrinfo	*ai_dst = NULL;		/* addrinfo host list */
236 	struct addrinfo	*ai_nexthop = NULL;		/* addrinfo nexthop */
237 	union any_in_addr *src_addr_list = NULL;	/* src addrs to use */
238 	int recv_sock = -1;				/* receive sockets */
239 	int recv_sock6 = -1;
240 	ushort_t udp_src_port;			/* src ports for UDP probes */
241 	ushort_t udp_src_port6;			/* used to identify replies */
242 	uint_t flowinfo = 0;
243 	uint_t class = 0;
244 	char abuf[INET6_ADDRSTRLEN];
245 	int c;
246 	int i;
247 	boolean_t has_sys_ip_config;
248 
249 	progname = argv[0];
250 
251 	/*
252 	 * This program needs the net_icmpaccess privilege for creating
253 	 * raw ICMP sockets.  It needs sys_ip_config for using the
254 	 * IP_NEXTHOP socket option (IPv4 only).  We'll fail
255 	 * on the socket call and report the error there when we have
256 	 * insufficient privileges.
257 	 *
258 	 * Shared-IP zones don't have the sys_ip_config privilege, so
259 	 * we need to check for it in our limit set before trying
260 	 * to set it.
261 	 */
262 	has_sys_ip_config = priv_ineffect(PRIV_SYS_IP_CONFIG);
263 
264 	(void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_NET_ICMPACCESS,
265 	    has_sys_ip_config ? PRIV_SYS_IP_CONFIG : (char *)NULL,
266 	    (char *)NULL);
267 
268 	setbuf(stdout, (char *)0);
269 
270 	while ((c = getopt(argc, argv,
271 	    "abA:c:dF:G:g:I:i:LlnN:P:p:rRSsTt:UvX:x:Y0123?")) != -1) {
272 		switch ((char)c) {
273 		case 'A':
274 			if (strcmp(optarg, "inet") == 0) {
275 				family_input = AF_INET;
276 			} else if (strcmp(optarg, "inet6") == 0) {
277 				family_input = AF_INET6;
278 			} else {
279 				Fprintf(stderr,
280 				    "%s: unknown address family %s\n",
281 				    progname, optarg);
282 				exit(EXIT_FAILURE);
283 			}
284 			break;
285 
286 		case 'a':
287 			probe_all = _B_TRUE;
288 			break;
289 
290 		case 'c':
291 			i = int_arg(optarg, "traffic class");
292 			if (i > MAX_TRAFFIC_CLASS) {
293 				Fprintf(stderr, "%s: traffic class %d out of "
294 				    "range\n", progname, i);
295 				exit(EXIT_FAILURE);
296 			}
297 			class = (uint_t)i;
298 			break;
299 
300 		case 'd':
301 			options |= SO_DEBUG;
302 			break;
303 
304 		case 'b':
305 			bypass = _B_TRUE;
306 			break;
307 
308 		case 'F':
309 			i = int_arg(optarg, "flow label");
310 			if (i > MAX_FLOW_LABEL) {
311 				Fprintf(stderr, "%s: flow label %d out of "
312 				    "range\n", progname, i);
313 				exit(EXIT_FAILURE);
314 			}
315 			flowinfo = (uint_t)i;
316 			break;
317 
318 		case 'I':
319 			stats = _B_TRUE;
320 			interval = int_arg(optarg, "interval");
321 			break;
322 
323 		case 'i':
324 			/*
325 			 * this can accept interface index, interface name, and
326 			 * address configured on the interface
327 			 */
328 			moptions |= MULTICAST_IF;
329 			out_if.str = optarg;
330 
331 			if (inet_pton(AF_INET6, optarg, &out_if.id.addr) > 0) {
332 				out_if.id_type = IF_ADDR6;
333 			} else if (inet_pton(AF_INET, optarg,
334 			    &out_if.id.addr) > 0) {
335 				out_if.id_type = IF_ADDR;
336 			} else if (strcmp(optarg, "0") == 0) {
337 				out_if.id_type = IF_INDEX;
338 				out_if.id.index = 0;
339 			} else if ((out_if.id.index = atoi(optarg)) != 0) {
340 				out_if.id_type = IF_INDEX;
341 			} else {
342 				out_if.id.name = optarg;
343 				out_if.id_type = IF_NAME;
344 			}
345 			break;
346 
347 		case 'L':
348 			moptions |= MULTICAST_NOLOOP;
349 			break;
350 
351 		case 'l':
352 			send_reply = _B_TRUE;
353 			strict = _B_FALSE;
354 			break;
355 
356 		case 'n':
357 			nflag = _B_TRUE;
358 			break;
359 
360 		case 'P':
361 			settos = _B_TRUE;
362 			i = int_arg(optarg, "type-of-service");
363 			if (i > MAX_TOS) {
364 				Fprintf(stderr, "%s: tos value %d out of "
365 				    "range\n", progname, i);
366 				exit(EXIT_FAILURE);
367 			}
368 			tos = (ushort_t)i;
369 			break;
370 
371 		case 'p':
372 			i = int_arg(optarg, "port number");
373 			if (i > MAX_PORT) {
374 				Fprintf(stderr, "%s: port number %d out of "
375 				    "range\n", progname, i);
376 				exit(EXIT_FAILURE);
377 			}
378 			dest_port = (ushort_t)i;
379 			break;
380 
381 		case 'r':
382 			options |= SO_DONTROUTE;
383 			break;
384 
385 		case 'R':
386 			rr_option = _B_TRUE;
387 			break;
388 
389 		case 'S':
390 			send_reply = _B_TRUE;
391 			strict = _B_TRUE;
392 			break;
393 
394 		case 's':
395 			stats = _B_TRUE;
396 			break;
397 
398 		case 'T':
399 			ts_option = _B_TRUE;
400 			break;
401 
402 		case 't':
403 			moptions |= MULTICAST_TTL;
404 			hoplimit = int_arg(optarg, "ttl");
405 			if (hoplimit > MAXTTL) {
406 				Fprintf(stderr, "%s: ttl %d out of range\n",
407 				    progname, hoplimit);
408 				exit(EXIT_FAILURE);
409 			}
410 			break;
411 
412 		case 'U':
413 			use_udp = _B_TRUE;
414 			use_icmp_ts = _B_FALSE;
415 			break;
416 
417 		case 'v':
418 			verbose = _B_TRUE;
419 			break;
420 		/*
421 		 * 'x' and 'X' has been undocumented flags for source routing.
422 		 * Now we document loose source routing with the new flag 'g',
423 		 * which is same as in traceroute. We still keep x/X as
424 		 * as undocumented. 'G', which is for strict source routing is
425 		 * also undocumented.
426 		 */
427 		case 'x':
428 		case 'g':
429 			strict = _B_FALSE;
430 			if (num_gw > MAXMAX_GWS) {
431 				Fprintf(stderr, "%s: too many gateways\n",
432 				    progname);
433 				exit(EXIT_FAILURE);
434 			}
435 			gw_list[num_gw++] = optarg;
436 			break;
437 
438 		case 'X':
439 		case 'G':
440 			strict = _B_TRUE;
441 			if (num_gw > MAXMAX_GWS) {
442 				Fprintf(stderr, "%s: too many gateways\n",
443 				    progname);
444 				exit(EXIT_FAILURE);
445 			}
446 			gw_list[num_gw++] = optarg;
447 			break;
448 
449 		case 'N':
450 			if (nexthop != NULL) {
451 				Fprintf(stderr, "%s: only one next hop gateway"
452 				    " allowed\n", progname);
453 				exit(EXIT_FAILURE);
454 			}
455 			nexthop = optarg;
456 			break;
457 
458 		case 'Y':
459 			use_icmp_ts = _B_TRUE;
460 			use_udp = _B_FALSE;
461 			break;
462 
463 		case '0':
464 		case '1':
465 		case '2':
466 		case '3':
467 			ts_flag = (char)c - '0';
468 			break;
469 
470 		case '?':
471 			usage(progname);
472 			exit(EXIT_FAILURE);
473 			break;
474 
475 		default:
476 			usage(progname);
477 			exit(EXIT_FAILURE);
478 			break;
479 		}
480 	}
481 
482 	if (optind >= argc) {
483 		usage(progname);
484 		exit(EXIT_FAILURE);
485 	}
486 
487 	/*
488 	 * send_reply, which sends the probe packet back to itself
489 	 * doesn't work with UDP
490 	 */
491 	if (use_udp)
492 		send_reply = _B_FALSE;
493 
494 	if (getenv("MACHINE_THAT_GOES_PING") != NULL)
495 		stats = _B_TRUE;
496 
497 	targethost = argv[optind];
498 	optind++;
499 	if (optind < argc) {
500 		if (stats) {
501 			datalen = int_arg(argv[optind], "data size");
502 			optind++;
503 			if (optind < argc) {
504 				npackets = int_arg(argv[optind],
505 				    "packet count");
506 				if (npackets < 1) {
507 					Fprintf(stderr, "%s: packet count %d "
508 					    "out of range\n", progname,
509 					    npackets);
510 					exit(EXIT_FAILURE);
511 				}
512 			}
513 		} else {
514 			timeout = int_arg(argv[optind], "timeout");
515 		}
516 	}
517 
518 	/*
519 	 * Let's prepare sockaddr_in* structures, cause we might need both of
520 	 * them.
521 	 */
522 	bzero((char *)&to, sizeof (struct sockaddr_in));
523 	to.sin_family = AF_INET;
524 
525 	bzero((char *)&to6, sizeof (struct sockaddr_in6));
526 	to6.sin6_family = AF_INET6;
527 	to6.sin6_flowinfo = htonl((class << 20) | flowinfo);
528 
529 	if (stats)
530 		(void) sigset(SIGINT, finish);
531 
532 	ident = (int)getpid() & 0xFFFF;
533 
534 	/* resolve the hostnames */
535 	resolve_nodes(&ai_dst, &ai_nexthop, &src_addr_list);
536 
537 	/*
538 	 * We should make sure datalen is reasonable.
539 	 * 	IP_MAXPACKET >= IPv4/IPv6 header length +
540 	 *			IPv4 options/IPv6 routing header length +
541 	 *			ICMP/ICMP6/UDP header length +
542 	 *			datalen
543 	 */
544 
545 	if (family_input == AF_INET6 ||
546 	    (family_input == AF_UNSPEC && num_v6 != 0)) {
547 		size_t exthdr_len = 0;
548 
549 		if (send_reply) {
550 			exthdr_len = sizeof (struct ip6_rthdr0) +
551 			    2 * num_gw * sizeof (struct in6_addr);
552 		} else if (num_gw > 0) {
553 			exthdr_len = sizeof (struct ip6_rthdr0) +
554 			    num_gw * sizeof (struct in6_addr);
555 		}
556 
557 		/*
558 		 * Size of ICMP6 header and UDP header are the same. Let's
559 		 * use ICMP6_MINLEN.
560 		 */
561 		if (datalen > (IP_MAXPACKET - (sizeof (struct ip6_hdr) +
562 		    exthdr_len + ICMP6_MINLEN))) {
563 			Fprintf(stderr,
564 			    "%s: data size too large for IPv6 packet\n",
565 			    progname);
566 			num_v6 = 0;
567 		}
568 	}
569 
570 	if (family_input == AF_INET ||
571 	    (family_input == AF_UNSPEC && num_v4 != 0)) {
572 		size_t opt_len = 0;
573 
574 		if (send_reply) {
575 			/*
576 			 * Includes 3 bytes code+ptr+len, the intermediate
577 			 * gateways, the actual and the effective target.
578 			 */
579 			opt_len = 3 +
580 			    (2 * num_gw + 2) * sizeof (struct in_addr);
581 		} else if (num_gw > 0) {
582 			opt_len = 3 + (num_gw + 1) * sizeof (struct in_addr);
583 		}
584 
585 		if (rr_option) {
586 			opt_len = MAX_IPOPTLEN;
587 		} else if (ts_option) {
588 			if ((ts_flag & 0x0f) <= IPOPT_TS_TSANDADDR) {
589 				opt_len = MAX_IPOPTLEN;
590 			} else {
591 				opt_len += IPOPT_MINOFF +
592 				    2 * sizeof (struct ipt_ta);
593 				/*
594 				 * Note: BSD/4.X is broken in their check so we
595 				 * have to  bump up this number by at least one.
596 				 */
597 				opt_len++;
598 			}
599 		}
600 
601 		/* Round up to 4 byte boundary */
602 		if (opt_len & 0x3)
603 			opt_len = (opt_len & ~0x3) + 4;
604 
605 		if (datalen > (IP_MAXPACKET - (sizeof (struct ip) + opt_len +
606 		    ICMP_MINLEN))) {
607 			Fprintf(stderr,
608 			    "%s: data size too large for IPv4 packet\n",
609 			    progname);
610 			num_v4 = 0;
611 		}
612 	}
613 
614 	if (num_v4 == 0 && num_v6 == 0) {
615 		exit(EXIT_FAILURE);
616 	}
617 
618 	/* setup the sockets */
619 	if (num_v6 != 0) {
620 		if (!setup_socket(AF_INET6, &send_sock6, &recv_sock6,
621 		    &if_index, &udp_src_port6, ai_nexthop))
622 			exit(EXIT_FAILURE);
623 	}
624 
625 	if (num_v4 != 0) {
626 		if (!setup_socket(AF_INET, &send_sock, &recv_sock, &if_index,
627 		    &udp_src_port, ai_nexthop))
628 			exit(EXIT_FAILURE);
629 	}
630 
631 	__priv_relinquish();
632 
633 	/*
634 	 * If sending back to ourself, add the mirror image of current
635 	 * gateways, so that the probes travel to and from the target
636 	 * by visiting the same gateways in reverse order.
637 	 */
638 	if (send_reply) {
639 		if (num_v6 != 0)
640 			mirror_gws(gw_IP_list6, AF_INET6);
641 		if (num_v4 != 0)
642 			mirror_gws(gw_IP_list, AF_INET);
643 
644 		/* We add 1 because we put the target as the middle gateway */
645 		eff_num_gw = 2 * num_gw + 1;
646 
647 	} else {
648 		eff_num_gw = num_gw;
649 	}
650 
651 	targetaddr_list = build_targetaddr_list(ai_dst, src_addr_list);
652 	current_targetaddr = targetaddr_list;
653 
654 	/*
655 	 * Set the starting_seq_num for the first targetaddr.
656 	 * If we are sending ICMP Echo Requests, the sequence number is same as
657 	 * ICMP sequence number, and it starts from zero. If we are sending UDP
658 	 * packets, the sequence number is the destination UDP port number,
659 	 * which starts from dest_port. At each probe, this sequence number is
660 	 * incremented by one.
661 	 * We set the starting_seq_num for first targetaddr here. The
662 	 * following ones will be set by looking at where we left with the last
663 	 * targetaddr.
664 	 */
665 	current_targetaddr->starting_seq_num = use_udp ? dest_port : 0;
666 
667 	if (stats) {
668 		if (probe_all || !nflag) {
669 			Printf("PING %s: %d data bytes\n", targethost, datalen);
670 		} else {
671 			if (ai_dst->ai_family == AF_INET) {
672 				(void) inet_ntop(AF_INET,
673 				    &((struct sockaddr_in *)(void *)
674 				    ai_dst->ai_addr)->sin_addr,
675 				    abuf, sizeof (abuf));
676 			} else {
677 				(void) inet_ntop(AF_INET6,
678 				    &((struct sockaddr_in6 *)(void *)
679 				    ai_dst->ai_addr)->sin6_addr,
680 				    abuf, sizeof (abuf));
681 			}
682 			Printf("PING %s (%s): %d data bytes\n",
683 			    targethost, abuf, datalen);
684 		}
685 	}
686 
687 	/* Let's get things going */
688 	send_scheduled_probe();
689 
690 	/* SIGALRM is used to send the next scheduled probe */
691 	(void) sigset(SIGALRM, sigalrm_handler);
692 	schedule_sigalrm();
693 
694 	/*
695 	 * From now on, we'll always be listening to ICMP packets. As SIGALRM
696 	 * comes in, sigalrm_handler() will be invoked and send another
697 	 * probe.
698 	 */
699 	recv_icmp_packet(ai_dst, recv_sock6, recv_sock, udp_src_port6,
700 	    udp_src_port);
701 
702 	return (EXIT_SUCCESS);	/* should never come here */
703 }
704 
705 /*
706  * Build the target IP address list. Use command line options and
707  * name lookup results returned from name server to determine which addresses
708  * to probe, how many times, in which order.
709  */
710 static struct targetaddr *
711 build_targetaddr_list(struct addrinfo *ai_dst, union any_in_addr *src_addr_list)
712 {
713 	struct targetaddr *head = NULL;
714 	struct targetaddr *targetaddr;
715 	struct targetaddr **nextp;
716 	int num_dst;
717 	int i;
718 	struct addrinfo *aip;
719 
720 	aip = ai_dst;
721 	if (probe_all)
722 		num_dst = num_v4 + num_v6;
723 	else
724 		num_dst = 1;
725 	num_targetaddrs = num_dst;
726 	nextp = &head;
727 	for (aip = ai_dst, i = 0; aip != NULL; aip = aip->ai_next, i++) {
728 		if (aip->ai_family == AF_INET && num_v4 != 0) {
729 			targetaddr = create_targetaddr_item(aip->ai_family,
730 			    (union any_in_addr *)
731 			    /* LINTED E_BAD_PTR_CAST_ALIGN */
732 			    &((struct sockaddr_in *)
733 			    aip->ai_addr)->sin_addr,
734 			    &src_addr_list[i]);
735 		} else if (aip->ai_family == AF_INET6 && num_v6 != 0) {
736 			targetaddr = create_targetaddr_item(aip->ai_family,
737 			    (union any_in_addr *)
738 			    /* LINTED E_BAD_PTR_CAST_ALIGN */
739 			    &((struct sockaddr_in6 *)
740 			    aip->ai_addr)->sin6_addr,
741 			    &src_addr_list[i]);
742 		} else {
743 			continue;
744 		}
745 		*nextp = targetaddr;
746 		nextp = &targetaddr->next;
747 		if (num_targetaddrs == 1)
748 			break;
749 	}
750 	if (npackets == 0 && stats)
751 		*nextp = head;	/* keep going indefinitely */
752 
753 	return (head);
754 }
755 
756 /*
757  * Given an address family, dst and src addresses, by also looking at the
758  * options provided at the command line, this function creates a targetaddr
759  * to be linked with others, forming a global targetaddr list. Each targetaddr
760  * item contains information about probes sent to a specific IP address.
761  */
762 static struct targetaddr *
763 create_targetaddr_item(int family, union any_in_addr *dst_addr,
764     union any_in_addr *src_addr)
765 {
766 	struct targetaddr *targetaddr;
767 
768 	targetaddr = (struct targetaddr *)malloc(sizeof (struct targetaddr));
769 	if (targetaddr == NULL) {
770 		Fprintf(stderr, "%s: malloc %s\n", progname, strerror(errno));
771 		exit(EXIT_FAILURE);
772 	}
773 	targetaddr->family = family;
774 	targetaddr->dst_addr = *dst_addr;
775 	targetaddr->src_addr = *src_addr;
776 	if (stats) {
777 		/*
778 		 * npackets is only defined if we are in stats mode.
779 		 * npackets determines how many probes to send to each target
780 		 * IP address. npackets == 0 means send only 1 and move on to
781 		 * next target IP.
782 		 */
783 		if (npackets > 0)
784 			targetaddr->num_probes = npackets;
785 		else
786 			targetaddr->num_probes = 1;
787 	} else {
788 		targetaddr->num_probes = timeout;
789 	}
790 	targetaddr->num_sent = 0;
791 	targetaddr->got_reply = _B_FALSE;
792 	targetaddr->probing_done = _B_FALSE;
793 	targetaddr->starting_seq_num = 0; /* actual value will be set later */
794 	targetaddr->next = NULL;	/* actual value will be set later */
795 
796 	return (targetaddr);
797 }
798 
799 /*
800  * print "unknown host" message
801  */
802 static void
803 print_unknown_host_msg(const char *protocol, const char *hostname)
804 {
805 	Fprintf(stderr, "%s: unknown%s host %s\n", progname, protocol,
806 	    hostname);
807 }
808 
809 /*
810  * Resolve hostnames for the target host and gateways. Also, determine source
811  * addresses to use for each target address.
812  */
813 static void
814 resolve_nodes(struct addrinfo **ai_dstp, struct addrinfo **ai_nexthopp,
815     union any_in_addr **src_addr_listp)
816 {
817 	struct addrinfo *ai_dst = NULL;
818 	struct addrinfo *ai_nexthop = NULL;
819 	struct addrinfo *aip = NULL;
820 	union any_in_addr *src_addr_list = NULL;
821 	int num_resolved_gw = 0;
822 	int num_resolved_gw6 = 0;
823 
824 	get_hostinfo(targethost, family_input, &ai_dst);
825 	if (ai_dst == NULL) {
826 		print_unknown_host_msg("", targethost);
827 		exit(EXIT_FAILURE);
828 	}
829 	if (nexthop != NULL) {
830 		get_hostinfo(nexthop, family_input, &ai_nexthop);
831 		if (ai_nexthop == NULL) {
832 			print_unknown_host_msg("", nexthop);
833 			exit(EXIT_FAILURE);
834 		}
835 	}
836 	/* Get a count of the v4 & v6 addresses */
837 	for (aip = ai_dst; aip != NULL; aip = aip->ai_next) {
838 		switch (aip->ai_family) {
839 		case AF_INET:
840 			num_v4++;
841 			break;
842 		case AF_INET6:
843 			num_v6++;
844 			break;
845 		}
846 	}
847 
848 	if (family_input == AF_UNSPEC && !probe_all) {
849 		family_input = ai_dst->ai_family;
850 	}
851 
852 	/* resolve gateways */
853 	if (num_gw > 0) {
854 		get_gwaddrs(gw_list, family_input, gw_IP_list, gw_IP_list6,
855 		    &num_resolved_gw, &num_resolved_gw6);
856 
857 		/* we couldn't resolve a gateway as an IPv6 host */
858 		if (num_resolved_gw6 != num_gw && num_v6 != 0 &&
859 		    (family_input == AF_INET6 || family_input == AF_UNSPEC)) {
860 			print_unknown_host_msg(" IPv6",
861 			    gw_list[num_resolved_gw6]);
862 			num_v6 = 0;
863 		}
864 
865 		/* we couldn't resolve a gateway as an IPv4 host */
866 		if (num_resolved_gw != num_gw && num_v4 != 0 &&
867 		    (family_input == AF_INET || family_input == AF_UNSPEC)) {
868 			print_unknown_host_msg(" IPv4",
869 			    gw_list[num_resolved_gw]);
870 			num_v4 = 0;
871 		}
872 	}
873 
874 	if (num_v4 == 0 && num_v6 == 0)
875 		exit(EXIT_FAILURE);
876 
877 	select_all_src_addrs(&src_addr_list, ai_dst, gw_IP_list, gw_IP_list6);
878 	*ai_dstp = ai_dst;
879 	*ai_nexthopp = ai_nexthop;
880 	*src_addr_listp = src_addr_list;
881 }
882 
883 /*
884  * Resolve the gateway names, splitting results into v4 and v6 lists.
885  * Gateway addresses are added to the appropriate passed-in array; the
886  * number of resolved gateways for each af is returned in resolved[6].
887  * Assumes that passed-in arrays are large enough for MAX_GWS[6] addrs
888  * and resolved[6] ptrs are non-null; ignores array and counter if the
889  * address family param makes them irrelevant.
890  */
891 static void
892 get_gwaddrs(char **gw_list, int family, union any_in_addr *gwIPlist,
893     union any_in_addr *gwIPlist6, int *resolved, int *resolved6)
894 {
895 	int i;
896 	boolean_t check_v4 = _B_TRUE, check_v6 = _B_TRUE;
897 	struct addrinfo	*ai = NULL;
898 	struct addrinfo	*aip = NULL;
899 
900 	*resolved = *resolved6 = 0;
901 	switch (family) {
902 	case AF_UNSPEC:
903 		break;
904 	case AF_INET:
905 		check_v6 = _B_FALSE;
906 		break;
907 	case AF_INET6:
908 		check_v4 = _B_FALSE;
909 		break;
910 	default:
911 		return;
912 	}
913 
914 	if (check_v4 && num_gw >= MAX_GWS) {
915 		check_v4 = _B_FALSE;
916 		Fprintf(stderr, "%s: too many IPv4 gateways\n", progname);
917 	}
918 	if (check_v6 && num_gw > MAX_GWS6) {
919 		check_v6 = _B_FALSE;
920 		Fprintf(stderr, "%s: too many IPv6 gateways\n", progname);
921 	}
922 
923 	for (i = 0; i < num_gw; i++) {
924 		if (!check_v4 && !check_v6)
925 			return;
926 		get_hostinfo(gw_list[i], family, &ai);
927 		if (ai == NULL)
928 			return;
929 		if (check_v4 && num_v4 != 0) {
930 			for (aip = ai; aip != NULL; aip = aip->ai_next) {
931 				if (aip->ai_family == AF_INET) {
932 					/* LINTED E_BAD_PTR_CAST_ALIGN */
933 					bcopy(&((struct sockaddr_in *)
934 					    aip->ai_addr)->sin_addr,
935 					    &gwIPlist[i].addr,
936 					    aip->ai_addrlen);
937 					(*resolved)++;
938 					break;
939 				}
940 			}
941 		} else if (check_v4) {
942 			check_v4 = _B_FALSE;
943 		}
944 		if (check_v6 && num_v6 != 0) {
945 			for (aip = ai; aip != NULL; aip = aip->ai_next) {
946 				if (aip->ai_family == AF_INET6) {
947 					/* LINTED E_BAD_PTR_CAST_ALIGN */
948 					bcopy(&((struct sockaddr_in6 *)
949 					    aip->ai_addr)->sin6_addr,
950 					    &gwIPlist6[i].addr6,
951 					    aip->ai_addrlen);
952 					(*resolved6)++;
953 					break;
954 				}
955 			}
956 		} else if (check_v6) {
957 			check_v6 = _B_FALSE;
958 		}
959 	}
960 	freeaddrinfo(ai);
961 }
962 
963 /*
964  * Given the list of gateways, extends the list with its mirror image. This is
965  * used when -l/-S is used. The middle gateway will be the target address. We'll
966  * leave it blank for now.
967  */
968 static void
969 mirror_gws(union any_in_addr *gwIPlist, int family)
970 {
971 	int effective_num_gw;
972 	int i;
973 
974 	/* We add 1 because we put the target as the middle gateway */
975 	effective_num_gw = 2 * num_gw + 1;
976 
977 	if ((family == AF_INET && effective_num_gw >= MAX_GWS) ||
978 	    (family == AF_INET6 && effective_num_gw > MAX_GWS6)) {
979 		Fprintf(stderr, "%s: too many %s gateways\n",
980 		    progname, (family == AF_INET) ? "IPv4" : "IPv6");
981 		exit(EXIT_FAILURE);
982 	}
983 
984 	for (i = 0; i < num_gw; i++)
985 		gwIPlist[num_gw + i + 1].addr6 = gwIPlist[num_gw - i - 1].addr6;
986 }
987 
988 /*
989  * Given IP address or hostname, return addrinfo list.
990  * Assumes that addrinfo ** ptr is non-null.
991  */
992 static void
993 get_hostinfo(char *host, int family, struct addrinfo **aipp)
994 {
995 	struct addrinfo hints, *ai;
996 	struct in6_addr addr6;
997 	struct in_addr addr;
998 	boolean_t broadcast;		/* is this 255.255.255.255? */
999 	char tmp_buf[INET6_ADDRSTRLEN];
1000 	int rc;
1001 
1002 	/* check if broadcast */
1003 	if (strcmp(host, "255.255.255.255") == 0)
1004 		broadcast = _B_TRUE;
1005 	else
1006 		broadcast = _B_FALSE;
1007 
1008 	/* check if IPv4-mapped address or broadcast */
1009 	if (((inet_pton(AF_INET6, host, &addr6) > 0) &&
1010 	    IN6_IS_ADDR_V4MAPPED(&addr6)) || broadcast) {
1011 		if (!broadcast) {
1012 			/*
1013 			 * Peel off the "mapping" stuff, leaving 32 bit IPv4
1014 			 * address.
1015 			 */
1016 			IN6_V4MAPPED_TO_INADDR(&addr6, &addr);
1017 
1018 			/* convert it back to a string */
1019 			(void) inet_ntop(AF_INET, (void *)&addr, tmp_buf,
1020 			    sizeof (tmp_buf));
1021 			/*
1022 			 * Now the host is an IPv4 address.
1023 			 * Since it previously was a v4 mapped v6 address
1024 			 * we can be sure that the size of buffer 'host'
1025 			 * is large enough to contain the associated v4
1026 			 * address and so we don't need to use a strn/lcpy
1027 			 * here.
1028 			 */
1029 			(void) strcpy(host, tmp_buf);
1030 		}
1031 		/*
1032 		 * If it's a broadcast address, it cannot be an IPv6 address.
1033 		 * Also, if it's a mapped address, we convert it into IPv4
1034 		 * address because ping will send and receive IPv4 packets for
1035 		 * that address. Therefore, it's a failure case to ask
1036 		 * get_hostinfo() to treat a broadcast or a mapped address
1037 		 * as an IPv6 address.
1038 		 */
1039 		if (family == AF_INET6) {
1040 			return;
1041 		}
1042 	}
1043 
1044 	(void) memset(&hints, 0, sizeof (hints));
1045 	hints.ai_family = family;
1046 	hints.ai_flags = AI_ADDRCONFIG;
1047 	rc = getaddrinfo(host, NULL, &hints, &ai);
1048 	if (rc != 0) {
1049 		if (rc != EAI_NONAME)
1050 			Fprintf(stderr, "%s: getaddrinfo: %s\n", progname,
1051 			    gai_strerror(rc));
1052 		return;
1053 	}
1054 	*aipp = ai;
1055 }
1056 
1057 /*
1058  * For each IP address of the target host, determine a source address to use.
1059  */
1060 static void
1061 select_all_src_addrs(union any_in_addr **src_addr_list, struct addrinfo *ai,
1062     union any_in_addr *gwv4, union any_in_addr *gwv6)
1063 {
1064 	union any_in_addr *list;
1065 	struct addrinfo *aip;
1066 	int num_dst = 1;
1067 	int i;
1068 
1069 	if (probe_all) {
1070 		for (aip = ai; aip->ai_next != NULL; aip = aip->ai_next)
1071 			num_dst++;
1072 	}
1073 
1074 	list = calloc((size_t)num_dst, sizeof (union any_in_addr));
1075 	if (list == NULL) {
1076 		Fprintf(stderr, "%s: calloc: %s\n", progname, strerror(errno));
1077 		exit(EXIT_FAILURE);
1078 	}
1079 
1080 	/*
1081 	 * If there's a gateway, a routing header as a consequence, our kernel
1082 	 * picks the source address based on the first hop address, rather than
1083 	 * final destination address.
1084 	 */
1085 	if (num_gw > 0) {
1086 		if (ai->ai_family == AF_INET)
1087 			select_src_addr(gwv4, ai->ai_family, &list[0]);
1088 		else
1089 			select_src_addr(gwv6, ai->ai_family, &list[0]);
1090 		/*
1091 		 * Since the first gateway address is fixed, we'll use the same
1092 		 * src address for every different final destination address
1093 		 * we send to.
1094 		 */
1095 		for (i = 1; i < num_dst; i++)
1096 			list[i] = list[0];
1097 	} else {
1098 		/*
1099 		 * Although something like 'ping -l host' results in a routing
1100 		 * header, the first gateway address is the target host's
1101 		 * address. Therefore, as far as src address selection goes,
1102 		 * the result is same as having no routing header.
1103 		 */
1104 		for (i = 0, aip = ai; i < num_dst && aip != NULL;
1105 		    i++, aip = aip->ai_next) {
1106 			if (aip->ai_family == AF_INET) {
1107 				if (num_v4 != 0) {
1108 					select_src_addr((union any_in_addr *)
1109 					    /* LINTED E_BAD_PTR_CAST_ALIGN */
1110 					    &((struct sockaddr_in *)
1111 					    aip->ai_addr)->sin_addr,
1112 					    aip->ai_family,
1113 					    &list[i]);
1114 				}
1115 			} else {
1116 				if (num_v6 != 0) {
1117 					select_src_addr((union any_in_addr *)
1118 					    /* LINTED E_BAD_PTR_CAST_ALIGN */
1119 					    &((struct sockaddr_in6 *)
1120 					    aip->ai_addr)->sin6_addr,
1121 					    aip->ai_family,
1122 					    &list[i]);
1123 				}
1124 			}
1125 		}
1126 	}
1127 
1128 	*src_addr_list = list;
1129 }
1130 
1131 /*
1132  * For a given destination address, determine a source address to use.
1133  * Returns wildcard address if it cannot determine the source address.
1134  */
1135 static void
1136 select_src_addr(union any_in_addr *dst_addr, int family,
1137     union any_in_addr *src_addr)
1138 {
1139 	struct sockaddr *sock;
1140 	struct sockaddr_in *sin;
1141 	struct sockaddr_in6 *sin6;
1142 	int tmp_fd;
1143 	size_t sock_len;
1144 
1145 	sock = (struct sockaddr *)malloc(sizeof (struct sockaddr_in6));
1146 	if (sock == NULL) {
1147 		Fprintf(stderr, "%s: malloc: %s\n", progname, strerror(errno));
1148 		exit(EXIT_FAILURE);
1149 	}
1150 	(void) bzero(sock, sizeof (struct sockaddr_in6));
1151 
1152 	if (family == AF_INET) {
1153 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1154 		sin = (struct sockaddr_in *)sock;
1155 		sin->sin_family = AF_INET;
1156 		sin->sin_addr = dst_addr->addr;
1157 		sin->sin_port = IPPORT_ECHO;	/* port shouldn't be 0 */
1158 		sock_len = sizeof (struct sockaddr_in);
1159 	} else {
1160 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1161 		sin6 = (struct sockaddr_in6 *)sock;
1162 		sin6->sin6_family = AF_INET6;
1163 		sin6->sin6_addr = dst_addr->addr6;
1164 		sin6->sin6_port = IPPORT_ECHO;	/* port shouldn't be 0 */
1165 		sock_len = sizeof (struct sockaddr_in6);
1166 	}
1167 
1168 	/* open a UDP socket */
1169 	if ((tmp_fd = socket(family, SOCK_DGRAM, 0)) < 0) {
1170 		Fprintf(stderr, "%s: udp socket: %s\n", progname,
1171 		    strerror(errno));
1172 		exit(EXIT_FAILURE);
1173 	}
1174 
1175 	/* connect it */
1176 	if (connect(tmp_fd, sock, sock_len) < 0) {
1177 		/*
1178 		 * If there's no route to the destination, this connect() call
1179 		 * fails. We just return all-zero (wildcard) as the source
1180 		 * address, so that user can get to see "no route to dest"
1181 		 * message, as it'll try to send the probe packet out and will
1182 		 * receive ICMP unreachable.
1183 		 */
1184 		if (family == AF_INET)
1185 			src_addr->addr.s_addr = INADDR_ANY;
1186 		else
1187 			src_addr->addr6 = in6addr_any;
1188 		free(sock);
1189 		return;
1190 	}
1191 
1192 	/* get the local sock info */
1193 	if (getsockname(tmp_fd, sock, &sock_len) < 0) {
1194 		Fprintf(stderr, "%s: getsockname: %s\n", progname,
1195 		    strerror(errno));
1196 		exit(EXIT_FAILURE);
1197 	}
1198 
1199 	if (family == AF_INET) {
1200 		src_addr->addr = sin->sin_addr;
1201 	} else {
1202 		src_addr->addr6 = sin6->sin6_addr;
1203 	}
1204 
1205 	(void) close(tmp_fd);
1206 	free(sock);
1207 }
1208 
1209 /*
1210  * Set the IP_NEXTHOP/IPV6_NEXTHOP socket option.
1211  * exits on failure
1212  */
1213 static void
1214 set_nexthop(int family, struct addrinfo	*ai_nexthop, int sock)
1215 {
1216 	if (family == AF_INET) {
1217 		ipaddr_t nh;
1218 
1219 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1220 		nh = ((struct sockaddr_in *)ai_nexthop->
1221 		    ai_addr)->sin_addr.s_addr;
1222 
1223 		/* now we need the sys_ip_config privilege */
1224 		(void) __priv_bracket(PRIV_ON);
1225 		if (setsockopt(sock, IPPROTO_IP, IP_NEXTHOP,
1226 		    &nh, sizeof (ipaddr_t)) < 0) {
1227 			if (errno == EPERM)
1228 				Fprintf(stderr, "%s: Insufficient privilege "
1229 				    "to specify IPv4 nexthop router.\n",
1230 				    progname);
1231 			else
1232 				Fprintf(stderr, "%s: setsockopt %s\n",
1233 				    progname, strerror(errno));
1234 			exit(EXIT_FAILURE);
1235 		}
1236 		(void) __priv_bracket(PRIV_OFF);
1237 		/* revert to non-privileged user */
1238 	} else {
1239 		struct sockaddr_in6 *nh;
1240 
1241 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1242 		nh = (struct sockaddr_in6 *)ai_nexthop->
1243 		    ai_addr;
1244 
1245 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_NEXTHOP,
1246 		    nh, sizeof (struct sockaddr_in6)) < 0) {
1247 			Fprintf(stderr, "%s: setsockopt %s\n",
1248 			    progname, strerror(errno));
1249 			exit(EXIT_FAILURE);
1250 		}
1251 	}
1252 }
1253 
1254 /*
1255  * Setup the socket for the given address family.
1256  * Returns _B_TRUE on success, _B_FALSE on failure. Failure is the case when no
1257  * interface can be found, or the specified interface (-i) is not found. On
1258  * library call failures, it exit()s.
1259  */
1260 static boolean_t
1261 setup_socket(int family, int *send_sockp, int *recv_sockp, int *if_index,
1262     ushort_t *udp_src_port, struct addrinfo *ai_nexthop)
1263 {
1264 	int send_sock;
1265 	int recv_sock;
1266 	struct sockaddr_in6 sin6;
1267 	struct sockaddr_in sin;
1268 	struct sockaddr *sp;
1269 	struct ipsec_req req;
1270 	size_t slen;
1271 	int on = 1;
1272 	uchar_t char_op;
1273 	int int_op;
1274 
1275 	/* now we need the net_icmpaccess privilege */
1276 	(void) __priv_bracket(PRIV_ON);
1277 
1278 	recv_sock = socket(family, SOCK_RAW,
1279 	    (family == AF_INET) ? IPPROTO_ICMP : IPPROTO_ICMPV6);
1280 
1281 	if (recv_sock < 0) {
1282 		Fprintf(stderr, "%s: socket %s\n", progname, strerror(errno));
1283 		exit(EXIT_FAILURE);
1284 	}
1285 
1286 	/* revert to non-privileged user after opening sockets */
1287 	(void) __priv_bracket(PRIV_OFF);
1288 
1289 	if (bypass) {
1290 		(void) memset(&req, 0, sizeof (req));
1291 		req.ipsr_ah_req = IPSEC_PREF_NEVER;
1292 		req.ipsr_esp_req = IPSEC_PREF_NEVER;
1293 
1294 		if (setsockopt(recv_sock, (family == AF_INET) ? IPPROTO_IP :
1295 		    IPPROTO_IPV6, IP_SEC_OPT, &req, sizeof (req)) < 0) {
1296 			if (errno == EPERM)
1297 				Fprintf(stderr, "%s: Insufficient privilege "
1298 				    "to bypass IPsec policy.\n", progname);
1299 			else
1300 				Fprintf(stderr, "%s: setsockopt %s\n", progname,
1301 				    strerror(errno));
1302 			exit(EXIT_FAILURE);
1303 		}
1304 	}
1305 
1306 	if (nexthop != NULL && !use_udp)
1307 		set_nexthop(family, ai_nexthop, recv_sock);
1308 	/*
1309 	 * We always receive on raw icmp socket. But the sending socket can be
1310 	 * raw icmp or udp, depending on the use of -U flag.
1311 	 */
1312 	if (use_udp) {
1313 		send_sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
1314 		if (send_sock < 0) {
1315 			Fprintf(stderr, "%s: socket %s\n", progname,
1316 			    strerror(errno));
1317 			exit(EXIT_FAILURE);
1318 		}
1319 
1320 		if (bypass) {
1321 			if (setsockopt(send_sock, (family == AF_INET) ?
1322 			    IPPROTO_IP : IPPROTO_IPV6, IP_SEC_OPT, &req,
1323 			    sizeof (req)) < 0) {
1324 				if (errno == EPERM)
1325 					Fprintf(stderr, "%s: Insufficient "
1326 					    "privilege to bypass IPsec "
1327 					    "policy.\n", progname);
1328 				else
1329 					Fprintf(stderr, "%s: setsockopt %s\n",
1330 					    progname, strerror(errno));
1331 				exit(EXIT_FAILURE);
1332 			}
1333 		}
1334 
1335 		if (nexthop != NULL)
1336 			set_nexthop(family, ai_nexthop, send_sock);
1337 
1338 		/*
1339 		 * In order to distinguish replies to our UDP probes from
1340 		 * other pings', we need to know our source port number.
1341 		 */
1342 		if (family == AF_INET) {
1343 			sp = (struct sockaddr *)&sin;
1344 			slen = sizeof (sin);
1345 		} else {
1346 			sp = (struct sockaddr *)&sin6;
1347 			slen = sizeof (sin6);
1348 		}
1349 		bzero(sp, slen);
1350 		sp->sa_family = family;
1351 
1352 		/* Let's bind() send_sock to wildcard address and port */
1353 		if (bind(send_sock, sp, slen) < 0) {
1354 			Fprintf(stderr, "%s: bind %s\n", progname,
1355 			    strerror(errno));
1356 			exit(EXIT_FAILURE);
1357 		}
1358 
1359 		/* .... and see what port kernel picked for us */
1360 		if (getsockname(send_sock, sp, &slen) < 0) {
1361 			Fprintf(stderr, "%s: getsockname %s\n", progname,
1362 			    strerror(errno));
1363 			exit(EXIT_FAILURE);
1364 		}
1365 		*udp_src_port = (family == AF_INET) ? sin.sin_port :
1366 		    sin6.sin6_port;
1367 	} else {
1368 		send_sock = recv_sock;
1369 	}
1370 
1371 	int_op = 48 * 1024;
1372 	if (int_op < datalen)
1373 		int_op = datalen;
1374 	if (setsockopt(recv_sock, SOL_SOCKET, SO_RCVBUF, (char *)&int_op,
1375 	    sizeof (int_op)) == -1) {
1376 		Fprintf(stderr, "%s: setsockopt SO_RCVBUF %s\n", progname,
1377 		    strerror(errno));
1378 		exit(EXIT_FAILURE);
1379 	}
1380 
1381 	if (setsockopt(send_sock, SOL_SOCKET, SO_SNDBUF, (char *)&int_op,
1382 	    sizeof (int_op)) == -1) {
1383 		Fprintf(stderr, "%s: setsockopt SO_SNDBUF %s\n", progname,
1384 		    strerror(errno));
1385 		exit(EXIT_FAILURE);
1386 	}
1387 
1388 	if (options & SO_DEBUG) {
1389 		if (setsockopt(send_sock, SOL_SOCKET, SO_DEBUG, (char *)&on,
1390 		    sizeof (on)) == -1) {
1391 			Fprintf(stderr, "%s: setsockopt SO_DEBUG %s\n",
1392 			    progname, strerror(errno));
1393 			exit(EXIT_FAILURE);
1394 		}
1395 	}
1396 
1397 	if (options & SO_DONTROUTE) {
1398 		if (setsockopt(send_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
1399 		    sizeof (on)) == -1) {
1400 			Fprintf(stderr, "%s: setsockopt SO_DONTROUTE %s\n",
1401 			    progname, strerror(errno));
1402 			exit(EXIT_FAILURE);
1403 		}
1404 	}
1405 
1406 	if (moptions & MULTICAST_NOLOOP) {
1407 		if (family == AF_INET) {
1408 			char_op = 0;	/* used to turn off option */
1409 
1410 			if (setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_LOOP,
1411 			    (char *)&char_op, sizeof (char_op)) == -1) {
1412 				Fprintf(stderr, "%s: setsockopt "
1413 				    "IP_MULTICAST_NOLOOP %s\n", progname,
1414 				    strerror(errno));
1415 				exit(EXIT_FAILURE);
1416 			}
1417 		} else {
1418 			int_op = 0;	/* used to turn off option */
1419 
1420 			if (setsockopt(send_sock, IPPROTO_IPV6,
1421 			    IPV6_MULTICAST_LOOP, (char *)&int_op,
1422 			    sizeof (int_op)) == -1) {
1423 				Fprintf(stderr, "%s: setsockopt "
1424 				    "IPV6_MULTICAST_NOLOOP %s\n", progname,
1425 				    strerror(errno));
1426 				exit(EXIT_FAILURE);
1427 			}
1428 		}
1429 	}
1430 
1431 	if (moptions & MULTICAST_TTL) {
1432 		char_op = hoplimit;
1433 
1434 		if (family == AF_INET) {
1435 			if (setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL,
1436 			    (char *)&char_op, sizeof (char)) == -1) {
1437 				Fprintf(stderr, "%s: setsockopt "
1438 				    "IP_MULTICAST_TTL %s\n", progname,
1439 				    strerror(errno));
1440 				exit(EXIT_FAILURE);
1441 			}
1442 			if (setsockopt(send_sock, IPPROTO_IP, IP_TTL,
1443 			    (char *)&hoplimit, sizeof (hoplimit)) == -1) {
1444 				Fprintf(stderr, "%s: setsockopt IP_TTL %s\n",
1445 				    progname, strerror(errno));
1446 				exit(EXIT_FAILURE);
1447 			}
1448 		}
1449 		/*
1450 		 * AF_INET6 case is handled in set_ancillary_data() function.
1451 		 * This is because when ancillary data is used (for routing
1452 		 * header and outgoing interface index), the hoplimit set using
1453 		 * setsockopt() is ignored.
1454 		 */
1455 	}
1456 
1457 	/* did the user specify an interface? */
1458 	if (moptions & MULTICAST_IF) {
1459 		struct ifaddrlist *al = NULL;		/* interface list */
1460 		struct ifaddrlist *my_if;
1461 		char errbuf[ERRBUFSIZE];
1462 		int num_ifs;
1463 		int num_src_ifs;		/* exclude down and loopback */
1464 		int i;
1465 
1466 		/* pull out the interface list */
1467 		num_ifs = ifaddrlist(&al, family, LIFC_UNDER_IPMP, errbuf);
1468 		if (num_ifs == -1) {
1469 			Fprintf(stderr, "%s: %s\n", progname, errbuf);
1470 			exit(EXIT_FAILURE);
1471 		}
1472 
1473 		/* filter out down and loopback interfaces */
1474 		num_src_ifs = 0;
1475 		for (i = 0; i < num_ifs; i++) {
1476 			if (!(al[i].flags & IFF_LOOPBACK) &&
1477 			    (al[i].flags & IFF_UP))
1478 				num_src_ifs++;
1479 		}
1480 
1481 		if (num_src_ifs == 0) {
1482 			Fprintf(stderr, "%s: can't find any %s interface\n",
1483 			    progname, (family == AF_INET) ? "IPv4" : "IPv6");
1484 
1485 			return (_B_FALSE);	/* failure */
1486 		}
1487 
1488 		/* locate the specified interface */
1489 		my_if = find_if(al, num_ifs);
1490 		if (my_if == NULL) {
1491 			Fprintf(stderr, "%s: %s is an invalid %s interface\n",
1492 			    progname, out_if.str,
1493 			    (family == AF_INET) ? "IPv4" : "IPv6");
1494 
1495 			return (_B_FALSE);
1496 		}
1497 
1498 		if (family == AF_INET) {
1499 			if (setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_IF,
1500 			    (char *)&my_if->addr.addr,
1501 			    sizeof (struct in_addr)) == -1) {
1502 				Fprintf(stderr, "%s: setsockopt "
1503 				    "IP_MULTICAST_IF %s\n", progname,
1504 				    strerror(errno));
1505 				exit(EXIT_FAILURE);
1506 			}
1507 		} else {
1508 			/*
1509 			 * the outgoing interface is set in set_ancillary_data()
1510 			 * function
1511 			 */
1512 			*if_index = my_if->index;
1513 		}
1514 
1515 		free(al);
1516 	}
1517 
1518 	if (settos && family == AF_INET) {
1519 		int_op = tos;
1520 		if (setsockopt(send_sock, IPPROTO_IP, IP_TOS, (char *)&int_op,
1521 		    sizeof (int_op)) == -1) {
1522 			Fprintf(stderr, "%s: setsockopt IP_TOS %s\n",
1523 			    progname, strerror(errno));
1524 			exit(EXIT_FAILURE);
1525 		}
1526 	}
1527 
1528 	/* receiving IPv6 extension headers in verbose mode */
1529 	if (verbose && family == AF_INET6) {
1530 		if (setsockopt(recv_sock, IPPROTO_IPV6, IPV6_RECVHOPOPTS,
1531 		    (char *)&on, sizeof (on)) == -1) {
1532 			Fprintf(stderr, "%s: setsockopt IPV6_RECVHOPOPTS %s\n",
1533 			    progname, strerror(errno));
1534 			exit(EXIT_FAILURE);
1535 		}
1536 
1537 		if (setsockopt(recv_sock, IPPROTO_IPV6, IPV6_RECVDSTOPTS,
1538 		    (char *)&on, sizeof (on)) == -1) {
1539 			Fprintf(stderr, "%s: setsockopt IPV6_RECVDSTOPTS %s\n",
1540 			    progname, strerror(errno));
1541 			exit(EXIT_FAILURE);
1542 		}
1543 
1544 		if (setsockopt(recv_sock, IPPROTO_IPV6, IPV6_RECVRTHDR,
1545 		    (char *)&on, sizeof (on)) == -1) {
1546 			Fprintf(stderr, "%s: setsockopt IPV6_RECVRTHDR %s\n",
1547 			    progname, strerror(errno));
1548 			exit(EXIT_FAILURE);
1549 		}
1550 	}
1551 
1552 	*send_sockp = send_sock;
1553 	*recv_sockp = recv_sock;
1554 
1555 	/* successful */
1556 	return (_B_TRUE);
1557 }
1558 
1559 /*
1560  * Pull out the record containing all the info about the interface specified by
1561  * `out_if'. Skips interfaces which are down or loopback.
1562  */
1563 static struct ifaddrlist *
1564 find_if(struct ifaddrlist *al, int num_ifs)
1565 {
1566 	static struct ifaddrlist tmp_if;
1567 	boolean_t found;
1568 	int i;
1569 
1570 	i = 0;
1571 	found = _B_FALSE;
1572 
1573 	while (i < num_ifs && !found) {
1574 		tmp_if = al[i];
1575 
1576 		/* skip down or loopback interfaces */
1577 		if ((tmp_if.flags & IFF_LOOPBACK) || !(tmp_if.flags & IFF_UP)) {
1578 			i++;
1579 			continue;
1580 		}
1581 
1582 		/* the type of interface id is variable */
1583 		switch (out_if.id_type) {
1584 		case IF_INDEX:
1585 			if (out_if.id.index == tmp_if.index)
1586 				found = _B_TRUE;
1587 			break;
1588 
1589 		case IF_NAME:
1590 			if (strcmp(out_if.id.name, tmp_if.device) == 0)
1591 				found = _B_TRUE;
1592 			break;
1593 
1594 		case IF_ADDR:
1595 			if (out_if.id.addr.addr.s_addr ==
1596 			    tmp_if.addr.addr.s_addr) {
1597 				found = _B_TRUE;
1598 			}
1599 			break;
1600 
1601 		case IF_ADDR6:
1602 			if (IN6_ARE_ADDR_EQUAL(&out_if.id.addr.addr6,
1603 			    &tmp_if.addr.addr6)) {
1604 				found = _B_TRUE;
1605 			}
1606 			break;
1607 
1608 		default:
1609 			break;
1610 		}
1611 
1612 		i++;
1613 	}
1614 
1615 	if (found)
1616 		return (&tmp_if);
1617 	else
1618 		return (NULL);
1619 }
1620 
1621 /*
1622  * Invoked by SIGALRM, sigalrm_handler() is, responsible for calling
1623  * send_scheduled_probe() to send next probe.
1624  */
1625 void
1626 sigalrm_handler(void)
1627 {
1628 	/*
1629 	 * Guard againist denial-of-service attacks. Make sure ping doesn't
1630 	 * send probes for every SIGALRM it receives. Evil hacker can generate
1631 	 * SIGALRMs as fast as it can, but ping will ignore those which are
1632 	 * received too soon (earlier than 0.5 sec) after it sent the last
1633 	 * probe.  We use gethrtime() instead of gettimeofday() because
1634 	 * the latter is not linear and is prone to resetting or drifting
1635 	 */
1636 	if ((gethrtime() - t_last_probe_sent) < 500000000) {
1637 		return;
1638 	}
1639 	send_scheduled_probe();
1640 	schedule_sigalrm();
1641 }
1642 
1643 /*
1644  * Schedule next SIGALRM.
1645  */
1646 void
1647 schedule_sigalrm(void)
1648 {
1649 	int waittime;
1650 
1651 	if (npackets == 0 ||
1652 	    current_targetaddr->num_sent < current_targetaddr->num_probes) {
1653 		(void) alarm(interval);
1654 	} else {
1655 		if (current_targetaddr->got_reply) {
1656 			waittime = 2 * tmax / MICROSEC;
1657 			if (waittime == 0)
1658 				waittime = 1;
1659 		} else {
1660 			waittime = MAX_WAIT;
1661 		}
1662 		(void) alarm(waittime);
1663 	}
1664 }
1665 
1666 /*
1667  * Called by sigalrm_handler(), check_reply() or check_reply6(),
1668  * send_scheduled_probe() looks at the current_targetaddr and determines what
1669  * should be sent next and calls pinger().
1670  */
1671 void
1672 send_scheduled_probe()
1673 {
1674 	static struct msghdr msg6;
1675 	static boolean_t first_probe = _B_TRUE;
1676 	char tmp_buf[INET6_ADDRSTRLEN];
1677 
1678 	/*
1679 	 * We are about to move to next targetaddr if it's either we sent
1680 	 * all the probes, or somebody set the probing_done flag to
1681 	 * _B_TRUE prompting us to move on.
1682 	 */
1683 	if (current_targetaddr->num_sent == current_targetaddr->num_probes ||
1684 	    current_targetaddr->probing_done) {
1685 		/*
1686 		 * is this a dead target?
1687 		 */
1688 		if (!stats && !current_targetaddr->got_reply) {
1689 			if (!probe_all) {
1690 				Printf("no answer from %s\n", targethost);
1691 			} else {
1692 				Printf("no answer from %s(%s)\n", targethost,
1693 				    inet_ntop(current_targetaddr->family,
1694 				    &current_targetaddr->dst_addr,
1695 				    tmp_buf, sizeof (tmp_buf)));
1696 			}
1697 		}
1698 		/*
1699 		 * Before we move onto next item, let's do some clean up.
1700 		 */
1701 		current_targetaddr->got_reply = _B_FALSE;
1702 		current_targetaddr->probing_done = _B_FALSE;
1703 		/*
1704 		 * If this is probe-all without stats mode, then we need to
1705 		 * preserve this count. This is needed when we try to map an
1706 		 * icmp_seq to IP address. Otherwise, clear it.
1707 		 */
1708 		if (stats || !probe_all)
1709 			current_targetaddr->num_sent = 0;
1710 		nreceived_last_target = 0;
1711 
1712 		current_targetaddr = current_targetaddr->next;
1713 
1714 		/*
1715 		 * Did we reach the end of road?
1716 		 */
1717 		if (current_targetaddr == NULL) {
1718 			(void) alarm(0);	/* cancel alarm */
1719 			if (stats)
1720 				finish();
1721 			if (is_alive)
1722 				exit(EXIT_SUCCESS);
1723 			else
1724 				exit(EXIT_FAILURE);
1725 		} else {
1726 			/*
1727 			 * We use starting_seq_num for authenticating replies.
1728 			 * Each time we move to a new targetaddr, which has
1729 			 * a different target IP address, we update this field.
1730 			 */
1731 			current_targetaddr->starting_seq_num = use_udp ?
1732 			    dest_port : (ntransmitted % (MAX_ICMP_SEQ + 1));
1733 		}
1734 	}
1735 
1736 	if (current_targetaddr->family == AF_INET6) {
1737 		if (send_reply) {
1738 			/* sending back to ourself */
1739 			to6.sin6_addr = current_targetaddr->src_addr.addr6;
1740 		} else {
1741 			to6.sin6_addr = current_targetaddr->dst_addr.addr6;
1742 		}
1743 		/*
1744 		 * Setting the ancillary data once is enough, if we are
1745 		 * not using source routing through target (-l/-S). In
1746 		 * case -l/-S used, the middle gateway will be the
1747 		 * IP address of the source, which can be different
1748 		 * for each target IP.
1749 		 */
1750 		if (first_probe ||
1751 		    (send_reply && current_targetaddr->num_sent == 0)) {
1752 			if (send_reply) {
1753 				/* target is the middle gateway now */
1754 				gw_IP_list6[num_gw].addr6 =
1755 				    current_targetaddr->dst_addr.addr6;
1756 			}
1757 			set_ancillary_data(&msg6, hoplimit, gw_IP_list6,
1758 			    eff_num_gw, if_index);
1759 			first_probe = _B_FALSE;
1760 		}
1761 		pinger(send_sock6, (struct sockaddr *)&to6, &msg6, AF_INET6);
1762 	} else {
1763 		to.sin_addr = current_targetaddr->dst_addr.addr;
1764 		/*
1765 		 * Set IPv4 options when sending the first probe to a target
1766 		 * IP address. Some options change when the target address
1767 		 * changes.
1768 		 */
1769 		if (current_targetaddr->num_sent == 0) {
1770 			if (eff_num_gw > 0) {
1771 				gw_IP_list[num_gw].addr =
1772 				    current_targetaddr->dst_addr.addr;
1773 				/*
1774 				 * If send_reply, the target becomes the
1775 				 * middle gateway, sender becomes the last
1776 				 * gateway.
1777 				 */
1778 				if (send_reply) {
1779 					gw_IP_list[eff_num_gw].addr =
1780 					    current_targetaddr->src_addr.addr;
1781 				}
1782 			}
1783 			/*
1784 			 * In IPv4, if source routing is used, the target
1785 			 * address shows up as the last gateway, hence +1.
1786 			 */
1787 			set_IPv4_options(send_sock, gw_IP_list,
1788 			    (eff_num_gw > 0) ? eff_num_gw + 1 : 0,
1789 			    &current_targetaddr->src_addr.addr, &to.sin_addr);
1790 		}
1791 		pinger(send_sock, (struct sockaddr *)&to, NULL, AF_INET);
1792 	}
1793 
1794 	current_targetaddr->num_sent++;
1795 }
1796 
1797 /*
1798  * recv_icmp_packet()'s job is to listen to icmp packets and filter out
1799  * those ping is interested in.
1800  */
1801 static void
1802 recv_icmp_packet(struct addrinfo *ai_dst, int recv_sock6, int recv_sock,
1803 ushort_t udp_src_port6, ushort_t udp_src_port)
1804 {
1805 	struct msghdr in_msg;
1806 	struct iovec iov;
1807 	struct sockaddr_in6 from6;
1808 	fd_set fds;
1809 	int result;
1810 	int cc;
1811 	boolean_t always_true = _B_TRUE; /* lint doesn't like while(_B_TRUE) */
1812 
1813 	while (always_true) {
1814 		(void) FD_ZERO(&fds);
1815 		if (recv_sock6 != -1)
1816 			FD_SET(recv_sock6, &fds);
1817 		if (recv_sock != -1)
1818 			FD_SET(recv_sock, &fds);
1819 
1820 		result = select(MAX(recv_sock6, recv_sock) + 1, &fds,
1821 		    (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL);
1822 		if (result == -1) {
1823 			if (errno == EINTR) {
1824 				continue;
1825 			} else {
1826 				Fprintf(stderr, "%s: select %s\n", progname,
1827 				    strerror(errno));
1828 				exit(EXIT_FAILURE);
1829 			}
1830 		} else if (result > 0) {
1831 			in_msg.msg_name = &from6;
1832 			in_msg.msg_namelen = sizeof (from6);
1833 			iov.iov_base = in_pkt;
1834 			iov.iov_len = sizeof (in_pkt);
1835 			in_msg.msg_iov = &iov;
1836 			in_msg.msg_iovlen = 1;
1837 			in_msg.msg_control = ancillary_data;
1838 			in_msg.msg_controllen = sizeof (ancillary_data);
1839 
1840 			/* Do we have an ICMP6 packet waiting? */
1841 			if ((recv_sock6 != -1) &&
1842 			    (FD_ISSET(recv_sock6, &fds))) {
1843 				cc = recvmsg(recv_sock6, &in_msg, 0);
1844 				if (cc < 0) {
1845 					if (errno != EINTR) {
1846 						Fprintf(stderr,
1847 						    "%s: recvmsg %s\n",
1848 						    progname, strerror(errno));
1849 					}
1850 					continue;
1851 				} else if (cc > 0) {
1852 					check_reply6(ai_dst, &in_msg, cc,
1853 					    udp_src_port6);
1854 				}
1855 			}
1856 			/* Do we have an ICMP packet waiting? */
1857 			if ((recv_sock != -1) && (FD_ISSET(recv_sock, &fds))) {
1858 				cc = recvmsg(recv_sock, &in_msg, 0);
1859 				if (cc < 0) {
1860 					if (errno != EINTR) {
1861 						Fprintf(stderr,
1862 						    "%s: recvmsg %s\n",
1863 						    progname, strerror(errno));
1864 					}
1865 					continue;
1866 				} if (cc > 0) {
1867 					check_reply(ai_dst, &in_msg, cc,
1868 					    udp_src_port);
1869 				}
1870 			}
1871 		}
1872 		/*
1873 		 * If we were probing last IP address of the target host and
1874 		 * received a reply for each probe sent to this address,
1875 		 * then we are done!
1876 		 */
1877 		if ((npackets > 0) && (current_targetaddr->next == NULL) &&
1878 		    (nreceived_last_target == npackets)) {
1879 			(void) alarm(0);	/* cancel alarm */
1880 			finish();
1881 		}
1882 	} /* infinite loop */
1883 }
1884 
1885 /*
1886  * Given a host (with possibly multiple IP addresses) and an IP address, this
1887  * function determines if this IP address is one of the host's addresses to
1888  * which we're sending probes. Used to determine if we are interested in a
1889  * packet.
1890  */
1891 boolean_t
1892 is_a_target(struct addrinfo *ai, union any_in_addr *addr)
1893 {
1894 	int num_addrs;
1895 	int i;
1896 	struct addrinfo *aip;
1897 
1898 	aip = ai;
1899 	if (probe_all)
1900 		num_addrs = num_v4 + num_v6;
1901 	else
1902 		num_addrs = 1;
1903 	for (i = 0; i < num_addrs && aip != NULL; i++) {
1904 		if (aip->ai_family == AF_INET6) {
1905 			/* LINTED E_BAD_PTR_CAST_ALIGN */
1906 			if (IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)
1907 			    aip->ai_addr)->sin6_addr, &addr->addr6))
1908 				return (_B_TRUE);
1909 		} else {
1910 			/* LINTED E_BAD_PTR_CAST_ALIGN */
1911 			if (((struct sockaddr_in *)
1912 			    aip->ai_addr)->sin_addr.s_addr == addr->addr.s_addr)
1913 				return (_B_TRUE);
1914 		}
1915 	}
1916 
1917 	return (_B_FALSE);
1918 }
1919 
1920 /*
1921  * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
1922  * will be added on by the kernel.  The ID field is our UNIX process ID,
1923  * and the sequence number is an ascending integer.  The first 8 bytes
1924  * of the data portion are used to hold a UNIX "timeval" struct in network
1925  * byte-order, to compute the round-trip time.
1926  */
1927 static void
1928 pinger(int send_sock, struct sockaddr *whereto, struct msghdr *msg6,
1929     int family)
1930 {
1931 	static uint64_t out_pkt_buf[(IP_MAXPACKET + 1) / 8];
1932 	uchar_t *out_pkt = (uchar_t *)&out_pkt_buf;
1933 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1934 	struct icmp *icp = (struct icmp *)out_pkt;
1935 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1936 	struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)whereto;
1937 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1938 	struct sockaddr_in *to = (struct sockaddr_in *)whereto;
1939 	struct timeval *tp;
1940 	struct timeval t_snd;
1941 	uchar_t *datap;
1942 	struct iovec iov;
1943 	int start = 0;
1944 	int cc;
1945 	int i;
1946 
1947 	/* using UDP? */
1948 	if (use_udp) {
1949 		cc = datalen;
1950 
1951 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1952 		tp = (struct timeval *)out_pkt;
1953 		datap = &out_pkt[sizeof (struct timeval)];
1954 
1955 		/*
1956 		 * This sets the port whether we are handling a v4 or v6
1957 		 * sockaddr structure.
1958 		 */
1959 		to->sin_port = htons(dest_port);
1960 
1961 		dest_port = (dest_port + 1) % (MAX_PORT + 1);
1962 		ntransmitted++;
1963 	} else {	/* using ICMP */
1964 		cc = datalen + ICMP_MINLEN;
1965 
1966 		if (family == AF_INET6) {
1967 			icp->icmp_type = send_reply ?
1968 			    ICMP6_ECHO_REPLY : ICMP6_ECHO_REQUEST;
1969 		} else if (use_icmp_ts) {	/* family is AF_INET */
1970 			icp->icmp_type = send_reply ?
1971 			    ICMP_TSTAMPREPLY : ICMP_TSTAMP;
1972 		} else {
1973 			icp->icmp_type = send_reply ?
1974 			    ICMP_ECHOREPLY : ICMP_ECHO;
1975 		}
1976 
1977 		icp->icmp_code = 0;
1978 		icp->icmp_cksum = 0;
1979 		icp->icmp_seq = htons(ntransmitted++ % (MAX_ICMP_SEQ + 1));
1980 		if (icp->icmp_seq == 0)
1981 			num_wraps++;
1982 		icp->icmp_id = htons(ident);		/* ID */
1983 
1984 		/* LINTED E_BAD_PTR_CAST_ALIGN */
1985 		tp = (struct timeval *)&out_pkt[ICMP_MINLEN];
1986 		datap = &out_pkt[ICMP_MINLEN + sizeof (struct timeval)];
1987 	}
1988 
1989 	start = sizeof (struct timeval);	/* skip for time */
1990 
1991 	(void) gettimeofday(&t_snd, (struct timezone *)NULL);
1992 
1993 	/* if packet is big enough to store timeval OR ... */
1994 	if ((datalen >= sizeof (struct timeval)) ||
1995 	    (family == AF_INET && use_icmp_ts))
1996 		*tp = t_snd;
1997 
1998 	if (family == AF_INET && use_icmp_ts) {
1999 		start = sizeof (struct id_ts);	/* skip for ICMP timestamps */
2000 		/* Number of milliseconds since midnight */
2001 		icp->icmp_otime = htonl((tp->tv_sec % (24*60*60)) * 1000 +
2002 		    tp->tv_usec / 1000);
2003 	}
2004 
2005 	for (i = start; i < datalen; i++)
2006 		*datap++ = i;
2007 
2008 	if (family == AF_INET) {
2009 		if (!use_udp)
2010 			icp->icmp_cksum = in_cksum((ushort_t *)icp, cc);
2011 
2012 		i = sendto(send_sock, (char *)out_pkt, cc, 0, whereto,
2013 		    sizeof (struct sockaddr_in));
2014 	} else {
2015 		/*
2016 		 * Fill in the rest of the msghdr structure. msg_control is set
2017 		 * in set_ancillary_data().
2018 		 */
2019 		msg6->msg_name = to6;
2020 		msg6->msg_namelen = sizeof (struct sockaddr_in6);
2021 
2022 		iov.iov_base = out_pkt;
2023 		iov.iov_len = cc;
2024 
2025 		msg6->msg_iov = &iov;
2026 		msg6->msg_iovlen = 1;
2027 
2028 		i = sendmsg(send_sock, msg6, 0);
2029 	}
2030 
2031 	/* This is a more precise time (right after we send the packet) */
2032 	t_last_probe_sent = gethrtime();
2033 
2034 	if (i < 0 || i != cc)  {
2035 		if (i < 0) {
2036 			Fprintf(stderr, "%s: sendto %s\n", progname,
2037 			    strerror(errno));
2038 			if (!stats)
2039 				exit(EXIT_FAILURE);
2040 		}
2041 		Printf("ping: wrote %s %d chars, ret=%d\n",
2042 		    targethost, cc, i);
2043 		(void) fflush(stdout);
2044 	}
2045 }
2046 
2047 /*
2048  * Return a hostname for the given IP address.
2049  */
2050 char *
2051 pr_name(char *addr, int family)
2052 {
2053 	struct sockaddr_in sin;
2054 	struct sockaddr_in6 sin6;
2055 	struct sockaddr *sa;
2056 	static struct in6_addr prev_addr = IN6ADDR_ANY_INIT;
2057 	char *cp;
2058 	char abuf[INET6_ADDRSTRLEN];
2059 	static char buf[NI_MAXHOST + INET6_ADDRSTRLEN + 3];
2060 	uint_t slen, alen, hlen;
2061 
2062 	switch (family) {
2063 	case AF_INET:
2064 		(void) memset(&sin, 0, sizeof (sin));
2065 		slen = sizeof (struct sockaddr_in);
2066 		alen = sizeof (struct in_addr);
2067 		/* LINTED E_BAD_PTR_CAST_ALIGN */
2068 		sin.sin_addr = *(struct in_addr *)addr;
2069 		sin.sin_port = 0;
2070 		sa = (struct sockaddr *)&sin;
2071 		break;
2072 	case AF_INET6:
2073 		(void) memset(&sin6, 0, sizeof (sin6));
2074 		slen = sizeof (struct sockaddr_in6);
2075 		alen = sizeof (struct in6_addr);
2076 		/* LINTED E_BAD_PTR_CAST_ALIGN */
2077 		sin6.sin6_addr = *(struct in6_addr *)addr;
2078 		sin6.sin6_port = 0;
2079 		sa = (struct sockaddr *)&sin6;
2080 		break;
2081 	default:
2082 		(void) snprintf(buf, sizeof (buf), "<invalid address family>");
2083 		return (buf);
2084 	}
2085 	sa->sa_family = family;
2086 
2087 	/* compare with the buffered (previous) lookup */
2088 	if (memcmp(addr, &prev_addr, alen) != 0) {
2089 		int flags = (nflag) ? NI_NUMERICHOST : NI_NAMEREQD;
2090 		if (getnameinfo(sa, slen, buf, sizeof (buf),
2091 		    NULL, 0, flags) != 0) {
2092 			/* getnameinfo() failed; return just the address */
2093 			if (inet_ntop(family, (const void*)addr,
2094 			    buf, sizeof (buf)) == NULL)
2095 				buf[0] = 0;
2096 		} else if (!nflag) {
2097 			/* append numeric address to hostname string */
2098 			hlen = strlen(buf);
2099 			cp = (char *)(buf + hlen);
2100 			(void) snprintf(cp, sizeof (buf) - hlen, " (%s)",
2101 			    inet_ntop(family, (const void *)addr, abuf,
2102 			    sizeof (abuf)));
2103 		}
2104 
2105 		/* LINTED E_BAD_PTR_CAST_ALIGN */
2106 		prev_addr = *(struct in6_addr *)addr;
2107 	}
2108 	return (buf);
2109 }
2110 
2111 /*
2112  * Return the protocol string, given its protocol number.
2113  */
2114 char *
2115 pr_protocol(int prot)
2116 {
2117 	static char buf[20];
2118 
2119 	switch (prot) {
2120 	case IPPROTO_ICMPV6:
2121 		(void) strlcpy(buf, "icmp6", sizeof (buf));
2122 		break;
2123 
2124 	case IPPROTO_ICMP:
2125 		(void) strlcpy(buf, "icmp", sizeof (buf));
2126 		break;
2127 
2128 	case IPPROTO_TCP:
2129 		(void) strlcpy(buf, "tcp", sizeof (buf));
2130 		break;
2131 
2132 	case IPPROTO_UDP:
2133 		(void) strlcpy(buf, "udp", sizeof (buf));
2134 		break;
2135 
2136 	default:
2137 		(void) snprintf(buf, sizeof (buf), "prot %d", prot);
2138 		break;
2139 	}
2140 
2141 	return (buf);
2142 }
2143 
2144 /*
2145  * Checks if value is between seq_begin and seq_begin+seq_len. Note that
2146  * sequence numbers wrap around after MAX_ICMP_SEQ (== MAX_PORT).
2147  */
2148 boolean_t
2149 seq_match(ushort_t seq_begin, int seq_len, ushort_t value)
2150 {
2151 	/*
2152 	 * If seq_len is too big, like some value greater than MAX_ICMP_SEQ/2,
2153 	 * truncate it down to MAX_ICMP_SEQ/2. We are not going to accept any
2154 	 * reply which come 83hr later!
2155 	 */
2156 	if (seq_len > MAX_ICMP_SEQ / 2) {
2157 		seq_begin = (seq_begin + seq_len - MAX_ICMP_SEQ / 2) %
2158 		    (MAX_ICMP_SEQ + 1);
2159 		seq_len = MAX_ICMP_SEQ / 2;
2160 	}
2161 
2162 	if (PINGSEQ_LEQ(seq_begin, value) &&
2163 	    PINGSEQ_LEQ(value, (seq_begin + seq_len - 1) % (MAX_ICMP_SEQ + 1)))
2164 		return (_B_TRUE);
2165 	else
2166 		return (_B_FALSE);
2167 }
2168 
2169 /*
2170  * For a given icmp_seq, find which destination address we must have sent this
2171  * to.
2172  */
2173 void
2174 find_dstaddr(ushort_t icmpseq, union any_in_addr *ipaddr)
2175 {
2176 	struct targetaddr *target = targetaddr_list;
2177 	int real_seq;
2178 	int targetaddr_index;
2179 	int real_npackets;
2180 	int i;
2181 
2182 	ipaddr->addr6 = in6addr_any;
2183 
2184 	/*
2185 	 * If this is probe_all and not stats, then the number of probes sent to
2186 	 * each IP address may be different (remember, we stop sending to one IP
2187 	 * address as soon as it replies). They are stored in target->num_sent
2188 	 * field. Since we don't wrap around the list (!stats), they are also
2189 	 * preserved.
2190 	 */
2191 	if (probe_all && !stats) {
2192 		do {
2193 			if (seq_match(target->starting_seq_num,
2194 			    target->num_sent, icmpseq)) {
2195 				ipaddr->addr6 = target->dst_addr.addr6;
2196 				/*
2197 				 * We are not immediately return()ing here.
2198 				 * Because of wrapping, we might find another
2199 				 * match later, which is more likely to be the
2200 				 * real one.
2201 				 */
2202 			}
2203 			target = target->next;
2204 		} while (target != NULL);
2205 	} else {
2206 		/*
2207 		 * Find the absolute (non-wrapped) seq number within the last
2208 		 * 64K
2209 		 */
2210 		if (icmpseq < (ntransmitted % (MAX_ICMP_SEQ + 1))) {
2211 			real_seq = num_wraps * (MAX_ICMP_SEQ + 1) + icmpseq;
2212 		} else {
2213 			real_seq = (num_wraps - 1) * (MAX_ICMP_SEQ + 1) +
2214 			    icmpseq;
2215 		}
2216 
2217 		/* Make sure it's non-negative */
2218 		if (real_seq < 0)
2219 			return;
2220 		real_npackets = (npackets == 0) ? 1 : npackets;
2221 
2222 		/*
2223 		 * We sent npackets many packets to each of those
2224 		 * num_targetaddrs many IP addresses.
2225 		 */
2226 		targetaddr_index =
2227 		    (real_seq % (num_targetaddrs * real_npackets)) /
2228 		    real_npackets;
2229 		for (i = 0; i < targetaddr_index; i++)
2230 			target = target->next;
2231 		ipaddr->addr6 = target->dst_addr.addr6;
2232 	}
2233 }
2234 
2235 /*
2236  * Checksum routine for Internet Protocol family headers (C Version)
2237  */
2238 static ushort_t
2239 in_cksum(ushort_t *addr, int len)
2240 {
2241 	int nleft = len;
2242 	ushort_t *w = addr;
2243 	ushort_t answer;
2244 	ushort_t odd_byte = 0;
2245 	int sum = 0;
2246 
2247 	/*
2248 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
2249 	 *  we add sequential 16 bit words to it, and at the end, fold
2250 	 *  back all the carry bits from the top 16 bits into the lower
2251 	 *  16 bits.
2252 	 */
2253 	while (nleft > 1) {
2254 		sum += *w++;
2255 		nleft -= 2;
2256 	}
2257 
2258 	/* mop up an odd byte, if necessary */
2259 	if (nleft == 1) {
2260 		*(uchar_t *)(&odd_byte) = *(uchar_t *)w;
2261 		sum += odd_byte;
2262 	}
2263 
2264 	/*
2265 	 * add back carry outs from top 16 bits to low 16 bits
2266 	 */
2267 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
2268 	sum += (sum >> 16);			/* add carry */
2269 	answer = ~sum;				/* truncate to 16 bits */
2270 	return (answer);
2271 }
2272 
2273 /*
2274  * Subtract 2 timeval structs:  out = out - in.
2275  * Out is assumed to be >= in.
2276  */
2277 void
2278 tvsub(struct timeval *out, struct timeval *in)
2279 {
2280 	if ((out->tv_usec -= in->tv_usec) < 0) {
2281 		out->tv_sec--;
2282 		out->tv_usec += 1000000;
2283 	}
2284 	out->tv_sec -= in->tv_sec;
2285 }
2286 
2287 /*
2288  * Print out statistics, and give up.
2289  * Heavily buffered STDIO is used here, so that all the statistics
2290  * will be written with 1 sys-write call.  This is nice when more
2291  * than one copy of the program is running on a terminal;  it prevents
2292  * the statistics output from becoming intermingled.
2293  */
2294 static void
2295 finish()
2296 {
2297 	Printf("\n----%s PING Statistics----\n", targethost);
2298 	Printf("%d packets transmitted, ", ntransmitted);
2299 	Printf("%d packets received, ", nreceived);
2300 	if (ntransmitted) {
2301 		if (nreceived <= ntransmitted) {
2302 			Printf("%d%% packet loss",
2303 			    (int)(((ntransmitted-nreceived)*100) /
2304 			    ntransmitted));
2305 		} else {
2306 			Printf("%.2f times amplification",
2307 			    (double)nreceived / (double)ntransmitted);
2308 		}
2309 	}
2310 	(void) putchar('\n');
2311 
2312 	/* if packet is big enough to store timeval AND ... */
2313 	if ((datalen >= sizeof (struct timeval)) && (nreceived > 0)) {
2314 		double mean = (double)tsum / nreceived;
2315 		double smean = (double)tsum2 / nreceived;
2316 		double sd =
2317 		    sqrt(((smean - mean*mean) * nreceived) / (nreceived-1));
2318 
2319 		Printf("round-trip (ms)  min/avg/max/stddev = "
2320 		    TIMEFORMAT "/" TIMEFORMAT "/"
2321 		    TIMEFORMAT "/" TIMEFORMAT "\n",
2322 		    (double)tmin / 1000, mean / 1000,
2323 		    (double)tmax / 1000, sd / 1000);
2324 	}
2325 	(void) fflush(stdout);
2326 
2327 	exit(is_alive ? EXIT_SUCCESS : EXIT_FAILURE);
2328 }
2329 
2330 /*
2331  * print the usage line
2332  */
2333 static void
2334 usage(char *cmdname)
2335 {
2336 	Fprintf(stderr, "usage: %s host [timeout]\n", cmdname);
2337 	Fprintf(stderr,
2338 /* CSTYLED */
2339 "usage: %s -s [-l | U] [abdLnRrv] [-A addr_family] [-c traffic_class]\n\t"
2340 "[-g gateway [-g gateway ...]] [-N nexthop] [-F flow_label] [-I interval]\n\t"
2341 "[-i interface] [-P tos] [-p port] [-t ttl] host [data_size] [npackets]\n",
2342 	    cmdname);
2343 }
2344 
2345 /*
2346  * Parse integer argument; exit with an error if it's not a number.
2347  * Now it also accepts hex. values.
2348  */
2349 static int
2350 int_arg(char *s, char *what)
2351 {
2352 	char *cp;
2353 	char *ep;
2354 	int num;
2355 
2356 	errno = 0;
2357 	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
2358 		cp = s + 2;
2359 		num = (int)strtol(cp, &ep, 16);
2360 	} else {
2361 		num = (int)strtol(s, &ep, 10);
2362 	}
2363 
2364 	if (errno || *ep != '\0' || num < 0) {
2365 		(void) Fprintf(stderr, "%s: bad %s: %s\n",
2366 		    progname, what, s);
2367 		exit(EXIT_FAILURE);
2368 	}
2369 
2370 	return (num);
2371 }
2372