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