1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <stdio.h> 38*7c478bd9Sstevel@tonic-gate #include <string.h> 39*7c478bd9Sstevel@tonic-gate #include <strings.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 42*7c478bd9Sstevel@tonic-gate #include <unistd.h> 43*7c478bd9Sstevel@tonic-gate #include <signal.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 51*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 52*7c478bd9Sstevel@tonic-gate #include <net/if.h> 53*7c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h> 54*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 55*7c478bd9Sstevel@tonic-gate #include <netinet/ip.h> 56*7c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h> 57*7c478bd9Sstevel@tonic-gate #include <netinet/udp.h> 58*7c478bd9Sstevel@tonic-gate #include <netdb.h> 59*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include <ifaddrlist.h> 62*7c478bd9Sstevel@tonic-gate #include "ping.h" 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * IPv4 source routing option. 67*7c478bd9Sstevel@tonic-gate * In order to avoid padding for the alignment of IPv4 addresses, ipsr_addrs 68*7c478bd9Sstevel@tonic-gate * is defined as a 2-D array of uint8_t, instead of 1-D array of struct in_addr. 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate struct ip_sourceroute { 71*7c478bd9Sstevel@tonic-gate uint8_t ipsr_code; 72*7c478bd9Sstevel@tonic-gate uint8_t ipsr_len; 73*7c478bd9Sstevel@tonic-gate uint8_t ipsr_ptr; 74*7c478bd9Sstevel@tonic-gate /* up to 9 IPv4 addresses */ 75*7c478bd9Sstevel@tonic-gate uint8_t ipsr_addrs[1][sizeof (struct in_addr)]; 76*7c478bd9Sstevel@tonic-gate }; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate void check_reply(struct addrinfo *, struct msghdr *, int, ushort_t); 79*7c478bd9Sstevel@tonic-gate extern void find_dstaddr(ushort_t, union any_in_addr *); 80*7c478bd9Sstevel@tonic-gate extern boolean_t is_a_target(struct addrinfo *, union any_in_addr *); 81*7c478bd9Sstevel@tonic-gate extern char *pr_name(char *, int); 82*7c478bd9Sstevel@tonic-gate static void pr_options(uchar_t *, int); 83*7c478bd9Sstevel@tonic-gate extern char *pr_protocol(int); 84*7c478bd9Sstevel@tonic-gate static void pr_rropt(uchar_t *, int, boolean_t); 85*7c478bd9Sstevel@tonic-gate static void pr_tsopt(uchar_t *, int); 86*7c478bd9Sstevel@tonic-gate static char *pr_type(int); 87*7c478bd9Sstevel@tonic-gate extern void schedule_sigalrm(); 88*7c478bd9Sstevel@tonic-gate extern void send_scheduled_probe(); 89*7c478bd9Sstevel@tonic-gate extern boolean_t seq_match(ushort_t, int, ushort_t); 90*7c478bd9Sstevel@tonic-gate extern void sigalrm_handler(); 91*7c478bd9Sstevel@tonic-gate void set_IPv4_options(int, union any_in_addr *, int, struct in_addr *, 92*7c478bd9Sstevel@tonic-gate struct in_addr *); 93*7c478bd9Sstevel@tonic-gate extern void tvsub(struct timeval *, struct timeval *); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * Set IPv4 options 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate void 99*7c478bd9Sstevel@tonic-gate set_IPv4_options(int sock, union any_in_addr *gw_IP_list, int gw_count, 100*7c478bd9Sstevel@tonic-gate struct in_addr *src, struct in_addr *dst) 101*7c478bd9Sstevel@tonic-gate { 102*7c478bd9Sstevel@tonic-gate int req_size; 103*7c478bd9Sstevel@tonic-gate char srr[ROUTE_SIZE + 1]; 104*7c478bd9Sstevel@tonic-gate char *bufp; 105*7c478bd9Sstevel@tonic-gate int optsize = ROUTE_SIZE; 106*7c478bd9Sstevel@tonic-gate struct ip_sourceroute *srp; 107*7c478bd9Sstevel@tonic-gate struct ip_timestamp *tsp; 108*7c478bd9Sstevel@tonic-gate int i; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate if (rr_option || ts_option || gw_count > 0) { 111*7c478bd9Sstevel@tonic-gate bzero(srr, sizeof (srr)); 112*7c478bd9Sstevel@tonic-gate bufp = srr; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate if (gw_count > 0) { 115*7c478bd9Sstevel@tonic-gate /* 3 = 1 (code) + 1 (len) + 1 (ptr) of src route opt. */ 116*7c478bd9Sstevel@tonic-gate req_size = 3 + (sizeof (struct in_addr)) * gw_count; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (optsize < req_size) { 119*7c478bd9Sstevel@tonic-gate Fprintf(stderr, "%s: too many IPv4 gateways\n", 120*7c478bd9Sstevel@tonic-gate progname); 121*7c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate srp = (struct ip_sourceroute *)bufp; 125*7c478bd9Sstevel@tonic-gate srp->ipsr_code = strict ? IPOPT_SSRR : IPOPT_LSRR; 126*7c478bd9Sstevel@tonic-gate srp->ipsr_len = req_size; 127*7c478bd9Sstevel@tonic-gate srp->ipsr_ptr = IPOPT_MINOFF; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate for (i = 0; i < gw_count; i++) { 130*7c478bd9Sstevel@tonic-gate bcopy((char *)&gw_IP_list[i].addr, 131*7c478bd9Sstevel@tonic-gate &srp->ipsr_addrs[i], 132*7c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate optsize -= srp->ipsr_len; 135*7c478bd9Sstevel@tonic-gate bufp += srp->ipsr_len; 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate /* do we send a timestamp option? */ 138*7c478bd9Sstevel@tonic-gate if (ts_option) { 139*7c478bd9Sstevel@tonic-gate if (optsize < IPOPT_MINOFF) { 140*7c478bd9Sstevel@tonic-gate Fprintf(stderr, 141*7c478bd9Sstevel@tonic-gate "%s: no room for timestamp option\n", 142*7c478bd9Sstevel@tonic-gate progname); 143*7c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate /* LINTED */ 146*7c478bd9Sstevel@tonic-gate tsp = (struct ip_timestamp *)bufp; 147*7c478bd9Sstevel@tonic-gate tsp->ipt_code = IPOPT_TS; 148*7c478bd9Sstevel@tonic-gate tsp->ipt_len = optsize; 149*7c478bd9Sstevel@tonic-gate tsp->ipt_ptr = IPOPT_MINOFF + 1; 150*7c478bd9Sstevel@tonic-gate tsp->ipt_flg = ts_flag & 0x0f; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate if (tsp->ipt_flg > IPOPT_TS_TSANDADDR) { 153*7c478bd9Sstevel@tonic-gate req_size = IPOPT_MINOFF + 154*7c478bd9Sstevel@tonic-gate 2 * sizeof (struct ipt_ta); 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * Note: BSD/4.X is broken in their check so we 157*7c478bd9Sstevel@tonic-gate * have to bump up this number by at least one. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate req_size++; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (optsize < req_size) { 162*7c478bd9Sstevel@tonic-gate Fprintf(stderr, "%s: no room for " 163*7c478bd9Sstevel@tonic-gate "timestamp option\n", progname); 164*7c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate bcopy((char *)dst, 168*7c478bd9Sstevel@tonic-gate &tsp->ipt_timestamp.ipt_ta[0].ipt_addr, 169*7c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate bcopy((char *)src, 172*7c478bd9Sstevel@tonic-gate &tsp->ipt_timestamp.ipt_ta[1].ipt_addr, 173*7c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 174*7c478bd9Sstevel@tonic-gate tsp->ipt_len = req_size; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate optsize -= tsp->ipt_len; 178*7c478bd9Sstevel@tonic-gate bufp += tsp->ipt_len; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate /* do we send a record route option? */ 181*7c478bd9Sstevel@tonic-gate if (rr_option) { 182*7c478bd9Sstevel@tonic-gate if (optsize < IPOPT_MINOFF) { 183*7c478bd9Sstevel@tonic-gate Fprintf(stderr, 184*7c478bd9Sstevel@tonic-gate "%s: no room for record route option\n", 185*7c478bd9Sstevel@tonic-gate progname); 186*7c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * Format of record route option is same as source 191*7c478bd9Sstevel@tonic-gate * route option. 192*7c478bd9Sstevel@tonic-gate */ 193*7c478bd9Sstevel@tonic-gate srp = (struct ip_sourceroute *)bufp; 194*7c478bd9Sstevel@tonic-gate srp->ipsr_code = IPOPT_RR; 195*7c478bd9Sstevel@tonic-gate srp->ipsr_len = optsize; 196*7c478bd9Sstevel@tonic-gate srp->ipsr_ptr = IPOPT_MINOFF; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate optsize -= srp->ipsr_len; 199*7c478bd9Sstevel@tonic-gate bufp += srp->ipsr_len; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate optsize = bufp - srr; 202*7c478bd9Sstevel@tonic-gate /* Round up to 4 byte boundary */ 203*7c478bd9Sstevel@tonic-gate if (optsize & 0x3) 204*7c478bd9Sstevel@tonic-gate optsize = (optsize & ~0x3) + 4; 205*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IP, IP_OPTIONS, srr, optsize) < 206*7c478bd9Sstevel@tonic-gate 0) { 207*7c478bd9Sstevel@tonic-gate Fprintf(stderr, "%s: setsockopt IP_OPTIONS %s\n", 208*7c478bd9Sstevel@tonic-gate progname, strerror(errno)); 209*7c478bd9Sstevel@tonic-gate exit(EXIT_FAILURE); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Check out the packet to see if it came from us. This logic is necessary 216*7c478bd9Sstevel@tonic-gate * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 217*7c478bd9Sstevel@tonic-gate * which arrive ('tis only fair). This permits multiple copies of this 218*7c478bd9Sstevel@tonic-gate * program to be run without having intermingled output (or statistics!). 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate void 221*7c478bd9Sstevel@tonic-gate check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc, 222*7c478bd9Sstevel@tonic-gate ushort_t udp_src_port) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate struct ip *ip; 225*7c478bd9Sstevel@tonic-gate struct icmp *icp; 226*7c478bd9Sstevel@tonic-gate struct udphdr *up; 227*7c478bd9Sstevel@tonic-gate union any_in_addr dst_addr; 228*7c478bd9Sstevel@tonic-gate uchar_t *buf; 229*7c478bd9Sstevel@tonic-gate int32_t *intp; 230*7c478bd9Sstevel@tonic-gate struct sockaddr_in *from; 231*7c478bd9Sstevel@tonic-gate struct timeval *tp; 232*7c478bd9Sstevel@tonic-gate struct timeval tv; 233*7c478bd9Sstevel@tonic-gate int hlen, hlen1; 234*7c478bd9Sstevel@tonic-gate int64_t triptime; 235*7c478bd9Sstevel@tonic-gate boolean_t valid_reply = _B_FALSE; 236*7c478bd9Sstevel@tonic-gate boolean_t reply_matched_current_target; /* Is the source address of */ 237*7c478bd9Sstevel@tonic-gate /* this reply same as where */ 238*7c478bd9Sstevel@tonic-gate /* we're sending currently? */ 239*7c478bd9Sstevel@tonic-gate boolean_t last_reply_from_targetaddr = _B_FALSE; /* Is this stats, */ 240*7c478bd9Sstevel@tonic-gate /* probe all with npackets>0 */ 241*7c478bd9Sstevel@tonic-gate /* and we received reply for */ 242*7c478bd9Sstevel@tonic-gate /* the last probe sent to */ 243*7c478bd9Sstevel@tonic-gate /* targetaddr */ 244*7c478bd9Sstevel@tonic-gate int cc_left; 245*7c478bd9Sstevel@tonic-gate char tmp_buf[INET6_ADDRSTRLEN]; 246*7c478bd9Sstevel@tonic-gate static char *unreach[] = { 247*7c478bd9Sstevel@tonic-gate "Net Unreachable", 248*7c478bd9Sstevel@tonic-gate "Host Unreachable", 249*7c478bd9Sstevel@tonic-gate "Protocol Unreachable", 250*7c478bd9Sstevel@tonic-gate "Port Unreachable", 251*7c478bd9Sstevel@tonic-gate "Fragmentation needed and DF set", 252*7c478bd9Sstevel@tonic-gate "Source Route Failed", 253*7c478bd9Sstevel@tonic-gate /* The following are from RFC1700 */ 254*7c478bd9Sstevel@tonic-gate "Net Unknown", 255*7c478bd9Sstevel@tonic-gate "Host Unknown", 256*7c478bd9Sstevel@tonic-gate "Source Host Isolated", 257*7c478bd9Sstevel@tonic-gate "Dest Net Prohibited", 258*7c478bd9Sstevel@tonic-gate "Dest Host Prohibited", 259*7c478bd9Sstevel@tonic-gate "Net Unreachable for TOS", 260*7c478bd9Sstevel@tonic-gate "Host Unreachable for TOS", 261*7c478bd9Sstevel@tonic-gate "Communication Administratively Prohibited", 262*7c478bd9Sstevel@tonic-gate "Host Precedence Violation", 263*7c478bd9Sstevel@tonic-gate "Precedence Cutoff in Effect" 264*7c478bd9Sstevel@tonic-gate }; 265*7c478bd9Sstevel@tonic-gate static char *redirect[] = { 266*7c478bd9Sstevel@tonic-gate "Net", 267*7c478bd9Sstevel@tonic-gate "Host", 268*7c478bd9Sstevel@tonic-gate "TOS Net", 269*7c478bd9Sstevel@tonic-gate "TOS Host" 270*7c478bd9Sstevel@tonic-gate }; 271*7c478bd9Sstevel@tonic-gate static char *timexceed[] = { 272*7c478bd9Sstevel@tonic-gate "Time exceeded in transit", 273*7c478bd9Sstevel@tonic-gate "Time exceeded during reassembly" 274*7c478bd9Sstevel@tonic-gate }; 275*7c478bd9Sstevel@tonic-gate boolean_t print_newline = _B_FALSE; 276*7c478bd9Sstevel@tonic-gate int i; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* decompose msghdr into useful pieces */ 279*7c478bd9Sstevel@tonic-gate buf = (uchar_t *)msg->msg_iov->iov_base; 280*7c478bd9Sstevel@tonic-gate from = (struct sockaddr_in *)msg->msg_name; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate /* LINTED */ 283*7c478bd9Sstevel@tonic-gate intp = (int32_t *)buf; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)NULL); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* LINTED */ 288*7c478bd9Sstevel@tonic-gate ip = (struct ip *)buf; 289*7c478bd9Sstevel@tonic-gate hlen = ip->ip_hl << 2; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate if ((cc < sizeof (struct ip)) || (cc < hlen + ICMP_MINLEN)) { 292*7c478bd9Sstevel@tonic-gate if (verbose) { 293*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", cc, 294*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate return; 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate cc -= hlen; 300*7c478bd9Sstevel@tonic-gate /* LINTED */ 301*7c478bd9Sstevel@tonic-gate icp = (struct icmp *)(buf + hlen); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (ip->ip_p == 0) { 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Assume that we are running on a pre-4.3BSD system 306*7c478bd9Sstevel@tonic-gate * such as SunOS before 4.0 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate /* LINTED */ 309*7c478bd9Sstevel@tonic-gate icp = (struct icmp *)buf; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate cc_left = cc - ICMP_MINLEN; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate switch (icp->icmp_type) { 314*7c478bd9Sstevel@tonic-gate case ICMP_UNREACH: 315*7c478bd9Sstevel@tonic-gate ip = &icp->icmp_ip; 316*7c478bd9Sstevel@tonic-gate hlen1 = ip->ip_hl << 2; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* check if we have enough of the packet to work on */ 319*7c478bd9Sstevel@tonic-gate if ((cc_left < sizeof (struct ip)) || 320*7c478bd9Sstevel@tonic-gate (cc_left < hlen1 + sizeof (struct udphdr))) { 321*7c478bd9Sstevel@tonic-gate if (verbose) { 322*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 323*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 324*7c478bd9Sstevel@tonic-gate AF_INET)); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate return; 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* get the UDP packet */ 330*7c478bd9Sstevel@tonic-gate cc_left -= hlen1 + sizeof (struct udphdr); 331*7c478bd9Sstevel@tonic-gate /* LINTED */ 332*7c478bd9Sstevel@tonic-gate up = (struct udphdr *)((uchar_t *)ip + hlen1); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* check to see if this is what we sent */ 335*7c478bd9Sstevel@tonic-gate if (icp->icmp_code == ICMP_UNREACH_PORT && 336*7c478bd9Sstevel@tonic-gate ip->ip_p == IPPROTO_UDP && 337*7c478bd9Sstevel@tonic-gate udp_src_port == up->uh_sport && 338*7c478bd9Sstevel@tonic-gate use_udp) { 339*7c478bd9Sstevel@tonic-gate valid_reply = _B_TRUE; 340*7c478bd9Sstevel@tonic-gate } else { 341*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate if (valid_reply) { 345*7c478bd9Sstevel@tonic-gate /* 346*7c478bd9Sstevel@tonic-gate * For this valid reply, if we are still sending to 347*7c478bd9Sstevel@tonic-gate * this target IP address, we'd like to do some 348*7c478bd9Sstevel@tonic-gate * updates to targetaddr, so hold SIGALRMs. 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate (void) sighold(SIGALRM); 351*7c478bd9Sstevel@tonic-gate is_alive = _B_TRUE; 352*7c478bd9Sstevel@tonic-gate nreceived++; 353*7c478bd9Sstevel@tonic-gate reply_matched_current_target = 354*7c478bd9Sstevel@tonic-gate seq_match(current_targetaddr->starting_seq_num, 355*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent, 356*7c478bd9Sstevel@tonic-gate ntohs(up->uh_dport)); 357*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 358*7c478bd9Sstevel@tonic-gate current_targetaddr->got_reply = _B_TRUE; 359*7c478bd9Sstevel@tonic-gate nreceived_last_target++; 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Determine if stats, probe-all, and 362*7c478bd9Sstevel@tonic-gate * npackets != 0, and this is the reply for 363*7c478bd9Sstevel@tonic-gate * the last probe we sent to current target 364*7c478bd9Sstevel@tonic-gate * address. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate if (stats && probe_all && npackets > 0 && 367*7c478bd9Sstevel@tonic-gate ((current_targetaddr->starting_seq_num + 368*7c478bd9Sstevel@tonic-gate current_targetaddr->num_probes - 1) % 369*7c478bd9Sstevel@tonic-gate (MAX_PORT + 1) == ntohs(up->uh_dport)) && 370*7c478bd9Sstevel@tonic-gate (current_targetaddr->num_probes == 371*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent)) 372*7c478bd9Sstevel@tonic-gate last_reply_from_targetaddr = _B_TRUE; 373*7c478bd9Sstevel@tonic-gate } else { 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * If it's just probe_all and we just received 376*7c478bd9Sstevel@tonic-gate * a reply from a target address we were 377*7c478bd9Sstevel@tonic-gate * probing and had timed out (now we are probing 378*7c478bd9Sstevel@tonic-gate * some other target address), we ignore 379*7c478bd9Sstevel@tonic-gate * this reply. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate if (probe_all && !stats) { 382*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * Only if it's verbose, we get a 385*7c478bd9Sstevel@tonic-gate * message regarding this reply, 386*7c478bd9Sstevel@tonic-gate * otherwise we are done here. 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate if (!verbose) { 389*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 390*7c478bd9Sstevel@tonic-gate return; 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* stats mode doesn't print 'alive' messages */ 397*7c478bd9Sstevel@tonic-gate if (valid_reply && !stats) { 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * if we are still sending to the same target address, 400*7c478bd9Sstevel@tonic-gate * then stop it, because we know it's alive. 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 403*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 404*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, SIG_IGN); 405*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate if (!probe_all) { 410*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", targethost); 411*7c478bd9Sstevel@tonic-gate } else { 412*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, (void *)&ip->ip_dst, 413*7c478bd9Sstevel@tonic-gate tmp_buf, sizeof (tmp_buf)); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (nflag) { 416*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", tmp_buf); 417*7c478bd9Sstevel@tonic-gate } else { 418*7c478bd9Sstevel@tonic-gate Printf("%s (%s) is alive\n", 419*7c478bd9Sstevel@tonic-gate targethost, tmp_buf); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * Let's get things going again, but now 425*7c478bd9Sstevel@tonic-gate * ping will start sending to next target IP 426*7c478bd9Sstevel@tonic-gate * address. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 429*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, sigalrm_handler); 430*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate return; 433*7c478bd9Sstevel@tonic-gate } else { 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * If we are not moving to next targetaddr, let's 436*7c478bd9Sstevel@tonic-gate * release the SIGALRM now. We don't want to stall in 437*7c478bd9Sstevel@tonic-gate * the middle of probing a targetaddr if the pr_name() 438*7c478bd9Sstevel@tonic-gate * call (see below) takes longer. 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate if (!last_reply_from_targetaddr) 441*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 442*7c478bd9Sstevel@tonic-gate /* else, we'll release it later */ 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate dst_addr.addr = ip->ip_dst; 446*7c478bd9Sstevel@tonic-gate if (valid_reply) { 447*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s: ", cc, 448*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 449*7c478bd9Sstevel@tonic-gate Printf("udp_port=%d. ", ntohs(up->uh_dport)); 450*7c478bd9Sstevel@tonic-gate print_newline = _B_TRUE; 451*7c478bd9Sstevel@tonic-gate } else if (is_a_target(ai_dst, &dst_addr) || verbose) { 452*7c478bd9Sstevel@tonic-gate if (icp->icmp_code >= A_CNT(unreach)) { 453*7c478bd9Sstevel@tonic-gate Printf("ICMP %d Unreachable from gateway %s\n", 454*7c478bd9Sstevel@tonic-gate icp->icmp_code, 455*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 456*7c478bd9Sstevel@tonic-gate } else { 457*7c478bd9Sstevel@tonic-gate Printf("ICMP %s from gateway %s\n", 458*7c478bd9Sstevel@tonic-gate unreach[icp->icmp_code], 459*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate Printf(" for %s from %s", pr_protocol(ip->ip_p), 462*7c478bd9Sstevel@tonic-gate pr_name((char *)&ip->ip_src, AF_INET)); 463*7c478bd9Sstevel@tonic-gate Printf(" to %s", pr_name((char *)&ip->ip_dst, AF_INET)); 464*7c478bd9Sstevel@tonic-gate if (ip->ip_p == IPPROTO_TCP || 465*7c478bd9Sstevel@tonic-gate ip->ip_p == IPPROTO_UDP) { 466*7c478bd9Sstevel@tonic-gate Printf(" port %d ", ntohs(up->uh_dport)); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate print_newline = _B_TRUE; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* if we are timing and the reply has a timeval */ 472*7c478bd9Sstevel@tonic-gate if (valid_reply && datalen >= sizeof (struct timeval) && 473*7c478bd9Sstevel@tonic-gate cc_left >= sizeof (struct timeval)) { 474*7c478bd9Sstevel@tonic-gate /* LINTED */ 475*7c478bd9Sstevel@tonic-gate tp = (struct timeval *)((char *)up + 476*7c478bd9Sstevel@tonic-gate sizeof (struct udphdr)); 477*7c478bd9Sstevel@tonic-gate (void) tvsub(&tv, tp); 478*7c478bd9Sstevel@tonic-gate triptime = (int64_t)tv.tv_sec * MICROSEC + tv.tv_usec; 479*7c478bd9Sstevel@tonic-gate Printf("time=" TIMEFORMAT " ms", triptime/1000.0); 480*7c478bd9Sstevel@tonic-gate tsum += triptime; 481*7c478bd9Sstevel@tonic-gate tsum2 += triptime*triptime; 482*7c478bd9Sstevel@tonic-gate if (triptime < tmin) 483*7c478bd9Sstevel@tonic-gate tmin = triptime; 484*7c478bd9Sstevel@tonic-gate if (triptime > tmax) 485*7c478bd9Sstevel@tonic-gate tmax = triptime; 486*7c478bd9Sstevel@tonic-gate print_newline = _B_TRUE; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate if (print_newline) 489*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 490*7c478bd9Sstevel@tonic-gate /* 491*7c478bd9Sstevel@tonic-gate * If it's stats, probe-all, npackets > 0, and we received reply 492*7c478bd9Sstevel@tonic-gate * for the last probe sent to this target address, then we 493*7c478bd9Sstevel@tonic-gate * don't need to wait anymore, let's move on to next target 494*7c478bd9Sstevel@tonic-gate * address, now! 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate if (last_reply_from_targetaddr) { 497*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 498*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 499*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 500*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 501*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate break; 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate case ICMP_REDIRECT: 506*7c478bd9Sstevel@tonic-gate if (cc_left < sizeof (struct ip)) { 507*7c478bd9Sstevel@tonic-gate if (verbose) { 508*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 509*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 510*7c478bd9Sstevel@tonic-gate AF_INET)); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate return; 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate ip = &icp->icmp_ip; 516*7c478bd9Sstevel@tonic-gate dst_addr.addr = ip->ip_dst; 517*7c478bd9Sstevel@tonic-gate if (is_a_target(ai_dst, &dst_addr) || verbose) { 518*7c478bd9Sstevel@tonic-gate if (icp->icmp_code >= A_CNT(redirect)) { 519*7c478bd9Sstevel@tonic-gate Printf("ICMP %d redirect from gateway %s\n", 520*7c478bd9Sstevel@tonic-gate icp->icmp_code, 521*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 522*7c478bd9Sstevel@tonic-gate } else { 523*7c478bd9Sstevel@tonic-gate Printf("ICMP %s redirect from gateway %s\n", 524*7c478bd9Sstevel@tonic-gate redirect[icp->icmp_code], 525*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate Printf(" to %s", 528*7c478bd9Sstevel@tonic-gate pr_name((char *)&icp->icmp_gwaddr, AF_INET)); 529*7c478bd9Sstevel@tonic-gate Printf(" for %s\n", 530*7c478bd9Sstevel@tonic-gate pr_name((char *)&ip->ip_dst, AF_INET)); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate break; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate case ICMP_ECHOREPLY: 535*7c478bd9Sstevel@tonic-gate if (ntohs(icp->icmp_id) == ident) { 536*7c478bd9Sstevel@tonic-gate if (!use_udp && !use_icmp_ts) 537*7c478bd9Sstevel@tonic-gate valid_reply = _B_TRUE; 538*7c478bd9Sstevel@tonic-gate else 539*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 540*7c478bd9Sstevel@tonic-gate } else { 541*7c478bd9Sstevel@tonic-gate return; 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate if (valid_reply) { 545*7c478bd9Sstevel@tonic-gate /* 546*7c478bd9Sstevel@tonic-gate * For this valid reply, if we are still sending to 547*7c478bd9Sstevel@tonic-gate * this target IP address, we'd like to do some 548*7c478bd9Sstevel@tonic-gate * updates to targetaddr, so hold SIGALRMs. 549*7c478bd9Sstevel@tonic-gate */ 550*7c478bd9Sstevel@tonic-gate (void) sighold(SIGALRM); 551*7c478bd9Sstevel@tonic-gate is_alive = _B_TRUE; 552*7c478bd9Sstevel@tonic-gate nreceived++; 553*7c478bd9Sstevel@tonic-gate reply_matched_current_target = 554*7c478bd9Sstevel@tonic-gate seq_match(current_targetaddr->starting_seq_num, 555*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent, 556*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq)); 557*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 558*7c478bd9Sstevel@tonic-gate current_targetaddr->got_reply = _B_TRUE; 559*7c478bd9Sstevel@tonic-gate nreceived_last_target++; 560*7c478bd9Sstevel@tonic-gate /* 561*7c478bd9Sstevel@tonic-gate * Determine if stats, probe-all, and 562*7c478bd9Sstevel@tonic-gate * npackets != 0, and this is the reply for 563*7c478bd9Sstevel@tonic-gate * the last probe we sent to current target 564*7c478bd9Sstevel@tonic-gate * address. 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate if (stats && probe_all && npackets > 0 && 567*7c478bd9Sstevel@tonic-gate ((current_targetaddr->starting_seq_num + 568*7c478bd9Sstevel@tonic-gate current_targetaddr->num_probes - 1) % 569*7c478bd9Sstevel@tonic-gate (MAX_ICMP_SEQ + 1) == 570*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq)) && 571*7c478bd9Sstevel@tonic-gate (current_targetaddr->num_probes == 572*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent)) 573*7c478bd9Sstevel@tonic-gate last_reply_from_targetaddr = _B_TRUE; 574*7c478bd9Sstevel@tonic-gate } else { 575*7c478bd9Sstevel@tonic-gate /* 576*7c478bd9Sstevel@tonic-gate * If it's just probe_all and we just received 577*7c478bd9Sstevel@tonic-gate * a reply from a target address we were 578*7c478bd9Sstevel@tonic-gate * probing and had timed out (now we are probing 579*7c478bd9Sstevel@tonic-gate * some other target address), we ignore 580*7c478bd9Sstevel@tonic-gate * this reply. 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate if (probe_all && !stats) { 583*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate * Only if it's verbose, we get a 586*7c478bd9Sstevel@tonic-gate * message regarding this reply, 587*7c478bd9Sstevel@tonic-gate * otherwise we are done here. 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate if (!verbose) { 590*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 591*7c478bd9Sstevel@tonic-gate return; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate if (!stats && valid_reply) { 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * if we are still sending to the same target address, 600*7c478bd9Sstevel@tonic-gate * then stop it, because we know it's alive. 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 603*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 604*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, SIG_IGN); 605*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate if (!probe_all) { 610*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", targethost); 611*7c478bd9Sstevel@tonic-gate } else { 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * If we are using send_reply, the real 614*7c478bd9Sstevel@tonic-gate * target address is not the src address of the 615*7c478bd9Sstevel@tonic-gate * replies. Use icmp_seq to find out where this 616*7c478bd9Sstevel@tonic-gate * probe was sent to. 617*7c478bd9Sstevel@tonic-gate */ 618*7c478bd9Sstevel@tonic-gate if (send_reply) { 619*7c478bd9Sstevel@tonic-gate (void) find_dstaddr( 620*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq), &dst_addr); 621*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, 622*7c478bd9Sstevel@tonic-gate (void *)&dst_addr.addr, 623*7c478bd9Sstevel@tonic-gate tmp_buf, sizeof (tmp_buf)); 624*7c478bd9Sstevel@tonic-gate } else { 625*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, 626*7c478bd9Sstevel@tonic-gate (void *)&from->sin_addr, 627*7c478bd9Sstevel@tonic-gate tmp_buf, sizeof (tmp_buf)); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate if (nflag) { 630*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", tmp_buf); 631*7c478bd9Sstevel@tonic-gate } else { 632*7c478bd9Sstevel@tonic-gate Printf("%s (%s) is alive\n", 633*7c478bd9Sstevel@tonic-gate targethost, tmp_buf); 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 637*7c478bd9Sstevel@tonic-gate /* 638*7c478bd9Sstevel@tonic-gate * Let's get things going again, but now 639*7c478bd9Sstevel@tonic-gate * ping will start sending to next target IP 640*7c478bd9Sstevel@tonic-gate * address. 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 643*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, sigalrm_handler); 644*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate return; 647*7c478bd9Sstevel@tonic-gate } else { 648*7c478bd9Sstevel@tonic-gate /* 649*7c478bd9Sstevel@tonic-gate * If we are not moving to next targetaddr, let's 650*7c478bd9Sstevel@tonic-gate * release the SIGALRM now. We don't want to stall in 651*7c478bd9Sstevel@tonic-gate * the middle of probing a targetaddr if the pr_name() 652*7c478bd9Sstevel@tonic-gate * call (see below) takes longer. 653*7c478bd9Sstevel@tonic-gate */ 654*7c478bd9Sstevel@tonic-gate if (!last_reply_from_targetaddr) 655*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 656*7c478bd9Sstevel@tonic-gate /* else, we'll release it later */ 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * If we are using send_reply, the real target address is 660*7c478bd9Sstevel@tonic-gate * not the src address of the replies. Use icmp_seq to find out 661*7c478bd9Sstevel@tonic-gate * where this probe was sent to. 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate if (send_reply) { 664*7c478bd9Sstevel@tonic-gate (void) find_dstaddr(ntohs(icp->icmp_seq), &dst_addr); 665*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s: ", cc, 666*7c478bd9Sstevel@tonic-gate pr_name((char *)&dst_addr.addr, AF_INET)); 667*7c478bd9Sstevel@tonic-gate } else { 668*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s: ", cc, 669*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate Printf("icmp_seq=%d. ", ntohs(icp->icmp_seq)); 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate if (valid_reply && datalen >= sizeof (struct timeval) && 674*7c478bd9Sstevel@tonic-gate cc_left >= sizeof (struct timeval)) { 675*7c478bd9Sstevel@tonic-gate /* LINTED */ 676*7c478bd9Sstevel@tonic-gate tp = (struct timeval *)&icp->icmp_data[0]; 677*7c478bd9Sstevel@tonic-gate (void) tvsub(&tv, tp); 678*7c478bd9Sstevel@tonic-gate triptime = (int64_t)tv.tv_sec * MICROSEC + tv.tv_usec; 679*7c478bd9Sstevel@tonic-gate Printf("time=" TIMEFORMAT " ms", triptime/1000.0); 680*7c478bd9Sstevel@tonic-gate tsum += triptime; 681*7c478bd9Sstevel@tonic-gate tsum2 += triptime*triptime; 682*7c478bd9Sstevel@tonic-gate if (triptime < tmin) 683*7c478bd9Sstevel@tonic-gate tmin = triptime; 684*7c478bd9Sstevel@tonic-gate if (triptime > tmax) 685*7c478bd9Sstevel@tonic-gate tmax = triptime; 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * If it's stats, probe-all, npackets > 0, and we received reply 691*7c478bd9Sstevel@tonic-gate * for the last probe sent to this target address, then we 692*7c478bd9Sstevel@tonic-gate * don't need to wait anymore, let's move on to next target 693*7c478bd9Sstevel@tonic-gate * address, now! 694*7c478bd9Sstevel@tonic-gate */ 695*7c478bd9Sstevel@tonic-gate if (last_reply_from_targetaddr) { 696*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 697*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 698*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 699*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 700*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate break; 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate case ICMP_SOURCEQUENCH: 705*7c478bd9Sstevel@tonic-gate if (cc_left < sizeof (struct ip)) { 706*7c478bd9Sstevel@tonic-gate if (verbose) { 707*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 708*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 709*7c478bd9Sstevel@tonic-gate AF_INET)); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate return; 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate ip = &icp->icmp_ip; 714*7c478bd9Sstevel@tonic-gate hlen1 = ip->ip_hl << 2; 715*7c478bd9Sstevel@tonic-gate dst_addr.addr = ip->ip_dst; 716*7c478bd9Sstevel@tonic-gate if (is_a_target(ai_dst, &dst_addr) || verbose) { 717*7c478bd9Sstevel@tonic-gate Printf("ICMP Source Quench from %s\n", 718*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 719*7c478bd9Sstevel@tonic-gate Printf(" for %s from %s", pr_protocol(ip->ip_p), 720*7c478bd9Sstevel@tonic-gate pr_name((char *)&ip->ip_src, AF_INET)); 721*7c478bd9Sstevel@tonic-gate Printf(" to %s", pr_name((char *)&ip->ip_dst, AF_INET)); 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * if it's a UDP or TCP packet, we need at least first 725*7c478bd9Sstevel@tonic-gate * 4 bytes of it to see the src/dst ports 726*7c478bd9Sstevel@tonic-gate */ 727*7c478bd9Sstevel@tonic-gate if ((ip->ip_p == IPPROTO_TCP || 728*7c478bd9Sstevel@tonic-gate ip->ip_p == IPPROTO_UDP) && 729*7c478bd9Sstevel@tonic-gate (cc_left >= hlen1 + 4)) { 730*7c478bd9Sstevel@tonic-gate /* LINTED */ 731*7c478bd9Sstevel@tonic-gate up = (struct udphdr *)((uchar_t *)ip + hlen1); 732*7c478bd9Sstevel@tonic-gate Printf(" port %d", ntohs(up->uh_dport)); 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate break; 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate case ICMP_PARAMPROB: 739*7c478bd9Sstevel@tonic-gate if (cc_left < sizeof (struct ip)) { 740*7c478bd9Sstevel@tonic-gate if (verbose) { 741*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 742*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 743*7c478bd9Sstevel@tonic-gate AF_INET)); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate return; 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate ip = &icp->icmp_ip; 748*7c478bd9Sstevel@tonic-gate hlen1 = ip->ip_hl << 2; 749*7c478bd9Sstevel@tonic-gate dst_addr.addr = ip->ip_dst; 750*7c478bd9Sstevel@tonic-gate if (is_a_target(ai_dst, &dst_addr) || verbose) { 751*7c478bd9Sstevel@tonic-gate switch (icp->icmp_code) { 752*7c478bd9Sstevel@tonic-gate case ICMP_PARAMPROB_OPTABSENT: 753*7c478bd9Sstevel@tonic-gate Printf("ICMP Missing a Required Option " 754*7c478bd9Sstevel@tonic-gate "parameter problem from %s\n", 755*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 756*7c478bd9Sstevel@tonic-gate Printf(" option type = %d", icp->icmp_pptr); 757*7c478bd9Sstevel@tonic-gate break; 758*7c478bd9Sstevel@tonic-gate case ICMP_PARAMPROB_BADLENGTH: 759*7c478bd9Sstevel@tonic-gate Printf("ICMP Bad Length parameter problem " 760*7c478bd9Sstevel@tonic-gate "from %s\n", 761*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 762*7c478bd9Sstevel@tonic-gate Printf(" in byte %d", icp->icmp_pptr); 763*7c478bd9Sstevel@tonic-gate if (icp->icmp_pptr <= hlen1) { 764*7c478bd9Sstevel@tonic-gate Printf(" (value 0x%x)", 765*7c478bd9Sstevel@tonic-gate *((char *)ip + icp->icmp_pptr)); 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate break; 768*7c478bd9Sstevel@tonic-gate case 0: 769*7c478bd9Sstevel@tonic-gate default: 770*7c478bd9Sstevel@tonic-gate Printf("ICMP Parameter Problem from %s\n", 771*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 772*7c478bd9Sstevel@tonic-gate Printf(" in byte %d", icp->icmp_pptr); 773*7c478bd9Sstevel@tonic-gate if (icp->icmp_pptr <= hlen1) { 774*7c478bd9Sstevel@tonic-gate Printf(" (value 0x%x)", 775*7c478bd9Sstevel@tonic-gate *((char *)ip + icp->icmp_pptr)); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate break; 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate Printf(" for %s from %s", pr_protocol(ip->ip_p), 781*7c478bd9Sstevel@tonic-gate pr_name((char *)&ip->ip_src, AF_INET)); 782*7c478bd9Sstevel@tonic-gate Printf(" to %s", pr_name((char *)&ip->ip_dst, AF_INET)); 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * if it's a UDP or TCP packet, we need at least first 786*7c478bd9Sstevel@tonic-gate * 4 bytes of it to see the src/dst ports 787*7c478bd9Sstevel@tonic-gate */ 788*7c478bd9Sstevel@tonic-gate if ((ip->ip_p == IPPROTO_TCP || 789*7c478bd9Sstevel@tonic-gate ip->ip_p == IPPROTO_UDP) && 790*7c478bd9Sstevel@tonic-gate (cc_left >= hlen1 + 4)) { 791*7c478bd9Sstevel@tonic-gate /* LINTED */ 792*7c478bd9Sstevel@tonic-gate up = (struct udphdr *)((uchar_t *)ip + hlen1); 793*7c478bd9Sstevel@tonic-gate Printf(" port %d", ntohs(up->uh_dport)); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate break; 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate case ICMP_TIMXCEED: 800*7c478bd9Sstevel@tonic-gate if (cc_left < sizeof (struct ip)) { 801*7c478bd9Sstevel@tonic-gate if (verbose) { 802*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 803*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 804*7c478bd9Sstevel@tonic-gate AF_INET)); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate return; 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate ip = &icp->icmp_ip; 809*7c478bd9Sstevel@tonic-gate hlen1 = ip->ip_hl << 2; 810*7c478bd9Sstevel@tonic-gate dst_addr.addr = ip->ip_dst; 811*7c478bd9Sstevel@tonic-gate if (is_a_target(ai_dst, &dst_addr) || verbose) { 812*7c478bd9Sstevel@tonic-gate if (icp->icmp_code >= A_CNT(timexceed)) { 813*7c478bd9Sstevel@tonic-gate Printf("ICMP %d time exceeded from %s\n", 814*7c478bd9Sstevel@tonic-gate icp->icmp_code, 815*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 816*7c478bd9Sstevel@tonic-gate } else { 817*7c478bd9Sstevel@tonic-gate Printf("ICMP %s from %s\n", 818*7c478bd9Sstevel@tonic-gate timexceed[icp->icmp_code], 819*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate Printf(" for %s from %s", pr_protocol(ip->ip_p), 822*7c478bd9Sstevel@tonic-gate pr_name((char *)&ip->ip_src, AF_INET)); 823*7c478bd9Sstevel@tonic-gate Printf(" to %s", pr_name((char *)&ip->ip_dst, AF_INET)); 824*7c478bd9Sstevel@tonic-gate if ((ip->ip_p == IPPROTO_TCP || 825*7c478bd9Sstevel@tonic-gate ip->ip_p == IPPROTO_UDP) && 826*7c478bd9Sstevel@tonic-gate (cc_left >= hlen1 + 4)) { 827*7c478bd9Sstevel@tonic-gate /* LINTED */ 828*7c478bd9Sstevel@tonic-gate up = (struct udphdr *)((uchar_t *)ip + hlen1); 829*7c478bd9Sstevel@tonic-gate Printf(" port %d", ntohs(up->uh_dport)); 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate break; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate case ICMP_TSTAMPREPLY: 836*7c478bd9Sstevel@tonic-gate /* the packet should have enough space to store timestamps */ 837*7c478bd9Sstevel@tonic-gate if (cc_left < sizeof (struct id_ts)) { 838*7c478bd9Sstevel@tonic-gate if (verbose) { 839*7c478bd9Sstevel@tonic-gate Printf("packet too short (%d bytes) from %s\n", 840*7c478bd9Sstevel@tonic-gate cc, pr_name((char *)&from->sin_addr, 841*7c478bd9Sstevel@tonic-gate AF_INET)); 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate return; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate if (ntohs(icp->icmp_id) == ident) { 847*7c478bd9Sstevel@tonic-gate if (use_icmp_ts) 848*7c478bd9Sstevel@tonic-gate valid_reply = _B_TRUE; 849*7c478bd9Sstevel@tonic-gate else 850*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 851*7c478bd9Sstevel@tonic-gate } else { 852*7c478bd9Sstevel@tonic-gate return; 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate if (valid_reply) { 856*7c478bd9Sstevel@tonic-gate /* 857*7c478bd9Sstevel@tonic-gate * For this valid reply, if we are still sending to 858*7c478bd9Sstevel@tonic-gate * this target IP address, we'd like to do some 859*7c478bd9Sstevel@tonic-gate * updates to targetaddr, so hold SIGALRMs. 860*7c478bd9Sstevel@tonic-gate */ 861*7c478bd9Sstevel@tonic-gate (void) sighold(SIGALRM); 862*7c478bd9Sstevel@tonic-gate is_alive = _B_TRUE; 863*7c478bd9Sstevel@tonic-gate nreceived++; 864*7c478bd9Sstevel@tonic-gate reply_matched_current_target = 865*7c478bd9Sstevel@tonic-gate seq_match(current_targetaddr->starting_seq_num, 866*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent, 867*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq)); 868*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 869*7c478bd9Sstevel@tonic-gate current_targetaddr->got_reply = _B_TRUE; 870*7c478bd9Sstevel@tonic-gate nreceived_last_target++; 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * Determine if stats, probe-all, and 873*7c478bd9Sstevel@tonic-gate * npackets != 0, and this is the reply for 874*7c478bd9Sstevel@tonic-gate * the last probe we sent to current target 875*7c478bd9Sstevel@tonic-gate * address. 876*7c478bd9Sstevel@tonic-gate */ 877*7c478bd9Sstevel@tonic-gate if (stats && probe_all && npackets > 0 && 878*7c478bd9Sstevel@tonic-gate ((current_targetaddr->starting_seq_num + 879*7c478bd9Sstevel@tonic-gate current_targetaddr->num_probes - 1) % 880*7c478bd9Sstevel@tonic-gate (MAX_ICMP_SEQ + 1) == 881*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq)) && 882*7c478bd9Sstevel@tonic-gate (current_targetaddr->num_probes == 883*7c478bd9Sstevel@tonic-gate current_targetaddr->num_sent)) 884*7c478bd9Sstevel@tonic-gate last_reply_from_targetaddr = _B_TRUE; 885*7c478bd9Sstevel@tonic-gate } else { 886*7c478bd9Sstevel@tonic-gate /* 887*7c478bd9Sstevel@tonic-gate * If it's just probe_all and we just received 888*7c478bd9Sstevel@tonic-gate * a reply from a target address we were 889*7c478bd9Sstevel@tonic-gate * probing and had timed out (now we are probing 890*7c478bd9Sstevel@tonic-gate * some other target address), we ignore 891*7c478bd9Sstevel@tonic-gate * this reply. 892*7c478bd9Sstevel@tonic-gate */ 893*7c478bd9Sstevel@tonic-gate if (probe_all && !stats) { 894*7c478bd9Sstevel@tonic-gate valid_reply = _B_FALSE; 895*7c478bd9Sstevel@tonic-gate /* 896*7c478bd9Sstevel@tonic-gate * Only if it's verbose, we get a 897*7c478bd9Sstevel@tonic-gate * message regarding this reply, 898*7c478bd9Sstevel@tonic-gate * otherwise we are done here. 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate if (!verbose) { 901*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 902*7c478bd9Sstevel@tonic-gate return; 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate if (!stats && valid_reply) { 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * if we are still sending to the same target address, 911*7c478bd9Sstevel@tonic-gate * then stop it, because we know it's alive. 912*7c478bd9Sstevel@tonic-gate */ 913*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 914*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 915*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, SIG_IGN); 916*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate if (!probe_all) { 921*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", targethost); 922*7c478bd9Sstevel@tonic-gate } else { 923*7c478bd9Sstevel@tonic-gate /* 924*7c478bd9Sstevel@tonic-gate * If we are using send_reply, the real 925*7c478bd9Sstevel@tonic-gate * target address is not the src address of the 926*7c478bd9Sstevel@tonic-gate * replies. Use icmp_seq to find out where this 927*7c478bd9Sstevel@tonic-gate * probe was sent to. 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate if (send_reply) { 930*7c478bd9Sstevel@tonic-gate (void) find_dstaddr( 931*7c478bd9Sstevel@tonic-gate ntohs(icp->icmp_seq), &dst_addr); 932*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, 933*7c478bd9Sstevel@tonic-gate (void *)&dst_addr.addr, 934*7c478bd9Sstevel@tonic-gate tmp_buf, sizeof (tmp_buf)); 935*7c478bd9Sstevel@tonic-gate } else { 936*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, 937*7c478bd9Sstevel@tonic-gate (void *)&from->sin_addr, 938*7c478bd9Sstevel@tonic-gate tmp_buf, sizeof (tmp_buf)); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate if (nflag) { 941*7c478bd9Sstevel@tonic-gate Printf("%s is alive\n", tmp_buf); 942*7c478bd9Sstevel@tonic-gate } else { 943*7c478bd9Sstevel@tonic-gate Printf("%s (%s) is alive\n", 944*7c478bd9Sstevel@tonic-gate targethost, tmp_buf); 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate if (reply_matched_current_target) { 948*7c478bd9Sstevel@tonic-gate /* 949*7c478bd9Sstevel@tonic-gate * Let's get things going again, but now 950*7c478bd9Sstevel@tonic-gate * ping will start sending to next target IP 951*7c478bd9Sstevel@tonic-gate * address. 952*7c478bd9Sstevel@tonic-gate */ 953*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 954*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, sigalrm_handler); 955*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate return; 958*7c478bd9Sstevel@tonic-gate } else { 959*7c478bd9Sstevel@tonic-gate /* 960*7c478bd9Sstevel@tonic-gate * If we are not moving to next targetaddr, let's 961*7c478bd9Sstevel@tonic-gate * release the SIGALRM now. We don't want to stall in 962*7c478bd9Sstevel@tonic-gate * the middle of probing a targetaddr if the pr_name() 963*7c478bd9Sstevel@tonic-gate * call (see below) takes longer. 964*7c478bd9Sstevel@tonic-gate */ 965*7c478bd9Sstevel@tonic-gate if (!last_reply_from_targetaddr) 966*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 967*7c478bd9Sstevel@tonic-gate /* else, we'll release it later */ 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * If we are using send_reply, the real target address is 972*7c478bd9Sstevel@tonic-gate * not the src address of the replies. Use icmp_seq to find out 973*7c478bd9Sstevel@tonic-gate * where this probe was sent to. 974*7c478bd9Sstevel@tonic-gate */ 975*7c478bd9Sstevel@tonic-gate if (send_reply) { 976*7c478bd9Sstevel@tonic-gate (void) find_dstaddr(ntohs(icp->icmp_seq), &dst_addr); 977*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s: ", cc, 978*7c478bd9Sstevel@tonic-gate pr_name((char *)&dst_addr.addr, AF_INET)); 979*7c478bd9Sstevel@tonic-gate } else { 980*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s: ", cc, 981*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate Printf("icmp_seq=%d. ", ntohs(icp->icmp_seq)); 984*7c478bd9Sstevel@tonic-gate Printf("orig = %lu, recv = %lu, xmit = %lu ", 985*7c478bd9Sstevel@tonic-gate (ulong_t)ntohl(icp->icmp_otime), 986*7c478bd9Sstevel@tonic-gate (ulong_t)ntohl(icp->icmp_rtime), 987*7c478bd9Sstevel@tonic-gate (ulong_t)ntohl(icp->icmp_ttime)); 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate if (valid_reply) { 990*7c478bd9Sstevel@tonic-gate /* 991*7c478bd9Sstevel@tonic-gate * icp->icmp_otime is the time passed since midnight. 992*7c478bd9Sstevel@tonic-gate * Therefore we need to adjust tv value, which is 993*7c478bd9Sstevel@tonic-gate * the time passed since Jan 1, 1970. 994*7c478bd9Sstevel@tonic-gate */ 995*7c478bd9Sstevel@tonic-gate triptime = (tv.tv_sec % (24LL * 60 * 60)) * MILLISEC + 996*7c478bd9Sstevel@tonic-gate (tv.tv_usec / (MICROSEC/MILLISEC)); 997*7c478bd9Sstevel@tonic-gate triptime -= ntohl(icp->icmp_otime); 998*7c478bd9Sstevel@tonic-gate if (triptime < 0) 999*7c478bd9Sstevel@tonic-gate triptime += 24LL * 60 * 60 * MILLISEC; 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate Printf("time=%d. ms", (int)triptime); 1002*7c478bd9Sstevel@tonic-gate triptime *= (MICROSEC/MILLISEC); 1003*7c478bd9Sstevel@tonic-gate tsum += triptime; 1004*7c478bd9Sstevel@tonic-gate tsum2 += triptime*triptime; 1005*7c478bd9Sstevel@tonic-gate if (triptime < tmin) 1006*7c478bd9Sstevel@tonic-gate tmin = triptime; 1007*7c478bd9Sstevel@tonic-gate if (triptime > tmax) 1008*7c478bd9Sstevel@tonic-gate tmax = triptime; 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1011*7c478bd9Sstevel@tonic-gate /* 1012*7c478bd9Sstevel@tonic-gate * If it's stats, probe-all, npackets > 0, and we received reply 1013*7c478bd9Sstevel@tonic-gate * for the last probe sent to this target address, then we 1014*7c478bd9Sstevel@tonic-gate * don't need to wait anymore, let's move on to next target 1015*7c478bd9Sstevel@tonic-gate * address, now! 1016*7c478bd9Sstevel@tonic-gate */ 1017*7c478bd9Sstevel@tonic-gate if (last_reply_from_targetaddr) { 1018*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* cancel alarm */ 1019*7c478bd9Sstevel@tonic-gate current_targetaddr->probing_done = _B_TRUE; 1020*7c478bd9Sstevel@tonic-gate (void) sigrelse(SIGALRM); 1021*7c478bd9Sstevel@tonic-gate send_scheduled_probe(); 1022*7c478bd9Sstevel@tonic-gate schedule_sigalrm(); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate break; 1025*7c478bd9Sstevel@tonic-gate case ICMP_ROUTERADVERT: 1026*7c478bd9Sstevel@tonic-gate case ICMP_ROUTERSOLICIT: 1027*7c478bd9Sstevel@tonic-gate /* Router discovery messages */ 1028*7c478bd9Sstevel@tonic-gate return; 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate case ICMP_ECHO: 1031*7c478bd9Sstevel@tonic-gate case ICMP_TSTAMP: 1032*7c478bd9Sstevel@tonic-gate case ICMP_IREQ: 1033*7c478bd9Sstevel@tonic-gate case ICMP_MASKREQ: 1034*7c478bd9Sstevel@tonic-gate /* These were never passed out from the SunOS 4.X kernel. */ 1035*7c478bd9Sstevel@tonic-gate return; 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate case ICMP_IREQREPLY: 1038*7c478bd9Sstevel@tonic-gate case ICMP_MASKREPLY: 1039*7c478bd9Sstevel@tonic-gate /* Replies for information and address mask requests */ 1040*7c478bd9Sstevel@tonic-gate return; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate default: 1043*7c478bd9Sstevel@tonic-gate if (verbose) { 1044*7c478bd9Sstevel@tonic-gate Printf("%d bytes from %s:\n", cc, 1045*7c478bd9Sstevel@tonic-gate pr_name((char *)&from->sin_addr, AF_INET)); 1046*7c478bd9Sstevel@tonic-gate Printf("icmp_type=%d (%s) ", 1047*7c478bd9Sstevel@tonic-gate icp->icmp_type, pr_type(icp->icmp_type)); 1048*7c478bd9Sstevel@tonic-gate Printf("icmp_code=%d\n", icp->icmp_code); 1049*7c478bd9Sstevel@tonic-gate for (i = 0; i < 12; i++) { 1050*7c478bd9Sstevel@tonic-gate Printf("x%2.2x: x%8.8x\n", 1051*7c478bd9Sstevel@tonic-gate i * sizeof (int32_t), *intp++); 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate break; 1055*7c478bd9Sstevel@tonic-gate } 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate buf += sizeof (struct ip); 1058*7c478bd9Sstevel@tonic-gate hlen -= sizeof (struct ip); 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate /* if verbose and there exists IP options */ 1061*7c478bd9Sstevel@tonic-gate if (verbose && hlen > 0) 1062*7c478bd9Sstevel@tonic-gate pr_options((uchar_t *)buf, hlen); 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate /* 1066*7c478bd9Sstevel@tonic-gate * Print out the ip options. 1067*7c478bd9Sstevel@tonic-gate */ 1068*7c478bd9Sstevel@tonic-gate static void 1069*7c478bd9Sstevel@tonic-gate pr_options(uchar_t *opt, int optlength) 1070*7c478bd9Sstevel@tonic-gate { 1071*7c478bd9Sstevel@tonic-gate int curlength; 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate Printf(" IP options: "); 1074*7c478bd9Sstevel@tonic-gate while (optlength > 0) { 1075*7c478bd9Sstevel@tonic-gate curlength = opt[1]; 1076*7c478bd9Sstevel@tonic-gate switch (*opt) { 1077*7c478bd9Sstevel@tonic-gate case IPOPT_EOL: 1078*7c478bd9Sstevel@tonic-gate optlength = 0; 1079*7c478bd9Sstevel@tonic-gate break; 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate case IPOPT_NOP: 1082*7c478bd9Sstevel@tonic-gate opt++; 1083*7c478bd9Sstevel@tonic-gate optlength--; 1084*7c478bd9Sstevel@tonic-gate continue; 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate case IPOPT_RR: 1087*7c478bd9Sstevel@tonic-gate Printf(" <record route> "); 1088*7c478bd9Sstevel@tonic-gate pr_rropt(opt, curlength, _B_TRUE); 1089*7c478bd9Sstevel@tonic-gate break; 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate case IPOPT_TS: 1092*7c478bd9Sstevel@tonic-gate Printf(" <time stamp> "); 1093*7c478bd9Sstevel@tonic-gate pr_tsopt(opt, curlength); 1094*7c478bd9Sstevel@tonic-gate break; 1095*7c478bd9Sstevel@tonic-gate 1096*7c478bd9Sstevel@tonic-gate case IPOPT_SECURITY: 1097*7c478bd9Sstevel@tonic-gate Printf(" <security>"); 1098*7c478bd9Sstevel@tonic-gate break; 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate case IPOPT_LSRR: 1101*7c478bd9Sstevel@tonic-gate Printf(" <loose source route> "); 1102*7c478bd9Sstevel@tonic-gate pr_rropt(opt, curlength, _B_FALSE); 1103*7c478bd9Sstevel@tonic-gate break; 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate case IPOPT_SATID: 1106*7c478bd9Sstevel@tonic-gate Printf(" <stream id>"); 1107*7c478bd9Sstevel@tonic-gate break; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate case IPOPT_SSRR: 1110*7c478bd9Sstevel@tonic-gate Printf(" <strict source route> "); 1111*7c478bd9Sstevel@tonic-gate pr_rropt(opt, curlength, _B_FALSE); 1112*7c478bd9Sstevel@tonic-gate break; 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate default: 1115*7c478bd9Sstevel@tonic-gate Printf(" <option %d, len %d>", *opt, curlength); 1116*7c478bd9Sstevel@tonic-gate break; 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate /* 1119*7c478bd9Sstevel@tonic-gate * Following most options comes a length field 1120*7c478bd9Sstevel@tonic-gate */ 1121*7c478bd9Sstevel@tonic-gate opt += curlength; 1122*7c478bd9Sstevel@tonic-gate optlength -= curlength; 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 1125*7c478bd9Sstevel@tonic-gate } 1126*7c478bd9Sstevel@tonic-gate 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * Print out a recorded route option. If rrflag is _B_TRUE, it prints record 1129*7c478bd9Sstevel@tonic-gate * route option, otherwise LSRR/SSRR. 1130*7c478bd9Sstevel@tonic-gate */ 1131*7c478bd9Sstevel@tonic-gate static void 1132*7c478bd9Sstevel@tonic-gate pr_rropt(uchar_t *opt, int length, boolean_t rrflag) 1133*7c478bd9Sstevel@tonic-gate { 1134*7c478bd9Sstevel@tonic-gate struct ip_sourceroute *rrp; 1135*7c478bd9Sstevel@tonic-gate int sr_index = 0; 1136*7c478bd9Sstevel@tonic-gate struct in_addr addr; 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate rrp = (struct ip_sourceroute *)opt; 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate /* data starts at offset 3 */ 1141*7c478bd9Sstevel@tonic-gate length -= 3; 1142*7c478bd9Sstevel@tonic-gate while (length > 0) { 1143*7c478bd9Sstevel@tonic-gate /* 1144*7c478bd9Sstevel@tonic-gate * Let's see if we are examining the addr pointed by ipsr_ptr 1145*7c478bd9Sstevel@tonic-gate */ 1146*7c478bd9Sstevel@tonic-gate if ((rrp->ipsr_ptr == (sr_index + 1) * sizeof (addr)) && 1147*7c478bd9Sstevel@tonic-gate rrflag) { 1148*7c478bd9Sstevel@tonic-gate Printf(" (End of record)"); 1149*7c478bd9Sstevel@tonic-gate break; 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate bcopy(&rrp->ipsr_addrs[sr_index], &addr, sizeof (addr)); 1153*7c478bd9Sstevel@tonic-gate Printf("%s", pr_name((char *)&addr, AF_INET)); 1154*7c478bd9Sstevel@tonic-gate 1155*7c478bd9Sstevel@tonic-gate if (rrp->ipsr_ptr == (sr_index + 1) * sizeof (addr)) { 1156*7c478bd9Sstevel@tonic-gate Printf("(Current)"); 1157*7c478bd9Sstevel@tonic-gate } 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate sr_index++; 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate length -= sizeof (addr); 1162*7c478bd9Sstevel@tonic-gate if (length > 0) 1163*7c478bd9Sstevel@tonic-gate Printf(", "); 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate /* 1168*7c478bd9Sstevel@tonic-gate * Print out a timestamp option. 1169*7c478bd9Sstevel@tonic-gate */ 1170*7c478bd9Sstevel@tonic-gate static void 1171*7c478bd9Sstevel@tonic-gate pr_tsopt(uchar_t *opt, int length) 1172*7c478bd9Sstevel@tonic-gate { 1173*7c478bd9Sstevel@tonic-gate boolean_t address_present; 1174*7c478bd9Sstevel@tonic-gate boolean_t rrflag; /* End at current entry? */ 1175*7c478bd9Sstevel@tonic-gate struct ip_timestamp *tsp; 1176*7c478bd9Sstevel@tonic-gate int ts_index = 0; 1177*7c478bd9Sstevel@tonic-gate struct in_addr addr; 1178*7c478bd9Sstevel@tonic-gate size_t data_len; 1179*7c478bd9Sstevel@tonic-gate int32_t time; 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate /* LINTED */ 1182*7c478bd9Sstevel@tonic-gate tsp = (struct ip_timestamp *)opt; 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate switch (tsp->ipt_flg) { 1185*7c478bd9Sstevel@tonic-gate case IPOPT_TS_TSONLY: 1186*7c478bd9Sstevel@tonic-gate address_present = _B_FALSE; 1187*7c478bd9Sstevel@tonic-gate data_len = sizeof (tsp->ipt_timestamp.ipt_time[0]); 1188*7c478bd9Sstevel@tonic-gate rrflag = _B_TRUE; 1189*7c478bd9Sstevel@tonic-gate break; 1190*7c478bd9Sstevel@tonic-gate case IPOPT_TS_TSANDADDR: 1191*7c478bd9Sstevel@tonic-gate address_present = _B_TRUE; 1192*7c478bd9Sstevel@tonic-gate data_len = sizeof (tsp->ipt_timestamp.ipt_ta[0]); 1193*7c478bd9Sstevel@tonic-gate rrflag = _B_TRUE; 1194*7c478bd9Sstevel@tonic-gate break; 1195*7c478bd9Sstevel@tonic-gate case IPOPT_TS_PRESPEC: 1196*7c478bd9Sstevel@tonic-gate case 3: 1197*7c478bd9Sstevel@tonic-gate address_present = _B_TRUE; 1198*7c478bd9Sstevel@tonic-gate data_len = sizeof (tsp->ipt_timestamp.ipt_ta[0]); 1199*7c478bd9Sstevel@tonic-gate rrflag = _B_FALSE; 1200*7c478bd9Sstevel@tonic-gate break; 1201*7c478bd9Sstevel@tonic-gate default: 1202*7c478bd9Sstevel@tonic-gate Printf("(Bad flag value: 0x%x)", tsp->ipt_flg); 1203*7c478bd9Sstevel@tonic-gate return; 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate if (tsp->ipt_oflw > 0) 1206*7c478bd9Sstevel@tonic-gate Printf("(Overflow: %d) ", tsp->ipt_oflw); 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate /* data starts at offset 4 */ 1209*7c478bd9Sstevel@tonic-gate length -= 4; 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate while (length > 0) { 1212*7c478bd9Sstevel@tonic-gate if (length < data_len) 1213*7c478bd9Sstevel@tonic-gate break; 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate /* the minimum value of ipt_ptr is 5 */ 1216*7c478bd9Sstevel@tonic-gate if ((tsp->ipt_ptr == ts_index * data_len + 5) && rrflag) { 1217*7c478bd9Sstevel@tonic-gate Printf(" (End of record)"); 1218*7c478bd9Sstevel@tonic-gate break; 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate if (address_present) { 1221*7c478bd9Sstevel@tonic-gate bcopy(&tsp->ipt_timestamp.ipt_ta[ts_index].ipt_addr, 1222*7c478bd9Sstevel@tonic-gate &addr, sizeof (addr)); 1223*7c478bd9Sstevel@tonic-gate Printf("%s: ", pr_name((char *)&addr, AF_INET)); 1224*7c478bd9Sstevel@tonic-gate bcopy(&tsp->ipt_timestamp.ipt_ta[ts_index].ipt_time, 1225*7c478bd9Sstevel@tonic-gate &time, sizeof (time)); 1226*7c478bd9Sstevel@tonic-gate } else { 1227*7c478bd9Sstevel@tonic-gate bcopy(&tsp->ipt_timestamp.ipt_time[ts_index], 1228*7c478bd9Sstevel@tonic-gate &time, sizeof (time)); 1229*7c478bd9Sstevel@tonic-gate } 1230*7c478bd9Sstevel@tonic-gate Printf("%d", ntohl(time)); 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate if (tsp->ipt_ptr == ts_index * data_len + 5) 1233*7c478bd9Sstevel@tonic-gate Printf("(Current)"); 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate ts_index++; 1236*7c478bd9Sstevel@tonic-gate length -= data_len; 1237*7c478bd9Sstevel@tonic-gate if (length > 0) 1238*7c478bd9Sstevel@tonic-gate Printf(", "); 1239*7c478bd9Sstevel@tonic-gate } 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate * Convert an ICMP "type" field to a printable string. 1244*7c478bd9Sstevel@tonic-gate */ 1245*7c478bd9Sstevel@tonic-gate static char * 1246*7c478bd9Sstevel@tonic-gate pr_type(int icmp_type) 1247*7c478bd9Sstevel@tonic-gate { 1248*7c478bd9Sstevel@tonic-gate static struct icmptype_table ttab[] = { 1249*7c478bd9Sstevel@tonic-gate {ICMP_ECHOREPLY, "Echo Reply"}, 1250*7c478bd9Sstevel@tonic-gate {1, "ICMP 1"}, 1251*7c478bd9Sstevel@tonic-gate {2, "ICMP 2"}, 1252*7c478bd9Sstevel@tonic-gate {ICMP_UNREACH, "Dest Unreachable"}, 1253*7c478bd9Sstevel@tonic-gate {ICMP_SOURCEQUENCH, "Source Quench"}, 1254*7c478bd9Sstevel@tonic-gate {ICMP_REDIRECT, "Redirect"}, 1255*7c478bd9Sstevel@tonic-gate {6, "ICMP 6"}, 1256*7c478bd9Sstevel@tonic-gate {7, "ICMP 7"}, 1257*7c478bd9Sstevel@tonic-gate {ICMP_ECHO, "Echo"}, 1258*7c478bd9Sstevel@tonic-gate {ICMP_ROUTERADVERT, "Router Advertisement"}, 1259*7c478bd9Sstevel@tonic-gate {ICMP_ROUTERSOLICIT, "Router Solicitation"}, 1260*7c478bd9Sstevel@tonic-gate {ICMP_TIMXCEED, "Time Exceeded"}, 1261*7c478bd9Sstevel@tonic-gate {ICMP_PARAMPROB, "Parameter Problem"}, 1262*7c478bd9Sstevel@tonic-gate {ICMP_TSTAMP, "Timestamp"}, 1263*7c478bd9Sstevel@tonic-gate {ICMP_TSTAMPREPLY, "Timestamp Reply"}, 1264*7c478bd9Sstevel@tonic-gate {ICMP_IREQ, "Info Request"}, 1265*7c478bd9Sstevel@tonic-gate {ICMP_IREQREPLY, "Info Reply"}, 1266*7c478bd9Sstevel@tonic-gate {ICMP_MASKREQ, "Netmask Request"}, 1267*7c478bd9Sstevel@tonic-gate {ICMP_MASKREPLY, "Netmask Reply"} 1268*7c478bd9Sstevel@tonic-gate }; 1269*7c478bd9Sstevel@tonic-gate int i; 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate for (i = 0; i < A_CNT(ttab); i++) { 1272*7c478bd9Sstevel@tonic-gate if (ttab[i].type == icmp_type) 1273*7c478bd9Sstevel@tonic-gate return (ttab[i].message); 1274*7c478bd9Sstevel@tonic-gate } 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate return ("OUT-OF-RANGE"); 1277*7c478bd9Sstevel@tonic-gate } 1278