1 /*        $NetBSD: ping.c,v 1.122 2022/12/01 14:42:12 christos Exp $  */
2 
3 /*
4  * Copyright (c) 1989, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Mike Muuss.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  *                            P I N G . C
37  *
38  * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
39  * measure round-trip-delays and packet loss across network paths.
40  *
41  * Author -
42  *        Mike Muuss
43  *        U. S. Army Ballistic Research Laboratory
44  *        December, 1983
45  * Modified at Uc Berkeley
46  * Record Route and verbose headers - Phil Dykstra, BRL, March 1988.
47  * Multicast options (ttl, if, loop) - Steve Deering, Stanford, August 1988.
48  * ttl, duplicate detection - Cliff Frost, UCB, April 1989
49  * Pad pattern - Cliff Frost (from Tom Ferrin, UCSF), April 1989
50  *
51  * Status -
52  *        Public Domain.  Distribution Unlimited.
53  *
54  * Bugs -
55  *        More statistics could always be gathered.
56  *        This program has to run SUID to ROOT to access the ICMP socket.
57  */
58 
59 #include <sys/cdefs.h>
60 #ifndef lint
61 __RCSID("$NetBSD: ping.c,v 1.122 2022/12/01 14:42:12 christos Exp $");
62 #endif
63 
64 #include <stdio.h>
65 #include <stddef.h>
66 #include <errno.h>
67 #include <signal.h>
68 #include <sys/time.h>
69 #include <sys/types.h>
70 #include <sys/param.h>
71 #include <sys/socket.h>
72 #include <sys/file.h>
73 #include <termios.h>
74 #include <stdlib.h>
75 #include <unistd.h>
76 #include <poll.h>
77 #include <limits.h>
78 #include <math.h>
79 #include <string.h>
80 #include <err.h>
81 
82 #include <netinet/in_systm.h>
83 #include <netinet/in.h>
84 #include <netinet/ip.h>
85 #include <netinet/ip_icmp.h>
86 #include <netinet/ip_var.h>
87 #include <arpa/inet.h>
88 #include <ctype.h>
89 #include <netdb.h>
90 
91 #ifdef IPSEC
92 #include <netipsec/ipsec.h>
93 #endif /*IPSEC*/
94 
95 #include "prog_ops.h"
96 
97 #define FLOOD_INTVL 0.01                /* default flood output interval */
98 #define   MAXPACKET (IP_MAXPACKET-60-8) /* max packet size */
99 
100 #define F_VERBOSE   0x0001
101 #define F_QUIET               0x0002              /* minimize all output */
102 #define F_SEMI_QUIET          0x0004              /* ignore our ICMP errors */
103 #define F_FLOOD               0x0008              /* flood-ping */
104 #define   F_RECORD_ROUTE      0x0010              /* record route */
105 #define F_SOURCE_ROUTE        0x0020              /* loose source route */
106 #define F_PING_FILLED         0x0040              /* is buffer filled with user data? */
107 #define F_PING_RANDOM         0x0080              /* use random data */
108 #define   F_NUMERIC 0x0100              /* do not do gethostbyaddr() calls */
109 #define F_TIMING    0x0200              /* room for a timestamp */
110 #define F_DF                  0x0400              /* set IP DF bit */
111 #define F_SOURCE_ADDR         0x0800              /* set source IP address/interface */
112 #define F_ONCE                0x1000              /* exit(0) after receiving 1 reply */
113 #define F_MCAST               0x2000              /* multicast target */
114 #define F_MCAST_NOLOOP        0x4000              /* no multicast loopback */
115 #define F_AUDIBLE   0x8000              /* audible output */
116 #define F_TIMING64  0x10000             /* 64 bit time, nanoseconds */
117 #ifdef IPSEC
118 #ifdef IPSEC_POLICY_IPSEC
119 #define F_POLICY    0x20000
120 #else
121 #define   F_AUTHHDR 0x20000
122 #define   F_ENCRYPT 0x40000
123 #endif /*IPSEC_POLICY_IPSEC*/
124 #endif /*IPSEC*/
125 
126 
127 /* MAX_DUP_CHK is the number of bits in received table, the
128  *        maximum number of received sequence numbers we can track to check
129  *        for duplicates.
130  */
131 #define MAX_DUP_CHK     (8 * 2048)
132 static u_char       rcvd_tbl[MAX_DUP_CHK/8];
133 static int     nrepeats = 0;
134 #define A(seq)      rcvd_tbl[(seq/8)%sizeof(rcvd_tbl)]  /* byte in array */
135 #define B(seq)      (1 << (seq & 0x07)) /* bit in byte */
136 #define SET(seq) (A(seq) |= B(seq))
137 #define CLR(seq) (A(seq) &= (~B(seq)))
138 #define TST(seq) (A(seq) & B(seq))
139 
140 struct tv32 {
141           int32_t tv32_sec;
142           int32_t tv32_usec;
143 };
144 
145 
146 static u_char       *packet;
147 static int          packlen;
148 static int          pingflags = 0, options;
149 static int          pongflags = 0;
150 static char         *fill_pat;
151 
152 static int s;                                               /* Socket file descriptor */
153 static int sloop;                                 /* Socket file descriptor/loopback */
154 
155 #define PHDR_LEN sizeof(struct tv32)              /* size of timestamp header */
156 #define PHDR64_LEN sizeof(struct timespec)        /* size of timestamp header */
157 static struct sockaddr_in whereto, send_addr;     /* Who to ping */
158 static struct sockaddr_in src_addr;               /* from where */
159 static struct sockaddr_in loc_addr;               /* 127.1 */
160 static int datalen;                               /* How much data */
161 static int phdrlen;
162 
163 static sigset_t blockmask, enablemask;            /* signal masks */
164 
165 #ifndef __NetBSD__
166 static char *progname;
167 #define   getprogname()                 (progname)
168 #define   setprogname(name)   ((void)(progname = (name)))
169 #endif
170 
171 static char hostname[MAXHOSTNAMELEN];
172 
173 static struct {
174           struct ip o_ip;
175           char                o_opt[MAX_IPOPTLEN];
176           union {
177                     u_char        u_buf[MAXPACKET+offsetof(struct icmp, icmp_data)];
178                     struct icmp u_icmp;
179           } o_u;
180 } out_pack;
181 #define   opack_icmp          out_pack.o_u.u_icmp
182 static struct ip *opack_ip;
183 
184 static uint8_t optspace[MAX_IPOPTLEN];            /* record route space */
185 static int optlen;
186 
187 static int npackets;                                        /* total packets to send */
188 static int preload;                               /* number of packets to "preload" */
189 static int ntransmitted;                          /* output sequence # = #sent */
190 static int ident;                                 /* 16 random bits to identify our packets */
191 
192 static int nreceived;                                       /* # of packets we got back */
193 
194 static double interval;                           /* interval between packets */
195 static struct timespec interval_tv;
196 static double tmin = 999999999.0;
197 static double tmax = 0.0;
198 static double tsum = 0.0;                         /* sum of all times */
199 static double tsumsq = 0.0;
200 static double maxwait = 0.0;
201 
202 static int bufspace = IP_MAXPACKET;
203 
204 static struct timespec now, clear_cache, last_tx, next_tx, first_tx;
205 static struct timespec last_rx, first_rx;
206 static int lastrcvd = 1;                          /* last ping sent has been received */
207 
208 static struct timespec jiggle_time;
209 static int jiggle_cnt, total_jiggled, jiggle_direction = -1;
210 
211 __dead static void doit(void);
212 static void prefinish(int);
213 static void prtsig(int);
214 __dead static void finish(int);
215 static void blocksignals(void);
216 static void enablesignals(void);
217 static void summary(int);
218 static void pinger(void);
219 static void fill(void);
220 static void rnd_fill(void);
221 static double diffsec(struct timespec *, struct timespec *);
222 #if 0
223 static void timespecadd(struct timespec *, struct timespec *);
224 #endif
225 static void sec_to_timespec(const double, struct timespec *);
226 static double timespec_to_sec(const struct timespec *);
227 static void pr_pack(u_char *, int, struct sockaddr_in *);
228 static u_int16_t in_cksum(u_int16_t *, u_int);
229 static void pr_saddr(u_char *);
230 static char *pr_addr(struct in_addr *);
231 static void pr_iph(struct icmp *, int);
232 static void pr_retip(struct icmp *, int);
233 static int pr_icmph(struct icmp *, struct sockaddr_in *, int);
234 static void jiggle(int), jiggle_flush(int);
235 static void gethost(const char *, const char *,
236                         struct sockaddr_in *, char *, int);
237 __dead static void usage(void);
238 
239 int
main(int argc,char * argv[])240 main(int argc, char *argv[])
241 {
242           int c, i, on = 1, hostind = 0;
243           long l;
244           int len = -1, compat = 0;
245           u_char ttl = 0;
246           u_long tos = 0;
247           char *p;
248 #ifdef IPSEC
249 #ifdef IPSEC_POLICY_IPSEC
250           char *policy_in = NULL;
251           char *policy_out = NULL;
252 #endif
253 #endif
254 #ifdef SIGINFO
255           struct sigaction sa;
256 #endif
257 
258           if (prog_init && prog_init() == -1)
259                     err(EXIT_FAILURE, "init failed");
260 
261           if ((s = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
262                     err(EXIT_FAILURE, "Cannot create socket");
263           if ((sloop = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
264                     err(EXIT_FAILURE, "Cannot create socket");
265 
266           /*
267            * sloop is never read on.  This prevents packets from
268            * queueing in its recv buffer.
269            */
270           if (prog_shutdown(sloop, SHUT_RD) == -1)
271                     warn("Cannot shutdown for read");
272 
273           if (prog_setuid(prog_getuid()) == -1)
274                     err(EXIT_FAILURE, "setuid");
275 
276           setprogname(argv[0]);
277 
278 #ifndef IPSEC
279 #define IPSECOPT
280 #else
281 #ifdef IPSEC_POLICY_IPSEC
282 #define IPSECOPT    "E:"
283 #else
284 #define IPSECOPT    "AE"
285 #endif /*IPSEC_POLICY_IPSEC*/
286 #endif
287           while ((c = getopt(argc, argv,
288                                  "ac:CdDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT)) != -1) {
289 #undef IPSECOPT
290                     switch (c) {
291                     case 'a':
292                               pingflags |= F_AUDIBLE;
293                               break;
294                     case 'C':
295                               compat = 1;
296                               break;
297                     case 'c':
298                               l = strtol(optarg, &p, 0);
299                               if (*p != '\0' || l <= 0)
300                                         errx(EXIT_FAILURE,
301                                             "Bad/invalid number of packets: %s",
302                                             optarg);
303 #if INT_MAX < LONG_MAX
304                               if (l > INT_MAX)
305                                         errx(EXIT_FAILURE,
306                                             "Too many packets to count: %ld", l);
307 #endif
308                               npackets = l;
309                               break;
310                     case 'D':
311                               pingflags |= F_DF;
312                               break;
313                     case 'd':
314                               options |= SO_DEBUG;
315                               break;
316                     case 'f':
317                               pingflags |= F_FLOOD;
318                               break;
319                     case 'h':
320                               hostind = optind-1;
321                               break;
322                     case 'i':           /* wait between sending packets */
323                               interval = strtod(optarg, &p);
324                               if (*p != '\0' || interval <= 0)
325                                         errx(EXIT_FAILURE, "Bad/invalid interval: %s",
326                                             optarg);
327                               /*
328                                * In order to avoid overflowing the microseconds
329                                * argument of poll() the interval must be less than
330                                * INT_MAX/1000. Limit it to one second less than
331                                * that to be safe.
332                                */
333                               if (interval >= INT_MAX/1000.0 - 1.0)
334                                         errx(EXIT_FAILURE,
335                                             "Timing interval %g too large", interval);
336                               break;
337                     case 'l':
338                               l = strtol(optarg, &p, 0);
339                               if (*p != '\0' || l < 0)
340                                         errx(EXIT_FAILURE, "Bad/invalid preload value: "
341                                             "%s", optarg);
342 #if INT_MAX < LONG_MAX
343                               if (l > INT_MAX)
344                                         errx(EXIT_FAILURE,
345                                             "Too many preload packets: %ld", l);
346 #endif
347                               preload = l;
348                               break;
349                     case 'n':
350                               pingflags |= F_NUMERIC;
351                               break;
352                     case 'o':
353                               pingflags |= F_ONCE;
354                               break;
355                     case 'p':           /* fill buffer with user pattern */
356                               if (pingflags & F_PING_RANDOM)
357                                         errx(EXIT_FAILURE,
358                                             "Only one of -P and -p allowed");
359                               pingflags |= F_PING_FILLED;
360                               fill_pat = optarg;
361                               break;
362                     case 'P':
363                               if (pingflags & F_PING_FILLED)
364                                         errx(EXIT_FAILURE,
365                                             "Only one of -P and -p allowed");
366                               pingflags |= F_PING_RANDOM;
367                               break;
368                     case 'q':
369                               pingflags |= F_QUIET;
370                               break;
371                     case 'Q':
372                               pingflags |= F_SEMI_QUIET;
373                               break;
374                     case 'r':
375                               options |= SO_DONTROUTE;
376                               break;
377                     case 's':           /* size of packet to send */
378                               l = strtol(optarg, &p, 0);
379                               if (*p != '\0' || l < 0)
380                                         errx(EXIT_FAILURE,
381                                             "Bad/invalid packet size: %s", optarg);
382                               if (l > MAXPACKET)
383                                         errx(EXIT_FAILURE, "packet size is too large");
384                               len = (int)l;
385                               break;
386                     case 'v':
387                               pingflags |= F_VERBOSE;
388                               break;
389                     case 'R':
390                               pingflags |= F_RECORD_ROUTE;
391                               break;
392                     case 'L':
393                               pingflags |= F_MCAST_NOLOOP;
394                               break;
395                     case 't':
396                               tos = strtoul(optarg, &p, 0);
397                               if (*p != '\0' ||  tos > 0xFF)
398                                         errx(EXIT_FAILURE, "bad tos value: %s", optarg);
399                               break;
400                     case 'T':
401                               l = strtol(optarg, &p, 0);
402                               if (*p != '\0' || l > 255 || l <= 0)
403                                         errx(EXIT_FAILURE, "ttl out of range: %s",
404                                             optarg);
405                               ttl = (u_char)l;    /* cannot check >255 otherwise */
406                               break;
407                     case 'I':
408                               pingflags |= F_SOURCE_ADDR;
409                               gethost("-I", optarg, &src_addr, 0, 0);
410                               break;
411                     case 'g':
412                               pingflags |= F_SOURCE_ROUTE;
413                               gethost("-g", optarg, &send_addr, 0, 0);
414                               break;
415                     case 'w':
416                               maxwait = strtod(optarg, &p);
417                               if (*p != '\0' || maxwait <= 0)
418                                         errx(EXIT_FAILURE, "Bad/invalid maxwait time: "
419                                             "%s", optarg);
420                               break;
421 #ifdef IPSEC
422 #ifdef IPSEC_POLICY_IPSEC
423                     case 'E':
424                               pingflags |= F_POLICY;
425                               if (!strncmp("in", optarg, 2)) {
426                                         policy_in = strdup(optarg);
427                                         if (!policy_in)
428                                                   err(EXIT_FAILURE, "strdup");
429                               } else if (!strncmp("out", optarg, 3)) {
430                                         policy_out = strdup(optarg);
431                                         if (!policy_out)
432                                                   err(EXIT_FAILURE, "strdup");
433                               } else
434                                         errx(EXIT_FAILURE, "invalid security policy: "
435                                             "%s", optarg);
436                               break;
437 #else
438                     case 'A':
439                               pingflags |= F_AUTHHDR;
440                               break;
441                     case 'E':
442                               pingflags |= F_ENCRYPT;
443                               break;
444 #endif /*IPSEC_POLICY_IPSEC*/
445 #endif /*IPSEC*/
446                     default:
447                               usage();
448                               break;
449                     }
450           }
451 
452           if (interval == 0)
453                     interval = (pingflags & F_FLOOD) ? FLOOD_INTVL : 1.0;
454           if (pingflags & F_FLOOD && prog_getuid())
455                     errx(EXIT_FAILURE, "Must be superuser to use -f");
456           if (interval < 1.0 && prog_getuid())
457                     errx(EXIT_FAILURE, "Must be superuser to use < 1 sec "
458                         "ping interval");
459           if (preload > 0 && prog_getuid())
460                     errx(EXIT_FAILURE, "Must be superuser to use -l");
461 
462           sec_to_timespec(interval, &interval_tv);
463           if (interval_tv.tv_sec == 0 && interval_tv.tv_nsec == 0) {
464                     errx(EXIT_FAILURE, "Packet interval must be at least 1 ns");
465           }
466 
467           if ((pingflags & (F_AUDIBLE|F_FLOOD)) == (F_AUDIBLE|F_FLOOD))
468                     warnx("Sorry, no audible output for flood pings");
469 
470           if (npackets != 0) {
471                     npackets += preload;
472           } else {
473                     npackets = INT_MAX;
474           }
475 
476           if (hostind == 0) {
477                     if (optind != argc-1)
478                               usage();
479                     else
480                               hostind = optind;
481           }
482           else if (hostind >= argc - 1)
483                     usage();
484 
485           gethost("", argv[hostind], &whereto, hostname, sizeof(hostname));
486           if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)))
487                     pingflags |= F_MCAST;
488           if (!(pingflags & F_SOURCE_ROUTE))
489                     (void) memcpy(&send_addr, &whereto, sizeof(send_addr));
490 
491           loc_addr.sin_family = AF_INET;
492           loc_addr.sin_len = sizeof(struct sockaddr_in);
493           loc_addr.sin_addr.s_addr = htonl((127 << 24) + 1);
494 
495           if (len != -1)
496                     datalen = len;
497           else
498                     datalen = 64 - PHDR_LEN;
499           if (!compat && datalen >= (int)PHDR64_LEN) { /* can we time them? */
500                     pingflags |= F_TIMING64;
501                     phdrlen = PHDR64_LEN;
502           } else if (datalen >= (int)PHDR_LEN) {  /* can we time them? */
503                     pingflags |= F_TIMING;
504                     phdrlen = PHDR_LEN;
505           } else
506                     phdrlen = 0;
507 
508           packlen = datalen + 60 + 76;  /* MAXIP + MAXICMP */
509           if ((packet = malloc(packlen)) == NULL)
510                     err(EXIT_FAILURE, "Can't allocate %d bytes", packlen);
511 
512           if (pingflags & F_PING_FILLED) {
513                     fill();
514           } else if (pingflags & F_PING_RANDOM) {
515                     rnd_fill();
516           } else {
517                     for (i = phdrlen; i < datalen; i++)
518                               opack_icmp.icmp_data[i] = i;
519           }
520 
521           ident = arc4random() & 0xFFFF;
522 
523           if (options & SO_DEBUG) {
524                     if (prog_setsockopt(s, SOL_SOCKET, SO_DEBUG,
525                                      (char *)&on, sizeof(on)) == -1)
526                               warn("Can't turn on socket debugging");
527           }
528           if (options & SO_DONTROUTE) {
529                     if (prog_setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
530                                      (char *)&on, sizeof(on)) == -1)
531                               warn("SO_DONTROUTE");
532           }
533 
534           if (options & SO_DEBUG) {
535                     if (prog_setsockopt(sloop, SOL_SOCKET, SO_DEBUG,
536                                      (char *)&on, sizeof(on)) == -1)
537                               warn("Can't turn on socket debugging");
538           }
539           if (options & SO_DONTROUTE) {
540                     if (prog_setsockopt(sloop, SOL_SOCKET, SO_DONTROUTE,
541                                      (char *)&on, sizeof(on)) == -1)
542                               warn("SO_DONTROUTE");
543           }
544 
545           if (pingflags & F_SOURCE_ROUTE) {
546                     optspace[IPOPT_OPTVAL] = IPOPT_LSRR;
547                     optspace[IPOPT_OLEN] = optlen = 7;
548                     optspace[IPOPT_OFFSET] = IPOPT_MINOFF;
549                     (void)memcpy(&optspace[IPOPT_MINOFF-1], &whereto.sin_addr,
550                                    sizeof(whereto.sin_addr));
551                     optspace[optlen++] = IPOPT_NOP;
552           }
553           if (pingflags & F_RECORD_ROUTE) {
554                     optspace[optlen+IPOPT_OPTVAL] = IPOPT_RR;
555                     optspace[optlen+IPOPT_OLEN] = (MAX_IPOPTLEN -1-optlen);
556                     optspace[optlen+IPOPT_OFFSET] = IPOPT_MINOFF;
557                     optlen = MAX_IPOPTLEN;
558           }
559           /* this leaves opack_ip 0(mod 4) aligned */
560           opack_ip = (struct ip *)((char *)&out_pack.o_ip
561                                          + sizeof(out_pack.o_opt)
562                                          - optlen);
563           (void) memcpy(opack_ip + 1, optspace, optlen);
564 
565           if (prog_setsockopt(s, IPPROTO_IP, IP_HDRINCL,
566               (char *) &on, sizeof(on)) < 0)
567                     err(EXIT_FAILURE, "Can't set special IP header");
568 
569           opack_ip->ip_v = IPVERSION;
570           opack_ip->ip_hl = (sizeof(struct ip)+optlen) >> 2;
571           opack_ip->ip_tos = tos;
572           opack_ip->ip_off = (pingflags & F_DF) ? IP_DF : 0;
573           opack_ip->ip_ttl = ttl ? ttl : MAXTTL;
574           opack_ip->ip_p = IPPROTO_ICMP;
575           opack_ip->ip_src = src_addr.sin_addr;
576           opack_ip->ip_dst = send_addr.sin_addr;
577 
578           if (pingflags & F_MCAST) {
579                     if (pingflags & F_MCAST_NOLOOP) {
580                               u_char loop = 0;
581                               if (prog_setsockopt(s, IPPROTO_IP,
582                                   IP_MULTICAST_LOOP,
583                                   (char *) &loop, 1) < 0)
584                                         err(EXIT_FAILURE, "Can't disable multicast loopback");
585                     }
586 
587                     if (ttl != 0
588                         && prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
589                         (char *) &ttl, 1) < 0)
590                               err(EXIT_FAILURE, "Can't set multicast time-to-live");
591 
592                     if ((pingflags & F_SOURCE_ADDR)
593                         && prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
594                                           (char *) &src_addr.sin_addr,
595                                           sizeof(src_addr.sin_addr)) < 0)
596                               err(EXIT_FAILURE, "Can't set multicast source interface");
597 
598           } else if (pingflags & F_SOURCE_ADDR) {
599                     if (prog_setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
600                                      (char *) &src_addr.sin_addr,
601                                      sizeof(src_addr.sin_addr)) < 0)
602                               err(EXIT_FAILURE, "Can't set source interface/address");
603           }
604 #ifdef IPSEC
605 #ifdef IPSEC_POLICY_IPSEC
606     {
607           char *buf;
608           if (pingflags & F_POLICY) {
609                     if (policy_in != NULL) {
610                               buf = ipsec_set_policy(policy_in, strlen(policy_in));
611                               if (buf == NULL)
612                                         errx(EXIT_FAILURE, "%s", ipsec_strerror());
613                               if (prog_setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
614                                                   buf, ipsec_get_policylen(buf)) < 0) {
615                                         err(EXIT_FAILURE, "ipsec policy cannot be "
616                                             "configured");
617                               }
618                               free(buf);
619                     }
620                     if (policy_out != NULL) {
621                               buf = ipsec_set_policy(policy_out, strlen(policy_out));
622                               if (buf == NULL)
623                                         errx(EXIT_FAILURE, "%s", ipsec_strerror());
624                               if (prog_setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
625                                                   buf, ipsec_get_policylen(buf)) < 0) {
626                                         err(EXIT_FAILURE, "ipsec policy cannot be "
627                                             "configured");
628                               }
629                               free(buf);
630                     }
631           }
632           buf = ipsec_set_policy("out bypass", strlen("out bypass"));
633           if (buf == NULL)
634                     errx(EXIT_FAILURE, "%s", ipsec_strerror());
635           if (prog_setsockopt(sloop, IPPROTO_IP, IP_IPSEC_POLICY,
636                               buf, ipsec_get_policylen(buf)) < 0) {
637 #if 0
638                     warnx("ipsec is not configured");
639 #else
640                     /* ignore it, should be okay */
641 #endif
642           }
643           free(buf);
644     }
645 #else
646     {
647           int optval;
648           if (pingflags & F_AUTHHDR) {
649                     optval = IPSEC_LEVEL_REQUIRE;
650 #ifdef IP_AUTH_TRANS_LEVEL
651                     (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL,
652                               (char *)&optval, sizeof(optval));
653 #else
654                     (void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL,
655                               (char *)&optval, sizeof(optval));
656 #endif
657           }
658           if (pingflags & F_ENCRYPT) {
659                     optval = IPSEC_LEVEL_REQUIRE;
660                     (void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL,
661                               (char *)&optval, sizeof(optval));
662           }
663           optval = IPSEC_LEVEL_BYPASS;
664 #ifdef IP_AUTH_TRANS_LEVEL
665           (void)prog_setsockopt(sloop, IPPROTO_IP, IP_AUTH_TRANS_LEVEL,
666                     (char *)&optval, sizeof(optval));
667 #else
668           (void)prog_setsockopt(sloop, IPPROTO_IP, IP_AUTH_LEVEL,
669                     (char *)&optval, sizeof(optval));
670 #endif
671           (void)prog_setsockopt(sloop, IPPROTO_IP, IP_ESP_TRANS_LEVEL,
672                     (char *)&optval, sizeof(optval));
673     }
674 #endif /*IPSEC_POLICY_IPSEC*/
675 #endif /*IPSEC*/
676 
677           (void)printf("PING %s (%s): %d data bytes\n", hostname,
678                          inet_ntoa(whereto.sin_addr), datalen);
679 
680           /* When pinging the broadcast address, you can get a lot
681            * of answers.  Doing something so evil is useful if you
682            * are trying to stress the ethernet, or just want to
683            * fill the arp cache to get some stuff for /etc/ethers.
684            */
685           while (0 > prog_setsockopt(s, SOL_SOCKET, SO_RCVBUF,
686                                     (char*)&bufspace, sizeof(bufspace))) {
687                     if ((bufspace -= 4096) <= 0)
688                               err(EXIT_FAILURE, "Cannot set the receive buffer size");
689           }
690 
691           /* make it possible to send giant probes, but do not worry now
692            * if it fails, since we probably won't send giant probes.
693            */
694           (void)prog_setsockopt(s, SOL_SOCKET, SO_SNDBUF,
695                                (char*)&bufspace, sizeof(bufspace));
696 
697           (void)signal(SIGINT, prefinish);
698 
699           /*
700            * Set up two signal masks:
701            *    - blockmask blocks the signals we catch
702            *    - enablemask does not
703            */
704 
705           sigemptyset(&enablemask);
706           sigemptyset(&blockmask);
707           sigaddset(&blockmask, SIGINT);
708 #ifdef SIGINFO
709           sigaddset(&blockmask, SIGINFO);
710 #else
711           sigaddset(&blockmask, SIGQUIT);
712 #endif
713 
714 #ifdef SIGINFO
715           sa.sa_handler = prtsig;
716           sa.sa_flags = SA_NOKERNINFO;
717           sigemptyset(&sa.sa_mask);
718           (void)sigaction(SIGINFO, &sa, NULL);
719 #else
720           (void)signal(SIGQUIT, prtsig);
721 #endif
722           (void)signal(SIGCONT, prtsig);
723 
724           blocksignals();
725 
726           /* fire off them quickies */
727           for (i = 0; i < preload; i++) {
728                     clock_gettime(CLOCK_MONOTONIC, &now);
729                     pinger();
730           }
731 
732           doit();
733           return 0;
734 }
735 
736 static void
doit(void)737 doit(void)
738 {
739           int cc;
740           struct sockaddr_in from;
741           socklen_t fromlen;
742           double sec, last, d_last;
743           struct pollfd fdmaskp[1];
744 
745           (void)clock_gettime(CLOCK_MONOTONIC, &clear_cache);
746           if (maxwait != 0) {
747                     last = timespec_to_sec(&clear_cache) + maxwait;
748                     d_last = 0;
749           } else {
750                     last = 0;
751                     d_last = 365*24*60*60;
752           }
753 
754           do {
755                     clock_gettime(CLOCK_MONOTONIC, &now);
756 
757                     if (last != 0)
758                               d_last = last - timespec_to_sec(&now);
759 
760                     if (ntransmitted < npackets && d_last > 0) {
761                               /* send if within 100 usec or late for next packet */
762                               sec = diffsec(&next_tx, &now);
763                               if (sec <= 0.0001 ||
764                                   (lastrcvd && (pingflags & F_FLOOD))) {
765                                         pinger();
766                                         sec = diffsec(&next_tx, &now);
767                               }
768                               if (sec < 0.0)
769                                         sec = 0.0;
770                               if (d_last < sec)
771                                         sec = d_last;
772 
773                     } else {
774                               /* For the last response, wait twice as long as the
775                                * worst case seen, or 10 times as long as the
776                                * maximum interpacket interval, whichever is longer.
777                                */
778                               sec = MAX(2 * tmax, 10 * interval) -
779                                   diffsec(&now, &last_tx);
780                               if (d_last < sec)
781                                         sec = d_last;
782                               if (sec <= 0)
783                                         break;
784                     }
785 
786 
787                     fdmaskp[0].fd = s;
788                     fdmaskp[0].events = POLLIN;
789 
790                     enablesignals();
791                     cc = prog_poll(fdmaskp, 1, (int)(sec * 1000));
792                     blocksignals();
793 
794                     if (cc <= 0) {
795                               if (cc < 0) {
796                                         if (errno == EINTR)
797                                                   continue;
798                                         jiggle_flush(1);
799                                         err(EXIT_FAILURE, "poll");
800                               }
801                               continue;
802                     }
803 
804                     fromlen  = sizeof(from);
805                     cc = prog_recvfrom(s, (char *) packet, packlen,
806                                     0, (struct sockaddr *)&from,
807                                     &fromlen);
808                     if (cc < 0) {
809                               if (errno != EINTR) {
810                                         jiggle_flush(1);
811                                         warn("recvfrom");
812                                         (void)fflush(stderr);
813                               }
814                               continue;
815                     }
816                     clock_gettime(CLOCK_MONOTONIC, &now);
817                     pr_pack(packet, cc, &from);
818 
819           } while (nreceived < npackets
820                      && (nreceived == 0 || !(pingflags & F_ONCE)));
821 
822           finish(0);
823 }
824 
825 
826 static void
jiggle_flush(int nl)827 jiggle_flush(int nl)                              /* new line if there are dots */
828 {
829           int serrno = errno;
830 
831           if (jiggle_cnt > 0) {
832                     total_jiggled += jiggle_cnt;
833                     jiggle_direction = 1;
834                     do {
835                               (void)putchar('.');
836                     } while (--jiggle_cnt > 0);
837 
838           } else if (jiggle_cnt < 0) {
839                     total_jiggled -= jiggle_cnt;
840                     jiggle_direction = -1;
841                     do {
842                               (void)putchar('\b');
843                     } while (++jiggle_cnt < 0);
844           }
845 
846           if (nl) {
847                     if (total_jiggled != 0)
848                               (void)putchar('\n');
849                     total_jiggled = 0;
850                     jiggle_direction = -1;
851           }
852 
853           (void)fflush(stdout);
854           (void)fflush(stderr);
855           jiggle_time = now;
856           errno = serrno;
857 }
858 
859 
860 /* jiggle the cursor for flood-ping
861  */
862 static void
jiggle(int delta)863 jiggle(int delta)
864 {
865           double dt;
866 
867           if (pingflags & F_QUIET)
868                     return;
869 
870           /* do not back up into messages */
871           if (total_jiggled+jiggle_cnt+delta < 0)
872                     return;
873 
874           jiggle_cnt += delta;
875 
876           /* flush the FLOOD dots when things are quiet
877            * or occasionally to make the cursor jiggle.
878            */
879           dt = diffsec(&last_tx, &jiggle_time);
880           if (dt > 0.2 || (dt >= 0.15 && delta*jiggle_direction < 0))
881                     jiggle_flush(0);
882 }
883 
884 
885 /*
886  * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
887  * will be added on by the kernel.  The ID field is random,
888  * and the sequence number is an ascending integer.  The first phdrlen bytes
889  * of the data portion are used to hold a UNIX "timeval" struct in VAX
890  * byte-order, to compute the round-trip time, or a UNIX "timespec" in native
891  * format.
892  */
893 static void
pinger(void)894 pinger(void)
895 {
896           struct tv32 tv32;
897           int i, cc, sw;
898           double waittime;
899           long numskip;
900 
901           opack_icmp.icmp_code = 0;
902           opack_icmp.icmp_seq = htons((u_int16_t)(ntransmitted));
903 
904           /* clear the cached route in the kernel after an ICMP
905            * response such as a Redirect is seen to stop causing
906            * more such packets.  Also clear the cached route
907            * periodically in case of routing changes that make
908            * black holes come and go.
909            */
910           if (clear_cache.tv_sec != now.tv_sec) {
911                     opack_icmp.icmp_type = ICMP_ECHOREPLY;
912                     opack_icmp.icmp_id = ~ident;
913                     opack_icmp.icmp_cksum = 0;
914                     opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp,
915                         ICMP_MINLEN);
916                     sw = 0;
917                     if (prog_setsockopt(sloop, IPPROTO_IP, IP_HDRINCL,
918                                      (char *)&sw, sizeof(sw)) < 0)
919                               err(EXIT_FAILURE, "Can't turn off special IP header");
920                     if (prog_sendto(sloop, (char *) &opack_icmp,
921                                  ICMP_MINLEN, MSG_DONTROUTE,
922                                  (struct sockaddr *)&loc_addr,
923                                  sizeof(struct sockaddr_in)) < 0) {
924                               /*
925                                * XXX: we only report this as a warning in verbose
926                                * mode because people get confused when they see
927                                * this error when they are running in single user
928                                * mode and they have not configured lo0
929                                */
930                               if (pingflags & F_VERBOSE)
931                                         warn("failed to clear cached route");
932                     }
933                     sw = 1;
934                     if (prog_setsockopt(sloop, IPPROTO_IP, IP_HDRINCL,
935                                      (char *)&sw, sizeof(sw)) < 0)
936                               err(EXIT_FAILURE, "Can't set special IP header");
937 
938                     (void)clock_gettime(CLOCK_MONOTONIC, &clear_cache);
939           }
940 
941           opack_icmp.icmp_type = ICMP_ECHO;
942           opack_icmp.icmp_id = ident;
943 
944           if (pingflags & F_TIMING) {
945                     tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
946                     tv32.tv32_usec = htonl(now.tv_nsec / 1000);
947                     (void) memcpy(&opack_icmp.icmp_data[0], &tv32, sizeof(tv32));
948           } else if (pingflags & F_TIMING64)
949                     (void) memcpy(&opack_icmp.icmp_data[0], &now, sizeof(now));
950 
951           cc = MAX(datalen, ICMP_MINLEN) + PHDR_LEN;
952           opack_icmp.icmp_cksum = 0;
953           opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp, cc);
954 
955           cc += opack_ip->ip_hl<<2;
956           opack_ip->ip_len = cc;
957           i = prog_sendto(s, (char *) opack_ip, cc, 0,
958                        (struct sockaddr *)&send_addr, sizeof(struct sockaddr_in));
959           if (i != cc) {
960                     jiggle_flush(1);
961                     if (i < 0)
962                               warn("sendto");
963                     else
964                               warnx("wrote %s %d chars, ret=%d", hostname, cc, i);
965                     (void)fflush(stderr);
966           }
967           lastrcvd = 0;
968 
969           CLR(ntransmitted);
970           ntransmitted++;
971 
972           last_tx = now;
973           if (next_tx.tv_sec == 0) {
974                     first_tx = now;
975                     next_tx = now;
976           }
977 
978           /* Transmit regularly, at always the same microsecond in the
979            * second when going at one packet per second.
980            * If we are at most 100 ms behind, send extras to get caught up.
981            * Otherwise, skip packets we were too slow to send.
982            */
983           waittime = diffsec(&next_tx, &now);
984           if (waittime < -1.0) {
985                     /* very behind - forget about being precise */
986                     next_tx.tv_sec += (int)(-waittime);
987           } else if (waittime < -0.1) {
988                     /* behind - skip a few */
989                     if (interval_tv.tv_sec == 0) {
990                               numskip = (long)(-waittime / interval_tv.tv_nsec);
991                               next_tx.tv_nsec += numskip * interval_tv.tv_nsec;
992                               /*
993                                * We can add at most one second's worth, but allow
994                                * for tv_nsec reaching 2 billion just in case FP
995                                * issues strike.
996                                */
997                               while (next_tx.tv_nsec >= 1000000000) {
998                                         next_tx.tv_sec++;
999                                         next_tx.tv_nsec -= 1000000000;
1000                               }
1001                     } else {
1002                               do {
1003                                         timespecadd(&next_tx, &interval_tv, &next_tx);
1004                               } while (diffsec(&next_tx, &now) < -0.1);
1005                     }
1006 
1007           } else if (waittime <= interval) {
1008                     timespecadd(&next_tx, &interval_tv, &next_tx);
1009           }
1010 
1011           if (pingflags & F_FLOOD)
1012                     jiggle(1);
1013 
1014           /* While the packet is going out, ready buffer for the next
1015            * packet. Use a fast but not very good random number generator.
1016            */
1017           if (pingflags & F_PING_RANDOM)
1018                     rnd_fill();
1019 }
1020 
1021 
1022 static void
pr_pack_sub(int cc,char * addr,int seqno,int dupflag,int ttl,double triptime)1023 pr_pack_sub(int cc,
1024               char *addr,
1025               int seqno,
1026               int dupflag,
1027               int ttl,
1028               double triptime)
1029 {
1030           jiggle_flush(1);
1031 
1032           if (pingflags & F_FLOOD)
1033                     return;
1034 
1035           (void)printf("%d bytes from %s: icmp_seq=%u", cc, addr, seqno);
1036           if (dupflag)
1037                     (void)printf(" DUP!");
1038           (void)printf(" ttl=%d", ttl);
1039           if (pingflags & (F_TIMING|F_TIMING64)) {
1040                     const unsigned int prec = (pingflags & F_TIMING64) != 0 ? 6 : 3;
1041 
1042                     (void)printf(" time=%.*f ms", prec, triptime*1000.0);
1043           }
1044 
1045           /*
1046            * Send beep to stderr, since that's more likely than stdout
1047            * to go to a terminal..
1048            */
1049           if (pingflags & F_AUDIBLE && !dupflag)
1050                     (void)fprintf(stderr,"\a");
1051 }
1052 
1053 
1054 /*
1055  * Print out the packet, if it came from us.  This logic is necessary
1056  * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
1057  * which arrive ('tis only fair).  This permits multiple copies of this
1058  * program to be run without having intermingled output (or statistics!).
1059  */
1060 static void
pr_pack(u_char * buf,int tot_len,struct sockaddr_in * from)1061 pr_pack(u_char *buf,
1062           int tot_len,
1063           struct sockaddr_in *from)
1064 {
1065           struct ip *ip;
1066           struct icmp *icp;
1067           int i, j, net_len;
1068           u_char *cp;
1069           static int old_rrlen;
1070           static char old_rr[MAX_IPOPTLEN];
1071           int hlen, dupflag = 0, dumped;
1072           double triptime = 0.0;
1073 #define PR_PACK_SUB() {if (!dumped) {                       \
1074           dumped = 1;                                                 \
1075           pr_pack_sub(net_len, inet_ntoa(from->sin_addr),   \
1076                         ntohs((u_int16_t)icp->icmp_seq),    \
1077                         dupflag, ip->ip_ttl, triptime);}}
1078 
1079           /* Check the IP header */
1080           ip = (struct ip *) buf;
1081           hlen = ip->ip_hl << 2;
1082           if (hlen < (int)sizeof(*ip) || tot_len < hlen + ICMP_MINLEN) {
1083                     if (pingflags & F_VERBOSE) {
1084                               jiggle_flush(1);
1085                               (void)printf("packet too short (%d bytes) from %s\n",
1086                                              tot_len, inet_ntoa(from->sin_addr));
1087                     }
1088                     return;
1089           }
1090 
1091           /* Now the ICMP part */
1092           dumped = 0;
1093           net_len = tot_len - hlen;
1094           icp = (struct icmp *)(buf + hlen);
1095           if (icp->icmp_type == ICMP_ECHOREPLY
1096               && icp->icmp_id == ident) {
1097 
1098                     if (icp->icmp_seq == htons((u_int16_t)(ntransmitted-1)))
1099                               lastrcvd = 1;
1100                     last_rx = now;
1101                     if (first_rx.tv_sec == 0)
1102                               first_rx = last_rx;
1103                     nreceived++;
1104                     if (pingflags & (F_TIMING|F_TIMING64)) {
1105                               struct timespec tv;
1106 
1107                               if (pingflags & F_TIMING) {
1108                                         struct tv32 tv32;
1109 
1110                                         (void)memcpy(&tv32, icp->icmp_data, sizeof(tv32));
1111                                         tv.tv_sec = (uint32_t)ntohl(tv32.tv32_sec);
1112                                         tv.tv_nsec = ntohl(tv32.tv32_usec) * 1000;
1113                               } else if (pingflags & F_TIMING64)
1114                                         (void)memcpy(&tv, icp->icmp_data, sizeof(tv));
1115                               else
1116                                         memset(&tv, 0, sizeof(tv));   /* XXX: gcc */
1117 
1118                               triptime = diffsec(&last_rx, &tv);
1119                               tsum += triptime;
1120                               tsumsq += triptime * triptime;
1121                               if (triptime < tmin)
1122                                         tmin = triptime;
1123                               if (triptime > tmax)
1124                                         tmax = triptime;
1125                     }
1126 
1127                     if (TST(ntohs((u_int16_t)icp->icmp_seq))) {
1128                               nrepeats++, nreceived--;
1129                               dupflag=1;
1130                     } else {
1131                               SET(ntohs((u_int16_t)icp->icmp_seq));
1132                     }
1133 
1134                     if (tot_len != opack_ip->ip_len) {
1135                               PR_PACK_SUB();
1136                               switch (opack_ip->ip_len - tot_len) {
1137                               case MAX_IPOPTLEN:
1138                                         if ((pongflags & F_RECORD_ROUTE) != 0)
1139                                                   break;
1140                                         if ((pingflags & F_RECORD_ROUTE) == 0)
1141                                                   goto out;
1142                                         pongflags |= F_RECORD_ROUTE;
1143                                         (void)printf("\nremote host does not "
1144                                             "support record route");
1145                                         break;
1146                               case 8:
1147                                         if ((pongflags & F_SOURCE_ROUTE) != 0)
1148                                                   break;
1149                                         if ((pingflags & F_SOURCE_ROUTE) == 0)
1150                                                   goto out;
1151                                         pongflags |= F_SOURCE_ROUTE;
1152                                         (void)printf("\nremote host does not "
1153                                             "support source route");
1154                                         break;
1155                               default:
1156                               out:
1157                                         (void)printf("\nwrong total length %d "
1158                                             "instead of %d", tot_len, opack_ip->ip_len);
1159                                         break;
1160                               }
1161                     }
1162 
1163                     if (!dupflag) {
1164                               static u_int16_t last_seqno = 0xffff;
1165                               u_int16_t seqno = ntohs((u_int16_t)icp->icmp_seq);
1166                               u_int16_t gap = seqno - (last_seqno + 1);
1167                               if (gap > 0 && gap < 0x8000 &&
1168                                   (pingflags & F_VERBOSE)) {
1169                                         (void)printf("[*** sequence gap of %u "
1170                                             "packets from %u ... %u ***]\n", gap,
1171                                             (u_int16_t) (last_seqno + 1),
1172                                             (u_int16_t) (seqno - 1));
1173                                         if (pingflags & F_QUIET)
1174                                                   summary(0);
1175                               }
1176 
1177                               if (gap < 0x8000)
1178                                         last_seqno = seqno;
1179                     }
1180 
1181                     if (pingflags & F_QUIET)
1182                               return;
1183 
1184                     if (!(pingflags & F_FLOOD))
1185                               PR_PACK_SUB();
1186 
1187                     /* check the data */
1188                     if ((size_t)(tot_len - hlen) >
1189                         offsetof(struct icmp, icmp_data) + datalen
1190                         && !(pingflags & F_PING_RANDOM)
1191                         && memcmp(icp->icmp_data + phdrlen,
1192                                   opack_icmp.icmp_data + phdrlen,
1193                                   datalen - phdrlen)) {
1194                               for (i = phdrlen; i < datalen; i++) {
1195                                         if (icp->icmp_data[i] !=
1196                                             opack_icmp.icmp_data[i])
1197                                                   break;
1198                               }
1199                               PR_PACK_SUB();
1200                               (void)printf("\nwrong data byte #%d should have been"
1201                                              " %#x but was %#x", i - phdrlen,
1202                                              (u_char)opack_icmp.icmp_data[i],
1203                                              (u_char)icp->icmp_data[i]);
1204                               for (i = phdrlen; i < datalen; i++) {
1205                                         if ((i % 16) == 0)
1206                                                   (void)printf("\n\t");
1207                                         (void)printf("%2x ",(u_char)icp->icmp_data[i]);
1208                               }
1209                     }
1210 
1211           } else {
1212                     if (!pr_icmph(icp, from, net_len))
1213                               return;
1214                     dumped = 2;
1215           }
1216 
1217           /* Display any IP options */
1218           cp = buf + sizeof(struct ip);
1219           while (hlen > (int)sizeof(struct ip)) {
1220                     switch (*cp) {
1221                     case IPOPT_EOL:
1222                               hlen = 0;
1223                               break;
1224                     case IPOPT_LSRR:
1225                               hlen -= 2;
1226                               j = *++cp;
1227                               ++cp;
1228                               j -= IPOPT_MINOFF;
1229                               if (j <= 0)
1230                                         continue;
1231                               if (dumped <= 1) {
1232                                         j = ((j+3)/4)*4;
1233                                         hlen -= j;
1234                                         cp += j;
1235                                         break;
1236                               }
1237                               PR_PACK_SUB();
1238                               (void)printf("\nLSRR: ");
1239                               for (;;) {
1240                                         pr_saddr(cp);
1241                                         cp += 4;
1242                                         hlen -= 4;
1243                                         j -= 4;
1244                                         if (j <= 0)
1245                                                   break;
1246                                         (void)putchar('\n');
1247                               }
1248                               break;
1249                     case IPOPT_RR:
1250                               j = *++cp;          /* get length */
1251                               i = *++cp;          /* and pointer */
1252                               hlen -= 2;
1253                               if (i > j)
1254                                         i = j;
1255                               i -= IPOPT_MINOFF;
1256                               if (i <= 0)
1257                                         continue;
1258                               if (dumped <= 1) {
1259                                         if (i == old_rrlen
1260                                             && !memcmp(cp, old_rr, i)) {
1261                                                   if (dumped)
1262                                                       (void)printf("\t(same route)");
1263                                                   j = ((i+3)/4)*4;
1264                                                   hlen -= j;
1265                                                   cp += j;
1266                                                   break;
1267                                         }
1268                                         old_rrlen = i;
1269                                         (void) memcpy(old_rr, cp, i);
1270                               }
1271                               if (!dumped) {
1272                                         jiggle_flush(1);
1273                                         (void)printf("RR: ");
1274                                         dumped = 1;
1275                               } else {
1276                                         (void)printf("\nRR: ");
1277                               }
1278                               for (;;) {
1279                                         pr_saddr(cp);
1280                                         cp += 4;
1281                                         hlen -= 4;
1282                                         i -= 4;
1283                                         if (i <= 0)
1284                                                   break;
1285                                         (void)putchar('\n');
1286                               }
1287                               break;
1288                     case IPOPT_NOP:
1289                               if (dumped <= 1)
1290                                         break;
1291                               PR_PACK_SUB();
1292                               (void)printf("\nNOP");
1293                               break;
1294                     default:
1295                               PR_PACK_SUB();
1296                               (void)printf("\nunknown option 0x%x", *cp);
1297                               break;
1298                     }
1299                     hlen--;
1300                     cp++;
1301           }
1302 
1303           if (dumped) {
1304                     (void)putchar('\n');
1305                     (void)fflush(stdout);
1306           } else {
1307                     jiggle(-1);
1308           }
1309 }
1310 
1311 
1312 /* Compute the IP checksum
1313  *        This assumes the packet is less than 32K long.
1314  */
1315 static u_int16_t
in_cksum(u_int16_t * p,u_int len)1316 in_cksum(u_int16_t *p, u_int len)
1317 {
1318           u_int32_t sum = 0;
1319           int nwords = len >> 1;
1320 
1321           while (nwords-- != 0)
1322                     sum += *p++;
1323 
1324           if (len & 1) {
1325                     union {
1326                               u_int16_t w;
1327                               u_int8_t c[2];
1328                     } u;
1329                     u.c[0] = *(u_char *)p;
1330                     u.c[1] = 0;
1331                     sum += u.w;
1332           }
1333 
1334           /* end-around-carry */
1335           sum = (sum >> 16) + (sum & 0xffff);
1336           sum += (sum >> 16);
1337           return (~sum);
1338 }
1339 
1340 
1341 /*
1342  * compute the difference of two timespecs in seconds
1343  */
1344 static double
diffsec(struct timespec * timenow,struct timespec * then)1345 diffsec(struct timespec *timenow,
1346           struct timespec *then)
1347 {
1348           if (timenow->tv_sec == 0)
1349                     return -1;
1350           return (timenow->tv_sec - then->tv_sec)
1351               * 1.0 + (timenow->tv_nsec - then->tv_nsec) / 1000000000.0;
1352 }
1353 
1354 
1355 #if 0
1356 static void
1357 timespecadd(struct timespec *t1,
1358              struct timespec *t2)
1359 {
1360 
1361           t1->tv_sec += t2->tv_sec;
1362           if ((t1->tv_nsec += t2->tv_nsec) >= 1000000000) {
1363                     t1->tv_sec++;
1364                     t1->tv_nsec -= 1000000000;
1365           }
1366 }
1367 #endif
1368 
1369 
1370 static void
sec_to_timespec(const double sec,struct timespec * tp)1371 sec_to_timespec(const double sec, struct timespec *tp)
1372 {
1373           tp->tv_sec = sec;
1374           tp->tv_nsec = (sec - tp->tv_sec) * 1000000000.0;
1375 }
1376 
1377 
1378 static double
timespec_to_sec(const struct timespec * tp)1379 timespec_to_sec(const struct timespec *tp)
1380 {
1381           return tp->tv_sec + tp->tv_nsec / 1000000000.0;
1382 }
1383 
1384 
1385 /*
1386  * Print statistics.
1387  * Heavily buffered STDIO is used here, so that all the statistics
1388  * will be written with 1 sys-write call.  This is nice when more
1389  * than one copy of the program is running on a terminal;  it prevents
1390  * the statistics output from becoming intermingled.
1391  */
1392 static void
summary(int header)1393 summary(int header)
1394 {
1395           jiggle_flush(1);
1396 
1397           if (header)
1398                     (void)printf("\n----%s PING Statistics----\n", hostname);
1399           (void)printf("%d packets transmitted, ", ntransmitted);
1400           (void)printf("%d packets received, ", nreceived);
1401           if (nrepeats)
1402                     (void)printf("+%d duplicates, ", nrepeats);
1403           if (ntransmitted) {
1404                     if (nreceived > ntransmitted)
1405                               (void)printf("-- somebody's duplicating packets!");
1406                     else
1407                               (void)printf("%.1f%% packet loss",
1408                                              (((ntransmitted-nreceived)*100.0) /
1409                                                       ntransmitted));
1410           }
1411           (void)printf("\n");
1412           if (nreceived && (pingflags & (F_TIMING|F_TIMING64))) {
1413                     double n = nreceived + nrepeats;
1414                     double avg = (tsum / n);
1415                     double variance = 0.0;
1416                     const unsigned int prec = (pingflags & F_TIMING64) != 0 ? 6 : 3;
1417                     if (n>1)
1418                               variance = (tsumsq - n*avg*avg) /(n-1);
1419 
1420                     (void)printf("round-trip min/avg/max/stddev = "
1421                               "%.*f/%.*f/%.*f/%.*f ms\n",
1422                               prec, tmin * 1000.0,
1423                               prec, avg * 1000.0,
1424                               prec, tmax * 1000.0,
1425                               prec, sqrt(variance) * 1000.0);
1426                     if (pingflags & F_FLOOD) {
1427                               double r = diffsec(&last_rx, &first_rx);
1428                               double t = diffsec(&last_tx, &first_tx);
1429                               if (r == 0)
1430                                         r = 0.0001;
1431                               if (t == 0)
1432                                         t = 0.0001;
1433                               (void)printf("  %.1f packets/sec sent, "
1434                                              " %.1f packets/sec received\n",
1435                                              ntransmitted/t, nreceived/r);
1436                     }
1437           }
1438 }
1439 
1440 
1441 /*
1442  * Print statistics when SIGINFO is received.
1443  */
1444 /* ARGSUSED */
1445 static void
prtsig(int dummy)1446 prtsig(int dummy)
1447 {
1448 
1449           summary(0);
1450 #ifndef SIGINFO
1451           (void)signal(SIGQUIT, prtsig);
1452 #endif
1453 }
1454 
1455 
1456 /*
1457  * On the first SIGINT, allow any outstanding packets to dribble in
1458  */
1459 static void
prefinish(int sig)1460 prefinish(int sig)
1461 {
1462           if (lastrcvd                            /* quit now if caught up */
1463               || nreceived == 0)                  /* or if remote is dead */
1464                     finish(0);
1465 
1466           (void)signal(sig, finish);    /* do this only the 1st time */
1467 
1468           if (npackets > ntransmitted)  /* let the normal limit work */
1469                     npackets = ntransmitted;
1470 }
1471 
1472 /*
1473  * Print statistics and give up.
1474  */
1475 /* ARGSUSED */
1476 static void
finish(int dummy)1477 finish(int dummy)
1478 {
1479 #ifdef SIGINFO
1480           (void)signal(SIGINFO, SIG_DFL);
1481 #else
1482           (void)signal(SIGQUIT, SIG_DFL);
1483 #endif
1484 
1485           summary(1);
1486           exit(nreceived > 0 ? 0 : 2);
1487 }
1488 
1489 static void
blocksignals(void)1490 blocksignals(void)
1491 {
1492           if (sigprocmask(SIG_SETMASK, &blockmask, NULL) == -1) {
1493                     err(EXIT_FAILURE, "blocksignals: sigprocmask");
1494           }
1495 }
1496 
1497 static void
enablesignals(void)1498 enablesignals(void)
1499 {
1500           if (sigprocmask(SIG_SETMASK, &enablemask, NULL) == -1) {
1501                     err(EXIT_FAILURE, "enablesignals: sigprocmask");
1502           }
1503 }
1504 
1505 
1506 static int                                        /* 0=do not print it */
ck_pr_icmph(struct icmp * icp,struct sockaddr_in * from,int cc,int override)1507 ck_pr_icmph(struct icmp *icp,
1508               struct sockaddr_in *from,
1509               int cc,
1510               int override)             /* 1=override VERBOSE if interesting */
1511 {
1512           int       hlen;
1513           struct ip ipb, *ip = &ipb;
1514           struct icmp icp2b, *icp2 = &icp2b;
1515           int res;
1516 
1517           if (pingflags & F_VERBOSE) {
1518                     res = 1;
1519                     jiggle_flush(1);
1520           } else {
1521                     res = 0;
1522           }
1523 
1524           (void) memcpy(ip, icp->icmp_data, sizeof(*ip));
1525           hlen = ip->ip_hl << 2;
1526           if (ip->ip_p == IPPROTO_ICMP
1527               && hlen + 6 <= cc) {
1528                     (void) memcpy(icp2, &icp->icmp_data[hlen], sizeof(*icp2));
1529                     if (icp2->icmp_id == ident) {
1530                               /* remember to clear route cached in kernel
1531                                * if this non-Echo-Reply ICMP message was for one
1532                                * of our packets.
1533                                */
1534                               clear_cache.tv_sec = 0;
1535 
1536                               if (!res && override
1537                                   && (pingflags & (F_QUIET|F_SEMI_QUIET)) == 0) {
1538                                         jiggle_flush(1);
1539                                         (void)printf("%d bytes from %s: ",
1540                                                        cc, pr_addr(&from->sin_addr));
1541                                         res = 1;
1542                               }
1543                     }
1544           }
1545 
1546           return res;
1547 }
1548 
1549 
1550 /*
1551  *  Print a descriptive string about an ICMP header other than an echo reply.
1552  */
1553 static int                                        /* 0=printed nothing */
pr_icmph(struct icmp * icp,struct sockaddr_in * from,int cc)1554 pr_icmph(struct icmp *icp,
1555            struct sockaddr_in *from,
1556            int cc)
1557 {
1558           switch (icp->icmp_type ) {
1559           case ICMP_UNREACH:
1560                     if (!ck_pr_icmph(icp, from, cc, 1))
1561                               return 0;
1562                     switch (icp->icmp_code) {
1563                     case ICMP_UNREACH_NET:
1564                               (void)printf("Destination Net Unreachable");
1565                               break;
1566                     case ICMP_UNREACH_HOST:
1567                               (void)printf("Destination Host Unreachable");
1568                               break;
1569                     case ICMP_UNREACH_PROTOCOL:
1570                               (void)printf("Destination Protocol Unreachable");
1571                               break;
1572                     case ICMP_UNREACH_PORT:
1573                               (void)printf("Destination Port Unreachable");
1574                               break;
1575                     case ICMP_UNREACH_NEEDFRAG:
1576                               (void)printf("frag needed and DF set.  Next MTU=%d",
1577                                      ntohs(icp->icmp_nextmtu));
1578                               break;
1579                     case ICMP_UNREACH_SRCFAIL:
1580                               (void)printf("Source Route Failed");
1581                               break;
1582                     case ICMP_UNREACH_NET_UNKNOWN:
1583                               (void)printf("Unreachable unknown net");
1584                               break;
1585                     case ICMP_UNREACH_HOST_UNKNOWN:
1586                               (void)printf("Unreachable unknown host");
1587                               break;
1588                     case ICMP_UNREACH_ISOLATED:
1589                               (void)printf("Unreachable host isolated");
1590                               break;
1591                     case ICMP_UNREACH_NET_PROHIB:
1592                               (void)printf("Net prohibited access");
1593                               break;
1594                     case ICMP_UNREACH_HOST_PROHIB:
1595                               (void)printf("Host prohibited access");
1596                               break;
1597                     case ICMP_UNREACH_TOSNET:
1598                               (void)printf("Bad TOS for net");
1599                               break;
1600                     case ICMP_UNREACH_TOSHOST:
1601                               (void)printf("Bad TOS for host");
1602                               break;
1603                     case 13:
1604                               (void)printf("Communication prohibited");
1605                               break;
1606                     case 14:
1607                               (void)printf("Host precedence violation");
1608                               break;
1609                     case 15:
1610                               (void)printf("Precedence cutoff");
1611                               break;
1612                     default:
1613                               (void)printf("Bad Destination Unreachable Code: %d",
1614                                              icp->icmp_code);
1615                               break;
1616                     }
1617                     /* Print returned IP header information */
1618                     pr_retip(icp, cc);
1619                     break;
1620 
1621           case ICMP_SOURCEQUENCH:
1622                     if (!ck_pr_icmph(icp, from, cc, 1))
1623                               return 0;
1624                     (void)printf("Source Quench");
1625                     pr_retip(icp, cc);
1626                     break;
1627 
1628           case ICMP_REDIRECT:
1629                     if (!ck_pr_icmph(icp, from, cc, 1))
1630                               return 0;
1631                     switch (icp->icmp_code) {
1632                     case ICMP_REDIRECT_NET:
1633                               (void)printf("Redirect Network");
1634                               break;
1635                     case ICMP_REDIRECT_HOST:
1636                               (void)printf("Redirect Host");
1637                               break;
1638                     case ICMP_REDIRECT_TOSNET:
1639                               (void)printf("Redirect Type of Service and Network");
1640                               break;
1641                     case ICMP_REDIRECT_TOSHOST:
1642                               (void)printf("Redirect Type of Service and Host");
1643                               break;
1644                     default:
1645                               (void)printf("Redirect--Bad Code: %d", icp->icmp_code);
1646                               break;
1647                     }
1648                     (void)printf(" New router addr: %s",
1649                                    pr_addr(&icp->icmp_hun.ih_gwaddr));
1650                     pr_retip(icp, cc);
1651                     break;
1652 
1653           case ICMP_ECHO:
1654                     if (!ck_pr_icmph(icp, from, cc, 0))
1655                               return 0;
1656                     (void)printf("Echo Request: ID=%d seq=%d",
1657                                    ntohs(icp->icmp_id), ntohs(icp->icmp_seq));
1658                     break;
1659 
1660           case ICMP_ECHOREPLY:
1661                     /* displaying other's pings is too noisey */
1662 #if 0
1663                     if (!ck_pr_icmph(icp, from, cc, 0))
1664                               return 0;
1665                     (void)printf("Echo Reply: ID=%d seq=%d",
1666                                    ntohs(icp->icmp_id), ntohs(icp->icmp_seq));
1667                     break;
1668 #else
1669                     return 0;
1670 #endif
1671 
1672           case ICMP_ROUTERADVERT:
1673                     if (!ck_pr_icmph(icp, from, cc, 0))
1674                               return 0;
1675                     (void)printf("Router Discovery Advert");
1676                     break;
1677 
1678           case ICMP_ROUTERSOLICIT:
1679                     if (!ck_pr_icmph(icp, from, cc, 0))
1680                               return 0;
1681                     (void)printf("Router Discovery Solicit");
1682                     break;
1683 
1684           case ICMP_TIMXCEED:
1685                     if (!ck_pr_icmph(icp, from, cc, 1))
1686                               return 0;
1687                     switch (icp->icmp_code ) {
1688                     case ICMP_TIMXCEED_INTRANS:
1689                               (void)printf("Time To Live exceeded");
1690                               break;
1691                     case ICMP_TIMXCEED_REASS:
1692                               (void)printf("Frag reassembly time exceeded");
1693                               break;
1694                     default:
1695                               (void)printf("Time exceeded, Bad Code: %d",
1696                                              icp->icmp_code);
1697                               break;
1698                     }
1699                     pr_retip(icp, cc);
1700                     break;
1701 
1702           case ICMP_PARAMPROB:
1703                     if (!ck_pr_icmph(icp, from, cc, 1))
1704                               return 0;
1705                     (void)printf("Parameter problem: pointer = 0x%02x",
1706                                    icp->icmp_hun.ih_pptr);
1707                     pr_retip(icp, cc);
1708                     break;
1709 
1710           case ICMP_TSTAMP:
1711                     if (!ck_pr_icmph(icp, from, cc, 0))
1712                               return 0;
1713                     (void)printf("Timestamp");
1714                     break;
1715 
1716           case ICMP_TSTAMPREPLY:
1717                     if (!ck_pr_icmph(icp, from, cc, 0))
1718                               return 0;
1719                     (void)printf("Timestamp Reply");
1720                     break;
1721 
1722           case ICMP_IREQ:
1723                     if (!ck_pr_icmph(icp, from, cc, 0))
1724                               return 0;
1725                     (void)printf("Information Request");
1726                     break;
1727 
1728           case ICMP_IREQREPLY:
1729                     if (!ck_pr_icmph(icp, from, cc, 0))
1730                               return 0;
1731                     (void)printf("Information Reply");
1732                     break;
1733 
1734           case ICMP_MASKREQ:
1735                     if (!ck_pr_icmph(icp, from, cc, 0))
1736                               return 0;
1737                     (void)printf("Address Mask Request");
1738                     break;
1739 
1740           case ICMP_MASKREPLY:
1741                     if (!ck_pr_icmph(icp, from, cc, 0))
1742                               return 0;
1743                     (void)printf("Address Mask Reply");
1744                     break;
1745 
1746           default:
1747                     if (!ck_pr_icmph(icp, from, cc, 0))
1748                               return 0;
1749                     (void)printf("Bad ICMP type: %d", icp->icmp_type);
1750                     if (pingflags & F_VERBOSE)
1751                               pr_iph(icp, cc);
1752           }
1753 
1754           return 1;
1755 }
1756 
1757 
1758 /*
1759  *  Print an IP header with options.
1760  */
1761 static void
pr_iph(struct icmp * icp,int cc)1762 pr_iph(struct icmp *icp,
1763        int cc)
1764 {
1765           int       hlen;
1766           u_char    *cp;
1767           struct ip __aligned(4) ipb;
1768           struct ip *ip = &ipb;
1769 
1770           (void) memcpy(ip, icp->icmp_data, sizeof(*ip));
1771 
1772           hlen = ip->ip_hl << 2;
1773           cp = (u_char *) &icp->icmp_data[20];    /* point to options */
1774 
1775           (void)printf("\n Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src        Dst\n");
1776           (void)printf("  %1x  %1x  %02x %04x %04x",
1777                          ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
1778           (void)printf("   %1x %04x",
1779                          ((ip->ip_off)&0xe000)>>13, (ip->ip_off)&0x1fff);
1780           (void)printf("  %02x  %02x %04x",
1781                          ip->ip_ttl, ip->ip_p, ip->ip_sum);
1782           (void)printf(" %15s ",
1783                          inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
1784           (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
1785           /* dump any option bytes */
1786           while (hlen-- > 20 && cp < (u_char*)icp+cc) {
1787                     (void)printf("%02x", *cp++);
1788           }
1789 }
1790 
1791 /*
1792  * Print an ASCII host address starting from a string of bytes.
1793  */
1794 static void
pr_saddr(u_char * cp)1795 pr_saddr(u_char *cp)
1796 {
1797           n_long l;
1798           struct in_addr addr;
1799 
1800           l = (u_char)*++cp;
1801           l = (l<<8) + (u_char)*++cp;
1802           l = (l<<8) + (u_char)*++cp;
1803           l = (l<<8) + (u_char)*++cp;
1804           addr.s_addr = htonl(l);
1805           (void)printf("\t%s", (l == 0) ? "0.0.0.0" : pr_addr(&addr));
1806 }
1807 
1808 
1809 /*
1810  *  Return an ASCII host address
1811  *  as a dotted quad and optionally with a hostname
1812  */
1813 static char *
pr_addr(struct in_addr * addr)1814 pr_addr(struct in_addr *addr)           /* in network order */
1815 {
1816           struct    hostent   *hp;
1817           static    char buf[MAXHOSTNAMELEN+4+16+1];
1818 
1819           if ((pingflags & F_NUMERIC)
1820               || !(hp = gethostbyaddr((char *)addr, sizeof(*addr), AF_INET))) {
1821                     (void)snprintf(buf, sizeof(buf), "%s", inet_ntoa(*addr));
1822           } else {
1823                     (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name,
1824                         inet_ntoa(*addr));
1825           }
1826 
1827           return buf;
1828 }
1829 
1830 /*
1831  *  Dump some info on a returned (via ICMP) IP packet.
1832  */
1833 static void
pr_retip(struct icmp * icp,int cc)1834 pr_retip(struct icmp *icp,
1835            int cc)
1836 {
1837           int       hlen;
1838           u_char    *cp;
1839           struct ip ipb, *ip = &ipb;
1840 
1841           (void) memcpy(ip, icp->icmp_data, sizeof(*ip));
1842 
1843           if (pingflags & F_VERBOSE)
1844                     pr_iph(icp, cc);
1845 
1846           hlen = ip->ip_hl << 2;
1847           cp = (u_char *) &icp->icmp_data[hlen];
1848 
1849           if (ip->ip_p == IPPROTO_TCP) {
1850                     if (pingflags & F_VERBOSE)
1851                               (void)printf("\n  TCP: from port %u, to port %u",
1852                                              (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)));
1853           } else if (ip->ip_p == IPPROTO_UDP) {
1854                     if (pingflags & F_VERBOSE)
1855                               (void)printf("\n  UDP: from port %u, to port %u",
1856                                              (*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)));
1857           } else if (ip->ip_p == IPPROTO_ICMP) {
1858                     struct icmp icp2;
1859                     (void) memcpy(&icp2, cp, sizeof(icp2));
1860                     if (icp2.icmp_type == ICMP_ECHO) {
1861                               if (pingflags & F_VERBOSE)
1862                                         (void)printf("\n  ID=%u icmp_seq=%u",
1863                                                        ntohs((u_int16_t)icp2.icmp_id),
1864                                                        ntohs((u_int16_t)icp2.icmp_seq));
1865                               else
1866                                         (void)printf(" for icmp_seq=%u",
1867                                                        ntohs((u_int16_t)icp2.icmp_seq));
1868                     }
1869           }
1870 }
1871 
1872 static void
fill(void)1873 fill(void)
1874 {
1875           int i, j, k;
1876           char *cp;
1877           int pat[16];
1878 
1879           for (cp = fill_pat; *cp != '\0'; cp++) {
1880                     if (!isxdigit((unsigned char)*cp))
1881                               break;
1882           }
1883           if (cp == fill_pat || *cp != '\0' || (cp-fill_pat) > 16*2) {
1884                     (void)fflush(stdout);
1885                     errx(EXIT_FAILURE, "\"-p %s\": patterns must be specified with"
1886                          " 1-32 hex digits\n",
1887                          fill_pat);
1888           }
1889 
1890           i = sscanf(fill_pat,
1891                        "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1892                         &pat[0], &pat[1], &pat[2], &pat[3],
1893                         &pat[4], &pat[5], &pat[6], &pat[7],
1894                         &pat[8], &pat[9], &pat[10], &pat[11],
1895                         &pat[12], &pat[13], &pat[14], &pat[15]);
1896 
1897           for (k = phdrlen, j = 0; k < datalen; k++) {
1898                     opack_icmp.icmp_data[k] = pat[j];
1899                     if (++j >= i)
1900                               j = 0;
1901           }
1902 
1903           if (!(pingflags & F_QUIET)) {
1904                     (void)printf("PATTERN: 0x");
1905                     for (j=0; j<i; j++)
1906                               (void)printf("%02x",
1907                                              (u_char)opack_icmp.icmp_data[phdrlen + j]);
1908                     (void)printf("\n");
1909           }
1910 
1911 }
1912 
1913 
1914 static void
rnd_fill(void)1915 rnd_fill(void)
1916 {
1917           static u_int32_t rnd;
1918           int i;
1919 
1920           for (i = phdrlen; i < datalen; i++) {
1921                     rnd = (3141592621U * rnd + 663896637U);
1922                     opack_icmp.icmp_data[i] = rnd>>24;
1923           }
1924 }
1925 
1926 
1927 static void
gethost(const char * arg,const char * name,struct sockaddr_in * sa,char * realname,int realname_len)1928 gethost(const char *arg,
1929           const char *name,
1930           struct sockaddr_in *sa,
1931           char *realname,
1932           int realname_len)
1933 {
1934           struct hostent *hp;
1935 
1936           (void)memset(sa, 0, sizeof(*sa));
1937           sa->sin_family = AF_INET;
1938           sa->sin_len = sizeof(struct sockaddr_in);
1939 
1940           /* If it is an IP address, try to convert it to a name to
1941            * have something nice to display.
1942            */
1943           if (inet_aton(name, &sa->sin_addr) != 0) {
1944                     if (realname) {
1945                               if (pingflags & F_NUMERIC)
1946                                         hp = 0;
1947                               else
1948                                         hp = gethostbyaddr((char *)&sa->sin_addr,
1949                                             sizeof(sa->sin_addr), AF_INET);
1950                               (void)strlcpy(realname, hp ? hp->h_name : name,
1951                                   realname_len);
1952                     }
1953                     return;
1954           }
1955 
1956           hp = gethostbyname(name);
1957           if (!hp)
1958                     errx(EXIT_FAILURE, "Cannot resolve \"%s\" (%s)",
1959                         name, hstrerror(h_errno));
1960 
1961           if (hp->h_addrtype != AF_INET)
1962                     errx(EXIT_FAILURE, "%s only supported with IP", arg);
1963 
1964           (void)memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr));
1965 
1966           if (realname)
1967                     (void)strlcpy(realname, hp->h_name, realname_len);
1968 }
1969 
1970 
1971 static void
usage(void)1972 usage(void)
1973 {
1974 #ifdef IPSEC
1975 #ifdef IPSEC_POLICY_IPSEC
1976 #define IPSECOPT    "\n     [-E policy] "
1977 #else
1978 #define IPSECOPT    "\n     [-AE] "
1979 #endif /*IPSEC_POLICY_IPSEC*/
1980 #else
1981 #define IPSECOPT    ""
1982 #endif /*IPSEC*/
1983 
1984           (void)fprintf(stderr, "usage: \n"
1985               "%s [-aCDdfLnoPQqRrv] [-c count] [-g gateway] [-h host]"
1986               " [-I addr] [-i interval]\n"
1987               "     [-l preload] [-p pattern] [-s size] [-T ttl] [-t tos]"
1988               " [-w maxwait] " IPSECOPT "host\n",
1989               getprogname());
1990           exit(1);
1991 }
1992