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