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