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