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