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