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