1 /* $NetBSD: ping.c,v 1.109 2014/11/29 14:48:42 christos Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
38 * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
39 * measure round-trip-delays and packet loss across network paths.
43 * U. S. Army Ballistic Research Laboratory
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
52 * Public Domain. Distribution Unlimited.
55 * More statistics could always be gathered.
56 * This program has to run SUID to ROOT to access the ICMP socket.
59 #include <sys/cdefs.h>
61 __RCSID("$NetBSD: ping.c,v 1.109 2014/11/29 14:48:42 christos Exp $");
69 #include <sys/types.h>
70 #include <sys/param.h>
71 #include <sys/socket.h>
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>
92 #include <netipsec/ipsec.h>
97 #define FLOOD_INTVL 0.01 /* default flood output interval */
98 #define MAXPACKET (IP_MAXPACKET-60-8) /* max packet size */
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 */
118 #ifdef IPSEC_POLICY_IPSEC
119 #define F_POLICY 0x20000
121 #define F_AUTHHDR 0x20000
122 #define F_ENCRYPT 0x40000
123 #endif /*IPSEC_POLICY_IPSEC*/
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
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))
146 static u_char
*packet
;
148 static int pingflags
= 0, options
;
149 static int pongflags
= 0;
150 static char *fill_pat
;
152 static int s
; /* Socket file descriptor */
153 static int sloop
; /* Socket file descriptor/loopback */
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 */
164 static char *progname
;
165 #define getprogname() (progname)
166 #define setprogname(name) ((void)(progname = (name)))
169 static char hostname
[MAXHOSTNAMELEN
];
173 char o_opt
[MAX_IPOPTLEN
];
175 u_char u_buf
[MAXPACKET
+offsetof(struct icmp
, icmp_data
)];
179 #define opack_icmp out_pack.o_u.u_icmp
180 static struct ip
*opack_ip
;
182 static char optspace
[MAX_IPOPTLEN
]; /* record route space */
185 static int npackets
; /* total packets to send */
186 static int preload
; /* number of packets to "preload" */
187 static int ntransmitted
; /* output sequence # = #sent */
188 static int ident
; /* our ID, in network byte order */
190 static int nreceived
; /* # of packets we got back */
192 static double interval
; /* interval between packets */
193 static struct timespec interval_tv
;
194 static double tmin
= 999999999.0;
195 static double tmax
= 0.0;
196 static double tsum
= 0.0; /* sum of all times */
197 static double tsumsq
= 0.0;
198 static double maxwait
= 0.0;
200 static int bufspace
= IP_MAXPACKET
;
202 static struct timespec now
, clear_cache
, last_tx
, next_tx
, first_tx
;
203 static struct timespec last_rx
, first_rx
;
204 static int lastrcvd
= 1; /* last ping sent has been received */
206 static struct timespec jiggle_time
;
207 static int jiggle_cnt
, total_jiggled
, jiggle_direction
= -1;
209 __dead
static void doit(void);
210 static void prefinish(int);
211 static void prtsig(int);
212 __dead
static void finish(int);
213 static void summary(int);
214 static void pinger(void);
215 static void fill(void);
216 static void rnd_fill(void);
217 static double diffsec(struct timespec
*, struct timespec
*);
219 static void timespecadd(struct timespec
*, struct timespec
*);
221 static void sec_to_timespec(const double, struct timespec
*);
222 static double timespec_to_sec(const struct timespec
*);
223 static void pr_pack(u_char
*, int, struct sockaddr_in
*);
224 static u_int16_t
in_cksum(u_int16_t
*, u_int
);
225 static void pr_saddr(u_char
*);
226 static char *pr_addr(struct in_addr
*);
227 static void pr_iph(struct icmp
*, int);
228 static void pr_retip(struct icmp
*, int);
229 static int pr_icmph(struct icmp
*, struct sockaddr_in
*, int);
230 static void jiggle(int), jiggle_flush(int);
231 static void gethost(const char *, const char *,
232 struct sockaddr_in
*, char *, int);
233 __dead
static void usage(void);
236 main(int argc
, char *argv
[])
238 int c
, i
, on
= 1, hostind
= 0;
240 int len
= -1, compat
= 0;
245 #ifdef IPSEC_POLICY_IPSEC
246 char *policy_in
= NULL
;
247 char *policy_out
= NULL
;
254 if (prog_init
&& prog_init() == -1)
255 err(EXIT_FAILURE
, "init failed");
257 if ((s
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
258 err(EXIT_FAILURE
, "Cannot create socket");
259 if ((sloop
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
260 err(EXIT_FAILURE
, "Cannot create socket");
263 * sloop is never read on. This prevents packets from
264 * queueing in its recv buffer.
266 if (prog_shutdown(sloop
, SHUT_RD
) == -1)
267 warn("Cannot shutdown for read");
269 if (prog_setuid(prog_getuid()) == -1)
270 err(EXIT_FAILURE
, "setuid");
272 setprogname(argv
[0]);
277 #ifdef IPSEC_POLICY_IPSEC
278 #define IPSECOPT "E:"
280 #define IPSECOPT "AE"
281 #endif /*IPSEC_POLICY_IPSEC*/
283 while ((c
= getopt(argc
, argv
,
284 "ac:CdDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT
)) != -1) {
288 pingflags
|= F_AUDIBLE
;
294 npackets
= strtol(optarg
, &p
, 0);
295 if (*p
!= '\0' || npackets
<= 0)
297 "Bad/invalid number of packets: %s",
307 pingflags
|= F_FLOOD
;
312 case 'i': /* wait between sending packets */
313 interval
= strtod(optarg
, &p
);
314 if (*p
!= '\0' || interval
<= 0)
315 errx(EXIT_FAILURE
, "Bad/invalid interval: %s",
319 preload
= strtol(optarg
, &p
, 0);
320 if (*p
!= '\0' || preload
< 0)
321 errx(EXIT_FAILURE
, "Bad/invalid preload value: "
325 pingflags
|= F_NUMERIC
;
330 case 'p': /* fill buffer with user pattern */
331 if (pingflags
& F_PING_RANDOM
)
333 "Only one of -P and -p allowed");
334 pingflags
|= F_PING_FILLED
;
338 if (pingflags
& F_PING_FILLED
)
340 "Only one of -P and -p allowed");
341 pingflags
|= F_PING_RANDOM
;
344 pingflags
|= F_QUIET
;
347 pingflags
|= F_SEMI_QUIET
;
350 options
|= SO_DONTROUTE
;
352 case 's': /* size of packet to send */
353 l
= strtol(optarg
, &p
, 0);
354 if (*p
!= '\0' || l
< 0)
356 "Bad/invalid packet size: %s", optarg
);
358 errx(EXIT_FAILURE
, "packet size is too large");
362 pingflags
|= F_VERBOSE
;
365 pingflags
|= F_RECORD_ROUTE
;
368 pingflags
|= F_MCAST_NOLOOP
;
371 tos
= strtoul(optarg
, &p
, 0);
372 if (*p
!= '\0' || tos
> 0xFF)
373 errx(EXIT_FAILURE
, "bad tos value: %s", optarg
);
376 l
= strtol(optarg
, &p
, 0);
377 if (*p
!= '\0' || l
> 255 || l
<= 0)
378 errx(EXIT_FAILURE
, "ttl out of range: %s",
380 ttl
= (u_char
)l
; /* cannot check >255 otherwise */
383 pingflags
|= F_SOURCE_ADDR
;
384 gethost("-I", optarg
, &src_addr
, 0, 0);
387 pingflags
|= F_SOURCE_ROUTE
;
388 gethost("-g", optarg
, &send_addr
, 0, 0);
391 maxwait
= strtod(optarg
, &p
);
392 if (*p
!= '\0' || maxwait
<= 0)
393 errx(EXIT_FAILURE
, "Bad/invalid maxwait time: "
397 #ifdef IPSEC_POLICY_IPSEC
399 pingflags
|= F_POLICY
;
400 if (!strncmp("in", optarg
, 2)) {
401 policy_in
= strdup(optarg
);
403 err(EXIT_FAILURE
, "strdup");
404 } else if (!strncmp("out", optarg
, 3)) {
405 policy_out
= strdup(optarg
);
407 err(EXIT_FAILURE
, "strdup");
409 errx(EXIT_FAILURE
, "invalid security policy: "
414 pingflags
|= F_AUTHHDR
;
417 pingflags
|= F_ENCRYPT
;
419 #endif /*IPSEC_POLICY_IPSEC*/
428 interval
= (pingflags
& F_FLOOD
) ? FLOOD_INTVL
: 1.0;
430 if (pingflags
& F_FLOOD
&& prog_getuid())
431 errx(EXIT_FAILURE
, "Must be superuser to use -f");
432 if (interval
< 1.0 && prog_getuid())
433 errx(EXIT_FAILURE
, "Must be superuser to use < 1 sec "
435 if (preload
> 0 && prog_getuid())
436 errx(EXIT_FAILURE
, "Must be superuser to use -l");
438 sec_to_timespec(interval
, &interval_tv
);
440 if ((pingflags
& (F_AUDIBLE
|F_FLOOD
)) == (F_AUDIBLE
|F_FLOOD
))
441 warnx("Sorry, no audible output for flood pings");
450 if (optind
!= argc
-1)
455 else if (hostind
>= argc
- 1)
458 gethost("", argv
[hostind
], &whereto
, hostname
, sizeof(hostname
));
459 if (IN_MULTICAST(ntohl(whereto
.sin_addr
.s_addr
)))
460 pingflags
|= F_MCAST
;
461 if (!(pingflags
& F_SOURCE_ROUTE
))
462 (void) memcpy(&send_addr
, &whereto
, sizeof(send_addr
));
464 loc_addr
.sin_family
= AF_INET
;
465 loc_addr
.sin_len
= sizeof(struct sockaddr_in
);
466 loc_addr
.sin_addr
.s_addr
= htonl((127 << 24) + 1);
471 datalen
= 64 - PHDR_LEN
;
472 if (!compat
&& datalen
>= (int)PHDR64_LEN
) { /* can we time them? */
473 pingflags
|= F_TIMING64
;
474 phdrlen
= PHDR64_LEN
;
475 } else if (datalen
>= (int)PHDR_LEN
) { /* can we time them? */
476 pingflags
|= F_TIMING
;
481 packlen
= datalen
+ 60 + 76; /* MAXIP + MAXICMP */
482 if ((packet
= malloc(packlen
)) == NULL
)
483 err(EXIT_FAILURE
, "Can't allocate %d bytes", packlen
);
485 if (pingflags
& F_PING_FILLED
) {
487 } else if (pingflags
& F_PING_RANDOM
) {
490 for (i
= phdrlen
; i
< datalen
; i
++)
491 opack_icmp
.icmp_data
[i
] = i
;
494 ident
= arc4random() & 0xFFFF;
496 if (options
& SO_DEBUG
) {
497 if (prog_setsockopt(s
, SOL_SOCKET
, SO_DEBUG
,
498 (char *)&on
, sizeof(on
)) == -1)
499 warn("Can't turn on socket debugging");
501 if (options
& SO_DONTROUTE
) {
502 if (prog_setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
,
503 (char *)&on
, sizeof(on
)) == -1)
504 warn("SO_DONTROUTE");
507 if (options
& SO_DEBUG
) {
508 if (prog_setsockopt(sloop
, SOL_SOCKET
, SO_DEBUG
,
509 (char *)&on
, sizeof(on
)) == -1)
510 warn("Can't turn on socket debugging");
512 if (options
& SO_DONTROUTE
) {
513 if (prog_setsockopt(sloop
, SOL_SOCKET
, SO_DONTROUTE
,
514 (char *)&on
, sizeof(on
)) == -1)
515 warn("SO_DONTROUTE");
518 if (pingflags
& F_SOURCE_ROUTE
) {
519 optspace
[IPOPT_OPTVAL
] = IPOPT_LSRR
;
520 optspace
[IPOPT_OLEN
] = optlen
= 7;
521 optspace
[IPOPT_OFFSET
] = IPOPT_MINOFF
;
522 (void)memcpy(&optspace
[IPOPT_MINOFF
-1], &whereto
.sin_addr
,
523 sizeof(whereto
.sin_addr
));
524 optspace
[optlen
++] = IPOPT_NOP
;
526 if (pingflags
& F_RECORD_ROUTE
) {
527 optspace
[optlen
+IPOPT_OPTVAL
] = IPOPT_RR
;
528 optspace
[optlen
+IPOPT_OLEN
] = (MAX_IPOPTLEN
-1-optlen
);
529 optspace
[optlen
+IPOPT_OFFSET
] = IPOPT_MINOFF
;
530 optlen
= MAX_IPOPTLEN
;
532 /* this leaves opack_ip 0(mod 4) aligned */
533 opack_ip
= (struct ip
*)((char *)&out_pack
.o_ip
534 + sizeof(out_pack
.o_opt
)
536 (void) memcpy(opack_ip
+ 1, optspace
, optlen
);
538 if (prog_setsockopt(s
, IPPROTO_IP
, IP_HDRINCL
,
539 (char *) &on
, sizeof(on
)) < 0)
540 err(EXIT_FAILURE
, "Can't set special IP header");
542 opack_ip
->ip_v
= IPVERSION
;
543 opack_ip
->ip_hl
= (sizeof(struct ip
)+optlen
) >> 2;
544 opack_ip
->ip_tos
= tos
;
545 opack_ip
->ip_off
= (pingflags
& F_DF
) ? IP_DF
: 0;
546 opack_ip
->ip_ttl
= ttl
? ttl
: MAXTTL
;
547 opack_ip
->ip_p
= IPPROTO_ICMP
;
548 opack_ip
->ip_src
= src_addr
.sin_addr
;
549 opack_ip
->ip_dst
= send_addr
.sin_addr
;
551 if (pingflags
& F_MCAST
) {
552 if (pingflags
& F_MCAST_NOLOOP
) {
554 if (prog_setsockopt(s
, IPPROTO_IP
,
556 (char *) &loop
, 1) < 0)
557 err(EXIT_FAILURE
, "Can't disable multicast loopback");
561 && prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_TTL
,
562 (char *) &ttl
, 1) < 0)
563 err(EXIT_FAILURE
, "Can't set multicast time-to-live");
565 if ((pingflags
& F_SOURCE_ADDR
)
566 && prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
,
567 (char *) &src_addr
.sin_addr
,
568 sizeof(src_addr
.sin_addr
)) < 0)
569 err(EXIT_FAILURE
, "Can't set multicast source interface");
571 } else if (pingflags
& F_SOURCE_ADDR
) {
572 if (prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
,
573 (char *) &src_addr
.sin_addr
,
574 sizeof(src_addr
.sin_addr
)) < 0)
575 err(EXIT_FAILURE
, "Can't set source interface/address");
578 #ifdef IPSEC_POLICY_IPSEC
581 if (pingflags
& F_POLICY
) {
582 if (policy_in
!= NULL
) {
583 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
585 errx(EXIT_FAILURE
, "%s", ipsec_strerror());
586 if (prog_setsockopt(s
, IPPROTO_IP
, IP_IPSEC_POLICY
,
587 buf
, ipsec_get_policylen(buf
)) < 0) {
588 err(EXIT_FAILURE
, "ipsec policy cannot be "
593 if (policy_out
!= NULL
) {
594 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
596 errx(EXIT_FAILURE
, "%s", ipsec_strerror());
597 if (prog_setsockopt(s
, IPPROTO_IP
, IP_IPSEC_POLICY
,
598 buf
, ipsec_get_policylen(buf
)) < 0) {
599 err(EXIT_FAILURE
, "ipsec policy cannot be "
605 buf
= ipsec_set_policy("out bypass", strlen("out bypass"));
607 errx(EXIT_FAILURE
, "%s", ipsec_strerror());
608 if (prog_setsockopt(sloop
, IPPROTO_IP
, IP_IPSEC_POLICY
,
609 buf
, ipsec_get_policylen(buf
)) < 0) {
611 warnx("ipsec is not configured");
613 /* ignore it, should be okay */
621 if (pingflags
& F_AUTHHDR
) {
622 optval
= IPSEC_LEVEL_REQUIRE
;
623 #ifdef IP_AUTH_TRANS_LEVEL
624 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
,
625 (char *)&optval
, sizeof(optval
));
627 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_LEVEL
,
628 (char *)&optval
, sizeof(optval
));
631 if (pingflags
& F_ENCRYPT
) {
632 optval
= IPSEC_LEVEL_REQUIRE
;
633 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
,
634 (char *)&optval
, sizeof(optval
));
636 optval
= IPSEC_LEVEL_BYPASS
;
637 #ifdef IP_AUTH_TRANS_LEVEL
638 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
,
639 (char *)&optval
, sizeof(optval
));
641 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_AUTH_LEVEL
,
642 (char *)&optval
, sizeof(optval
));
644 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
,
645 (char *)&optval
, sizeof(optval
));
647 #endif /*IPSEC_POLICY_IPSEC*/
650 (void)printf("PING %s (%s): %d data bytes\n", hostname
,
651 inet_ntoa(whereto
.sin_addr
), datalen
);
653 /* When pinging the broadcast address, you can get a lot
654 * of answers. Doing something so evil is useful if you
655 * are trying to stress the ethernet, or just want to
656 * fill the arp cache to get some stuff for /etc/ethers.
658 while (0 > prog_setsockopt(s
, SOL_SOCKET
, SO_RCVBUF
,
659 (char*)&bufspace
, sizeof(bufspace
))) {
660 if ((bufspace
-= 4096) <= 0)
661 err(EXIT_FAILURE
, "Cannot set the receive buffer size");
664 /* make it possible to send giant probes, but do not worry now
665 * if it fails, since we probably won't send giant probes.
667 (void)prog_setsockopt(s
, SOL_SOCKET
, SO_SNDBUF
,
668 (char*)&bufspace
, sizeof(bufspace
));
670 (void)signal(SIGINT
, prefinish
);
673 sa
.sa_handler
= prtsig
;
674 sa
.sa_flags
= SA_NOKERNINFO
;
675 sigemptyset(&sa
.sa_mask
);
676 (void)sigaction(SIGINFO
, &sa
, NULL
);
678 (void)signal(SIGQUIT
, prtsig
);
680 (void)signal(SIGCONT
, prtsig
);
682 /* fire off them quickies */
683 for (i
= 0; i
< preload
; i
++) {
684 clock_gettime(CLOCK_MONOTONIC
, &now
);
697 struct sockaddr_in from
;
699 double sec
, last
, d_last
;
700 struct pollfd fdmaskp
[1];
702 (void)clock_gettime(CLOCK_MONOTONIC
, &clear_cache
);
704 last
= timespec_to_sec(&clear_cache
) + maxwait
;
708 d_last
= 365*24*60*60;
712 clock_gettime(CLOCK_MONOTONIC
, &now
);
715 d_last
= last
- timespec_to_sec(&now
);
717 if (ntransmitted
< npackets
&& d_last
> 0) {
718 /* send if within 100 usec or late for next packet */
719 sec
= diffsec(&next_tx
, &now
);
721 (lastrcvd
&& (pingflags
& F_FLOOD
))) {
723 sec
= diffsec(&next_tx
, &now
);
731 /* For the last response, wait twice as long as the
732 * worst case seen, or 10 times as long as the
733 * maximum interpacket interval, whichever is longer.
735 sec
= MAX(2 * tmax
, 10 * interval
) -
736 diffsec(&now
, &last_tx
);
744 fdmaskp
[0].events
= POLLIN
;
745 cc
= prog_poll(fdmaskp
, 1, (int)(sec
* 1000));
751 err(EXIT_FAILURE
, "poll");
756 fromlen
= sizeof(from
);
757 cc
= prog_recvfrom(s
, (char *) packet
, packlen
,
758 0, (struct sockaddr
*)&from
,
761 if (errno
!= EINTR
) {
764 (void)fflush(stderr
);
768 clock_gettime(CLOCK_MONOTONIC
, &now
);
769 pr_pack(packet
, cc
, &from
);
771 } while (nreceived
< npackets
772 && (nreceived
== 0 || !(pingflags
& F_ONCE
)));
779 jiggle_flush(int nl
) /* new line if there are dots */
783 if (jiggle_cnt
> 0) {
784 total_jiggled
+= jiggle_cnt
;
785 jiggle_direction
= 1;
788 } while (--jiggle_cnt
> 0);
790 } else if (jiggle_cnt
< 0) {
791 total_jiggled
-= jiggle_cnt
;
792 jiggle_direction
= -1;
795 } while (++jiggle_cnt
< 0);
799 if (total_jiggled
!= 0)
802 jiggle_direction
= -1;
805 (void)fflush(stdout
);
806 (void)fflush(stderr
);
812 /* jiggle the cursor for flood-ping
819 if (pingflags
& F_QUIET
)
822 /* do not back up into messages */
823 if (total_jiggled
+jiggle_cnt
+delta
< 0)
828 /* flush the FLOOD dots when things are quiet
829 * or occassionally to make the cursor jiggle.
831 dt
= diffsec(&last_tx
, &jiggle_time
);
832 if (dt
> 0.2 || (dt
>= 0.15 && delta
*jiggle_direction
< 0))
838 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
839 * will be added on by the kernel. The ID field is our UNIX process ID,
840 * and the sequence number is an ascending integer. The first phdrlen bytes
841 * of the data portion are used to hold a UNIX "timeval" struct in VAX
842 * byte-order, to compute the round-trip time, or a UNIX "timespec" in native
849 #if !defined(__minix)
853 #endif /* !defined(__minix) */
855 opack_icmp
.icmp_code
= 0;
856 opack_icmp
.icmp_seq
= htons((u_int16_t
)(ntransmitted
));
858 #if !defined(__minix)
859 /* clear the cached route in the kernel after an ICMP
860 * response such as a Redirect is seen to stop causing
861 * more such packets. Also clear the cached route
862 * periodically in case of routing changes that make
863 * black holes come and go.
865 if (clear_cache
.tv_sec
!= now
.tv_sec
) {
866 opack_icmp
.icmp_type
= ICMP_ECHOREPLY
;
867 opack_icmp
.icmp_id
= ~ident
;
868 opack_icmp
.icmp_cksum
= 0;
869 opack_icmp
.icmp_cksum
= in_cksum((u_int16_t
*)&opack_icmp
,
872 if (prog_setsockopt(sloop
, IPPROTO_IP
, IP_HDRINCL
,
873 (char *)&sw
, sizeof(sw
)) < 0)
874 err(EXIT_FAILURE
, "Can't turn off special IP header");
875 if (prog_sendto(sloop
, (char *) &opack_icmp
,
876 ICMP_MINLEN
, MSG_DONTROUTE
,
877 (struct sockaddr
*)&loc_addr
,
878 sizeof(struct sockaddr_in
)) < 0) {
880 * XXX: we only report this as a warning in verbose
881 * mode because people get confused when they see
882 * this error when they are running in single user
883 * mode and they have not configured lo0
885 if (pingflags
& F_VERBOSE
)
886 warn("failed to clear cached route");
889 if (prog_setsockopt(sloop
, IPPROTO_IP
, IP_HDRINCL
,
890 (char *)&sw
, sizeof(sw
)) < 0)
891 err(EXIT_FAILURE
, "Can't set special IP header");
893 (void)clock_gettime(CLOCK_MONOTONIC
, &clear_cache
);
895 #endif /* !defined(__minix) */
897 opack_icmp
.icmp_type
= ICMP_ECHO
;
898 opack_icmp
.icmp_id
= ident
;
900 if (pingflags
& F_TIMING
) {
901 tv32
.tv32_sec
= (uint32_t)htonl(now
.tv_sec
);
902 tv32
.tv32_usec
= htonl(now
.tv_nsec
/ 1000);
903 (void) memcpy(&opack_icmp
.icmp_data
[0], &tv32
, sizeof(tv32
));
904 } else if (pingflags
& F_TIMING64
)
905 (void) memcpy(&opack_icmp
.icmp_data
[0], &now
, sizeof(now
));
907 cc
= MAX(datalen
, ICMP_MINLEN
) + PHDR_LEN
;
908 opack_icmp
.icmp_cksum
= 0;
909 opack_icmp
.icmp_cksum
= in_cksum((u_int16_t
*)&opack_icmp
, cc
);
911 cc
+= opack_ip
->ip_hl
<<2;
912 opack_ip
->ip_len
= cc
;
913 i
= prog_sendto(s
, (char *) opack_ip
, cc
, 0,
914 (struct sockaddr
*)&send_addr
, sizeof(struct sockaddr_in
));
920 warnx("wrote %s %d chars, ret=%d", hostname
, cc
, i
);
921 (void)fflush(stderr
);
929 if (next_tx
.tv_sec
== 0) {
934 /* Transmit regularly, at always the same microsecond in the
935 * second when going at one packet per second.
936 * If we are at most 100 ms behind, send extras to get caught up.
937 * Otherwise, skip packets we were too slow to send.
939 if (diffsec(&next_tx
, &now
) <= interval
) {
941 timespecadd(&next_tx
, &interval_tv
, &next_tx
);
942 } while (diffsec(&next_tx
, &now
) < -0.1);
945 if (pingflags
& F_FLOOD
)
948 /* While the packet is going out, ready buffer for the next
949 * packet. Use a fast but not very good random number generator.
951 if (pingflags
& F_PING_RANDOM
)
966 if (pingflags
& F_FLOOD
)
969 (void)printf("%d bytes from %s: icmp_seq=%u", cc
, addr
, seqno
);
971 (void)printf(" DUP!");
972 (void)printf(" ttl=%d", ttl
);
973 if (pingflags
& (F_TIMING
|F_TIMING64
)) {
974 const unsigned int prec
= (pingflags
& F_TIMING64
) != 0 ? 6 : 3;
976 (void)printf(" time=%.*f ms", prec
, triptime
*1000.0);
980 * Send beep to stderr, since that's more likely than stdout
981 * to go to a terminal..
983 if (pingflags
& F_AUDIBLE
&& !dupflag
)
984 (void)fprintf(stderr
,"\a");
989 * Print out the packet, if it came from us. This logic is necessary
990 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
991 * which arrive ('tis only fair). This permits multiple copies of this
992 * program to be run without having intermingled output (or statistics!).
997 struct sockaddr_in
*from
)
1003 static int old_rrlen
;
1004 static char old_rr
[MAX_IPOPTLEN
];
1005 int hlen
, dupflag
= 0, dumped
;
1006 double triptime
= 0.0;
1007 #define PR_PACK_SUB() {if (!dumped) { \
1009 pr_pack_sub(net_len, inet_ntoa(from->sin_addr), \
1010 ntohs((u_int16_t)icp->icmp_seq), \
1011 dupflag, ip->ip_ttl, triptime);}}
1013 /* Check the IP header */
1014 ip
= (struct ip
*) buf
;
1015 hlen
= ip
->ip_hl
<< 2;
1016 if (tot_len
< hlen
+ ICMP_MINLEN
) {
1017 if (pingflags
& F_VERBOSE
) {
1019 (void)printf("packet too short (%d bytes) from %s\n",
1020 tot_len
, inet_ntoa(from
->sin_addr
));
1025 /* Now the ICMP part */
1027 net_len
= tot_len
- hlen
;
1028 icp
= (struct icmp
*)(buf
+ hlen
);
1029 if (icp
->icmp_type
== ICMP_ECHOREPLY
1030 && icp
->icmp_id
== ident
) {
1032 if (icp
->icmp_seq
== htons((u_int16_t
)(ntransmitted
-1)))
1035 if (first_rx
.tv_sec
== 0)
1038 if (pingflags
& (F_TIMING
|F_TIMING64
)) {
1041 if (pingflags
& F_TIMING
) {
1044 (void)memcpy(&tv32
, icp
->icmp_data
, sizeof(tv32
));
1045 tv
.tv_sec
= (uint32_t)ntohl(tv32
.tv32_sec
);
1046 tv
.tv_nsec
= ntohl(tv32
.tv32_usec
) * 1000;
1047 } else if (pingflags
& F_TIMING64
)
1048 (void)memcpy(&tv
, icp
->icmp_data
, sizeof(tv
));
1050 memset(&tv
, 0, sizeof(tv
)); /* XXX: gcc */
1052 triptime
= diffsec(&last_rx
, &tv
);
1054 tsumsq
+= triptime
* triptime
;
1055 if (triptime
< tmin
)
1057 if (triptime
> tmax
)
1061 if (TST(ntohs((u_int16_t
)icp
->icmp_seq
))) {
1062 nrepeats
++, nreceived
--;
1065 SET(ntohs((u_int16_t
)icp
->icmp_seq
));
1068 if (tot_len
!= opack_ip
->ip_len
) {
1070 switch (opack_ip
->ip_len
- tot_len
) {
1072 if ((pongflags
& F_RECORD_ROUTE
) != 0)
1074 if ((pingflags
& F_RECORD_ROUTE
) == 0)
1076 pongflags
|= F_RECORD_ROUTE
;
1077 (void)printf("\nremote host does not "
1078 "support record route");
1081 if ((pongflags
& F_SOURCE_ROUTE
) != 0)
1083 if ((pingflags
& F_SOURCE_ROUTE
) == 0)
1085 pongflags
|= F_SOURCE_ROUTE
;
1086 (void)printf("\nremote host does not "
1087 "support source route");
1091 (void)printf("\nwrong total length %d "
1092 "instead of %d", tot_len
, opack_ip
->ip_len
);
1098 static u_int16_t last_seqno
= 0xffff;
1099 u_int16_t seqno
= ntohs((u_int16_t
)icp
->icmp_seq
);
1100 u_int16_t gap
= seqno
- (last_seqno
+ 1);
1101 if (gap
> 0 && gap
< 0x8000 &&
1102 (pingflags
& F_VERBOSE
)) {
1103 (void)printf("[*** sequence gap of %u "
1104 "packets from %u ... %u ***]\n", gap
,
1105 (u_int16_t
) (last_seqno
+ 1),
1106 (u_int16_t
) (seqno
- 1));
1107 if (pingflags
& F_QUIET
)
1115 if (pingflags
& F_QUIET
)
1118 if (!(pingflags
& F_FLOOD
))
1121 /* check the data */
1122 if ((size_t)(tot_len
- hlen
) >
1123 offsetof(struct icmp
, icmp_data
) + datalen
1124 && !(pingflags
& F_PING_RANDOM
)
1125 && memcmp(icp
->icmp_data
+ phdrlen
,
1126 opack_icmp
.icmp_data
+ phdrlen
,
1127 datalen
- phdrlen
)) {
1128 for (i
= phdrlen
; i
< datalen
; i
++) {
1129 if (icp
->icmp_data
[i
] !=
1130 opack_icmp
.icmp_data
[i
])
1134 (void)printf("\nwrong data byte #%d should have been"
1135 " %#x but was %#x", i
- phdrlen
,
1136 (u_char
)opack_icmp
.icmp_data
[i
],
1137 (u_char
)icp
->icmp_data
[i
]);
1138 for (i
= phdrlen
; i
< datalen
; i
++) {
1140 (void)printf("\n\t");
1141 (void)printf("%2x ",(u_char
)icp
->icmp_data
[i
]);
1146 if (!pr_icmph(icp
, from
, net_len
))
1151 /* Display any IP options */
1152 cp
= buf
+ sizeof(struct ip
);
1153 while (hlen
> (int)sizeof(struct ip
)) {
1172 (void)printf("\nLSRR: ");
1180 (void)putchar('\n');
1184 j
= *++cp
; /* get length */
1185 i
= *++cp
; /* and pointer */
1194 && !memcmp(cp
, old_rr
, i
)) {
1196 (void)printf("\t(same route)");
1203 (void) memcpy(old_rr
, cp
, i
);
1207 (void)printf("RR: ");
1210 (void)printf("\nRR: ");
1219 (void)putchar('\n');
1226 (void)printf("\nNOP");
1229 case IPOPT_SECURITY
: /* RFC 1108 RIPSO BSO */
1230 case IPOPT_ESO
: /* RFC 1108 RIPSO ESO */
1231 case IPOPT_CIPSO
: /* Commercial IPSO */
1232 if ((sysconf(_SC_IP_SECOPTS
)) > 0) {
1233 i
= (unsigned)cp
[1];
1236 (void)printf("\nSEC:");
1238 (void)printf(" %02x", *cp
++);
1246 (void)printf("\nunknown option 0x%x", *cp
);
1254 (void)putchar('\n');
1255 (void)fflush(stdout
);
1262 /* Compute the IP checksum
1263 * This assumes the packet is less than 32K long.
1266 in_cksum(u_int16_t
*p
, u_int len
)
1269 int nwords
= len
>> 1;
1271 while (nwords
-- != 0)
1279 u
.c
[0] = *(u_char
*)p
;
1284 /* end-around-carry */
1285 sum
= (sum
>> 16) + (sum
& 0xffff);
1292 * compute the difference of two timespecs in seconds
1295 diffsec(struct timespec
*timenow
,
1296 struct timespec
*then
)
1298 if (timenow
->tv_sec
== 0)
1300 return (timenow
->tv_sec
- then
->tv_sec
)
1301 * 1.0 + (timenow
->tv_nsec
- then
->tv_nsec
) / 1000000000.0;
1307 timespecadd(struct timespec
*t1
,
1308 struct timespec
*t2
)
1311 t1
->tv_sec
+= t2
->tv_sec
;
1312 if ((t1
->tv_nsec
+= t2
->tv_nsec
) >= 1000000000) {
1314 t1
->tv_nsec
-= 1000000000;
1321 sec_to_timespec(const double sec
, struct timespec
*tp
)
1324 tp
->tv_nsec
= (sec
- tp
->tv_sec
) * 1000000000.0;
1329 timespec_to_sec(const struct timespec
*tp
)
1331 return tp
->tv_sec
+ tp
->tv_nsec
/ 1000000000.0;
1337 * Heavily buffered STDIO is used here, so that all the statistics
1338 * will be written with 1 sys-write call. This is nice when more
1339 * than one copy of the program is running on a terminal; it prevents
1340 * the statistics output from becomming intermingled.
1348 (void)printf("\n----%s PING Statistics----\n", hostname
);
1349 (void)printf("%d packets transmitted, ", ntransmitted
);
1350 (void)printf("%d packets received, ", nreceived
);
1352 (void)printf("+%d duplicates, ", nrepeats
);
1354 if (nreceived
> ntransmitted
)
1355 (void)printf("-- somebody's duplicating packets!");
1357 (void)printf("%.1f%% packet loss",
1358 (((ntransmitted
-nreceived
)*100.0) /
1362 if (nreceived
&& (pingflags
& (F_TIMING
|F_TIMING64
))) {
1363 double n
= nreceived
+ nrepeats
;
1364 double avg
= (tsum
/ n
);
1365 double variance
= 0.0;
1366 const unsigned int prec
= (pingflags
& F_TIMING64
) != 0 ? 6 : 3;
1368 variance
= (tsumsq
- n
*avg
*avg
) /(n
-1);
1370 (void)printf("round-trip min/avg/max/stddev = "
1371 "%.*f/%.*f/%.*f/%.*f ms\n",
1372 prec
, tmin
* 1000.0,
1374 prec
, tmax
* 1000.0,
1375 prec
, sqrt(variance
) * 1000.0);
1376 if (pingflags
& F_FLOOD
) {
1377 double r
= diffsec(&last_rx
, &first_rx
);
1378 double t
= diffsec(&last_tx
, &first_tx
);
1383 (void)printf(" %.1f packets/sec sent, "
1384 " %.1f packets/sec received\n",
1385 ntransmitted
/t
, nreceived
/r
);
1392 * Print statistics when SIGINFO is received.
1401 (void)signal(SIGQUIT
, prtsig
);
1407 * On the first SIGINT, allow any outstanding packets to dribble in
1410 prefinish(int dummy
)
1412 if (lastrcvd
/* quit now if caught up */
1413 || nreceived
== 0) /* or if remote is dead */
1416 (void)signal(dummy
, finish
); /* do this only the 1st time */
1418 if (npackets
> ntransmitted
) /* let the normal limit work */
1419 npackets
= ntransmitted
;
1423 * Print statistics and give up.
1430 (void)signal(SIGINFO
, SIG_DFL
);
1432 (void)signal(SIGQUIT
, SIG_DFL
);
1436 exit(nreceived
> 0 ? 0 : 2);
1440 static int /* 0=do not print it */
1441 ck_pr_icmph(struct icmp
*icp
,
1442 struct sockaddr_in
*from
,
1444 int override
) /* 1=override VERBOSE if interesting */
1447 struct ip ipb
, *ip
= &ipb
;
1448 struct icmp icp2b
, *icp2
= &icp2b
;
1451 if (pingflags
& F_VERBOSE
) {
1458 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1459 hlen
= ip
->ip_hl
<< 2;
1460 if (ip
->ip_p
== IPPROTO_ICMP
1461 && hlen
+ 6 <= cc
) {
1462 (void) memcpy(icp2
, &icp
->icmp_data
[hlen
], sizeof(*icp2
));
1463 if (icp2
->icmp_id
== ident
) {
1464 /* remember to clear route cached in kernel
1465 * if this non-Echo-Reply ICMP message was for one
1468 clear_cache
.tv_sec
= 0;
1470 if (!res
&& override
1471 && (pingflags
& (F_QUIET
|F_SEMI_QUIET
)) == 0) {
1473 (void)printf("%d bytes from %s: ",
1474 cc
, pr_addr(&from
->sin_addr
));
1485 * Print a descriptive string about an ICMP header other than an echo reply.
1487 static int /* 0=printed nothing */
1488 pr_icmph(struct icmp
*icp
,
1489 struct sockaddr_in
*from
,
1492 switch (icp
->icmp_type
) {
1494 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1496 switch (icp
->icmp_code
) {
1497 case ICMP_UNREACH_NET
:
1498 (void)printf("Destination Net Unreachable");
1500 case ICMP_UNREACH_HOST
:
1501 (void)printf("Destination Host Unreachable");
1503 case ICMP_UNREACH_PROTOCOL
:
1504 (void)printf("Destination Protocol Unreachable");
1506 case ICMP_UNREACH_PORT
:
1507 (void)printf("Destination Port Unreachable");
1509 case ICMP_UNREACH_NEEDFRAG
:
1510 (void)printf("frag needed and DF set. Next MTU=%d",
1511 ntohs(icp
->icmp_nextmtu
));
1513 case ICMP_UNREACH_SRCFAIL
:
1514 (void)printf("Source Route Failed");
1516 case ICMP_UNREACH_NET_UNKNOWN
:
1517 (void)printf("Unreachable unknown net");
1519 case ICMP_UNREACH_HOST_UNKNOWN
:
1520 (void)printf("Unreachable unknown host");
1522 case ICMP_UNREACH_ISOLATED
:
1523 (void)printf("Unreachable host isolated");
1525 case ICMP_UNREACH_NET_PROHIB
:
1526 (void)printf("Net prohibited access");
1528 case ICMP_UNREACH_HOST_PROHIB
:
1529 (void)printf("Host prohibited access");
1531 case ICMP_UNREACH_TOSNET
:
1532 (void)printf("Bad TOS for net");
1534 case ICMP_UNREACH_TOSHOST
:
1535 (void)printf("Bad TOS for host");
1538 (void)printf("Communication prohibited");
1541 (void)printf("Host precedence violation");
1544 (void)printf("Precedence cutoff");
1547 (void)printf("Bad Destination Unreachable Code: %d",
1551 /* Print returned IP header information */
1555 case ICMP_SOURCEQUENCH
:
1556 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1558 (void)printf("Source Quench");
1563 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1565 switch (icp
->icmp_code
) {
1566 case ICMP_REDIRECT_NET
:
1567 (void)printf("Redirect Network");
1569 case ICMP_REDIRECT_HOST
:
1570 (void)printf("Redirect Host");
1572 case ICMP_REDIRECT_TOSNET
:
1573 (void)printf("Redirect Type of Service and Network");
1575 case ICMP_REDIRECT_TOSHOST
:
1576 (void)printf("Redirect Type of Service and Host");
1579 (void)printf("Redirect--Bad Code: %d", icp
->icmp_code
);
1582 (void)printf(" New router addr: %s",
1583 pr_addr(&icp
->icmp_hun
.ih_gwaddr
));
1588 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1590 (void)printf("Echo Request: ID=%d seq=%d",
1591 ntohs(icp
->icmp_id
), ntohs(icp
->icmp_seq
));
1594 case ICMP_ECHOREPLY
:
1595 /* displaying other's pings is too noisey */
1597 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1599 (void)printf("Echo Reply: ID=%d seq=%d",
1600 ntohs(icp
->icmp_id
), ntohs(icp
->icmp_seq
));
1606 case ICMP_ROUTERADVERT
:
1607 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1609 (void)printf("Router Discovery Advert");
1612 case ICMP_ROUTERSOLICIT
:
1613 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1615 (void)printf("Router Discovery Solicit");
1619 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1621 switch (icp
->icmp_code
) {
1622 case ICMP_TIMXCEED_INTRANS
:
1623 (void)printf("Time To Live exceeded");
1625 case ICMP_TIMXCEED_REASS
:
1626 (void)printf("Frag reassembly time exceeded");
1629 (void)printf("Time exceeded, Bad Code: %d",
1636 case ICMP_PARAMPROB
:
1637 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1639 (void)printf("Parameter problem: pointer = 0x%02x",
1640 icp
->icmp_hun
.ih_pptr
);
1645 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1647 (void)printf("Timestamp");
1650 case ICMP_TSTAMPREPLY
:
1651 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1653 (void)printf("Timestamp Reply");
1657 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1659 (void)printf("Information Request");
1662 case ICMP_IREQREPLY
:
1663 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1665 (void)printf("Information Reply");
1669 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1671 (void)printf("Address Mask Request");
1674 case ICMP_MASKREPLY
:
1675 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1677 (void)printf("Address Mask Reply");
1681 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1683 (void)printf("Bad ICMP type: %d", icp
->icmp_type
);
1684 if (pingflags
& F_VERBOSE
)
1693 * Print an IP header with options.
1696 pr_iph(struct icmp
*icp
,
1701 struct ip ipb
, *ip
= &ipb
;
1703 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1705 hlen
= ip
->ip_hl
<< 2;
1706 cp
= (u_char
*) &icp
->icmp_data
[20]; /* point to options */
1708 (void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
1709 (void)printf(" %1x %1x %02x %04x %04x",
1710 ip
->ip_v
, ip
->ip_hl
, ip
->ip_tos
, ip
->ip_len
, ip
->ip_id
);
1711 (void)printf(" %1x %04x",
1712 ((ip
->ip_off
)&0xe000)>>13, (ip
->ip_off
)&0x1fff);
1713 (void)printf(" %02x %02x %04x",
1714 ip
->ip_ttl
, ip
->ip_p
, ip
->ip_sum
);
1715 (void)printf(" %15s ",
1716 inet_ntoa(*(struct in_addr
*)&ip
->ip_src
.s_addr
));
1717 (void)printf(" %s ", inet_ntoa(*(struct in_addr
*)&ip
->ip_dst
.s_addr
));
1718 /* dump any option bytes */
1719 while (hlen
-- > 20 && cp
< (u_char
*)icp
+cc
) {
1720 (void)printf("%02x", *cp
++);
1725 * Print an ASCII host address starting from a string of bytes.
1728 pr_saddr(u_char
*cp
)
1731 struct in_addr addr
;
1734 l
= (l
<<8) + (u_char
)*++cp
;
1735 l
= (l
<<8) + (u_char
)*++cp
;
1736 l
= (l
<<8) + (u_char
)*++cp
;
1737 addr
.s_addr
= htonl(l
);
1738 (void)printf("\t%s", (l
== 0) ? "0.0.0.0" : pr_addr(&addr
));
1743 * Return an ASCII host address
1744 * as a dotted quad and optionally with a hostname
1747 pr_addr(struct in_addr
*addr
) /* in network order */
1750 static char buf
[MAXHOSTNAMELEN
+4+16+1];
1752 if ((pingflags
& F_NUMERIC
)
1753 || !(hp
= gethostbyaddr((char *)addr
, sizeof(*addr
), AF_INET
))) {
1754 (void)snprintf(buf
, sizeof(buf
), "%s", inet_ntoa(*addr
));
1756 (void)snprintf(buf
, sizeof(buf
), "%s (%s)", hp
->h_name
,
1764 * Dump some info on a returned (via ICMP) IP packet.
1767 pr_retip(struct icmp
*icp
,
1772 struct ip ipb
, *ip
= &ipb
;
1774 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1776 if (pingflags
& F_VERBOSE
)
1779 hlen
= ip
->ip_hl
<< 2;
1780 cp
= (u_char
*) &icp
->icmp_data
[hlen
];
1782 if (ip
->ip_p
== IPPROTO_TCP
) {
1783 if (pingflags
& F_VERBOSE
)
1784 (void)printf("\n TCP: from port %u, to port %u",
1785 (*cp
*256+*(cp
+1)), (*(cp
+2)*256+*(cp
+3)));
1786 } else if (ip
->ip_p
== IPPROTO_UDP
) {
1787 if (pingflags
& F_VERBOSE
)
1788 (void)printf("\n UDP: from port %u, to port %u",
1789 (*cp
*256+*(cp
+1)), (*(cp
+2)*256+*(cp
+3)));
1790 } else if (ip
->ip_p
== IPPROTO_ICMP
) {
1792 (void) memcpy(&icp2
, cp
, sizeof(icp2
));
1793 if (icp2
.icmp_type
== ICMP_ECHO
) {
1794 if (pingflags
& F_VERBOSE
)
1795 (void)printf("\n ID=%u icmp_seq=%u",
1796 ntohs((u_int16_t
)icp2
.icmp_id
),
1797 ntohs((u_int16_t
)icp2
.icmp_seq
));
1799 (void)printf(" for icmp_seq=%u",
1800 ntohs((u_int16_t
)icp2
.icmp_seq
));
1812 for (cp
= fill_pat
; *cp
!= '\0'; cp
++) {
1813 if (!isxdigit((unsigned char)*cp
))
1816 if (cp
== fill_pat
|| *cp
!= '\0' || (cp
-fill_pat
) > 16*2) {
1817 (void)fflush(stdout
);
1818 errx(EXIT_FAILURE
, "\"-p %s\": patterns must be specified with"
1819 " 1-32 hex digits\n",
1823 i
= sscanf(fill_pat
,
1824 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1825 &pat
[0], &pat
[1], &pat
[2], &pat
[3],
1826 &pat
[4], &pat
[5], &pat
[6], &pat
[7],
1827 &pat
[8], &pat
[9], &pat
[10], &pat
[11],
1828 &pat
[12], &pat
[13], &pat
[14], &pat
[15]);
1830 for (k
= phdrlen
, j
= 0; k
< datalen
; k
++) {
1831 opack_icmp
.icmp_data
[k
] = pat
[j
];
1836 if (!(pingflags
& F_QUIET
)) {
1837 (void)printf("PATTERN: 0x");
1839 (void)printf("%02x",
1840 (u_char
)opack_icmp
.icmp_data
[phdrlen
+ j
]);
1850 static u_int32_t rnd
;
1853 for (i
= phdrlen
; i
< datalen
; i
++) {
1854 rnd
= (3141592621U * rnd
+ 663896637U);
1855 opack_icmp
.icmp_data
[i
] = rnd
>>24;
1861 gethost(const char *arg
,
1863 struct sockaddr_in
*sa
,
1869 (void)memset(sa
, 0, sizeof(*sa
));
1870 sa
->sin_family
= AF_INET
;
1871 sa
->sin_len
= sizeof(struct sockaddr_in
);
1873 /* If it is an IP address, try to convert it to a name to
1874 * have something nice to display.
1876 if (inet_aton(name
, &sa
->sin_addr
) != 0) {
1878 if (pingflags
& F_NUMERIC
)
1881 hp
= gethostbyaddr((char *)&sa
->sin_addr
,
1882 sizeof(sa
->sin_addr
), AF_INET
);
1883 (void)strlcpy(realname
, hp
? hp
->h_name
: name
,
1889 hp
= gethostbyname(name
);
1891 errx(EXIT_FAILURE
, "Cannot resolve \"%s\" (%s)",
1892 name
, hstrerror(h_errno
));
1894 if (hp
->h_addrtype
!= AF_INET
)
1895 errx(EXIT_FAILURE
, "%s only supported with IP", arg
);
1897 (void)memcpy(&sa
->sin_addr
, hp
->h_addr
, sizeof(sa
->sin_addr
));
1900 (void)strlcpy(realname
, hp
->h_name
, realname_len
);
1908 #ifdef IPSEC_POLICY_IPSEC
1909 #define IPSECOPT "\n [-E policy] "
1911 #define IPSECOPT "\n [-AE] "
1912 #endif /*IPSEC_POLICY_IPSEC*/
1917 (void)fprintf(stderr
, "usage: \n"
1918 "%s [-aCDdfLnoPQqRrv] [-c count] [-g gateway] [-h host]"
1919 " [-I addr] [-i interval]\n"
1920 " [-l preload] [-p pattern] [-s size] [-T ttl] [-t tos]"
1921 " [-w maxwait] " IPSECOPT
"host\n",