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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 * 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