1 /* $NetBSD: ping.c,v 1.107 2013/10/19 01:08:25 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.107 2013/10/19 01:08:25 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;
201 static int bufspace
= IP_MAXPACKET
;
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 */
208 static struct timespec jiggle_time
;
209 static int jiggle_cnt
, total_jiggled
, jiggle_direction
= -1;
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 summary(int);
216 static void pinger(void);
217 static void fill(void);
218 static void rnd_fill(void);
219 static double diffsec(struct timespec
*, struct timespec
*);
221 static void timespecadd(struct timespec
*, struct timespec
*);
223 static void sec_to_timespec(const double, struct timespec
*);
224 static double timespec_to_sec(const struct timespec
*);
225 static void pr_pack(u_char
*, int, struct sockaddr_in
*);
226 static u_int16_t
in_cksum(u_int16_t
*, u_int
);
227 static void pr_saddr(u_char
*);
228 static char *pr_addr(struct in_addr
*);
229 static void pr_iph(struct icmp
*, int);
230 static void pr_retip(struct icmp
*, int);
231 static int pr_icmph(struct icmp
*, struct sockaddr_in
*, int);
232 static void jiggle(int), jiggle_flush(int);
233 static void gethost(const char *, const char *,
234 struct sockaddr_in
*, char *, int);
235 __dead
static void usage(void);
238 main(int argc
, char *argv
[])
240 int c
, i
, on
= 1, hostind
= 0;
242 int len
= -1, compat
= 0;
247 #ifdef IPSEC_POLICY_IPSEC
248 char *policy_in
= NULL
;
249 char *policy_out
= NULL
;
256 if (prog_init
&& prog_init() == -1)
257 err(1, "init failed");
259 if ((s
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
260 err(1, "Cannot create socket");
261 if ((sloop
= prog_socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) < 0)
262 err(1, "Cannot create socket");
266 * sloop is never read on. This prevents packets from
267 * queueing in its recv buffer.
269 if (prog_shutdown(sloop
, SHUT_RD
) == -1)
270 warn("Cannot shutdown for read");
273 if (prog_setuid(prog_getuid()) == -1)
276 setprogname(argv
[0]);
281 #ifdef IPSEC_POLICY_IPSEC
282 #define IPSECOPT "E:"
284 #define IPSECOPT "AE"
285 #endif /*IPSEC_POLICY_IPSEC*/
287 while ((c
= getopt(argc
, argv
,
288 "ac:CdDfg:h:i:I:l:Lnop:PqQrRs:t:T:vw:" IPSECOPT
)) != -1) {
292 pingflags
|= F_AUDIBLE
;
298 npackets
= strtol(optarg
, &p
, 0);
299 if (*p
!= '\0' || npackets
<= 0)
300 errx(1, "Bad/invalid number of packets");
309 pingflags
|= F_FLOOD
;
314 case 'i': /* wait between sending packets */
315 interval
= strtod(optarg
, &p
);
316 if (*p
!= '\0' || interval
<= 0)
317 errx(1, "Bad/invalid interval %s", optarg
);
320 preload
= strtol(optarg
, &p
, 0);
321 if (*p
!= '\0' || preload
< 0)
322 errx(1, "Bad/invalid preload value %s",
326 pingflags
|= F_NUMERIC
;
331 case 'p': /* fill buffer with user pattern */
332 if (pingflags
& F_PING_RANDOM
)
333 errx(1, "Only one of -P and -p allowed");
334 pingflags
|= F_PING_FILLED
;
338 if (pingflags
& F_PING_FILLED
)
339 errx(1, "Only one of -P and -p allowed");
340 pingflags
|= F_PING_RANDOM
;
343 pingflags
|= F_QUIET
;
346 pingflags
|= F_SEMI_QUIET
;
349 options
|= SO_DONTROUTE
;
351 case 's': /* size of packet to send */
352 l
= strtol(optarg
, &p
, 0);
353 if (*p
!= '\0' || l
< 0)
354 errx(1, "Bad/invalid packet size %s", optarg
);
356 errx(1, "packet size is too large");
360 pingflags
|= F_VERBOSE
;
363 pingflags
|= F_RECORD_ROUTE
;
366 pingflags
|= F_MCAST_NOLOOP
;
369 tos
= strtoul(optarg
, &p
, 0);
370 if (*p
!= '\0' || tos
> 0xFF)
371 errx(1, "bad tos value: %s", optarg
);
374 l
= strtol(optarg
, &p
, 0);
375 if (*p
!= '\0' || l
> 255 || l
<= 0)
376 errx(1, "ttl out of range");
377 ttl
= (u_char
)l
; /* cannot check >255 otherwise */
380 pingflags
|= F_SOURCE_ADDR
;
381 gethost("-I", optarg
, &src_addr
, 0, 0);
384 pingflags
|= F_SOURCE_ROUTE
;
385 gethost("-g", optarg
, &send_addr
, 0, 0);
388 maxwait
= strtod(optarg
, &p
);
389 if (*p
!= '\0' || maxwait
<= 0)
390 errx(1, "Bad/invalid maxwait time %s", optarg
);
393 #ifdef IPSEC_POLICY_IPSEC
395 pingflags
|= F_POLICY
;
396 if (!strncmp("in", optarg
, 2)) {
397 policy_in
= strdup(optarg
);
400 } else if (!strncmp("out", optarg
, 3)) {
401 policy_out
= strdup(optarg
);
405 errx(1, "invalid security policy");
409 pingflags
|= F_AUTHHDR
;
412 pingflags
|= F_ENCRYPT
;
414 #endif /*IPSEC_POLICY_IPSEC*/
423 interval
= (pingflags
& F_FLOOD
) ? FLOOD_INTVL
: 1.0;
425 if (pingflags
& F_FLOOD
&& prog_getuid())
426 errx(1, "Must be superuser to use -f");
427 if (interval
< 1.0 && prog_getuid())
428 errx(1, "Must be superuser to use < 1 sec ping interval");
429 if (preload
> 0 && prog_getuid())
430 errx(1, "Must be superuser to use -l");
432 sec_to_timespec(interval
, &interval_tv
);
434 if ((pingflags
& (F_AUDIBLE
|F_FLOOD
)) == (F_AUDIBLE
|F_FLOOD
))
435 warnx("Sorry, no audible output for flood pings");
444 if (optind
!= argc
-1)
449 else if (hostind
>= argc
- 1)
452 gethost("", argv
[hostind
], &whereto
, hostname
, sizeof(hostname
));
453 if (IN_MULTICAST(ntohl(whereto
.sin_addr
.s_addr
)))
454 pingflags
|= F_MCAST
;
455 if (!(pingflags
& F_SOURCE_ROUTE
))
456 (void) memcpy(&send_addr
, &whereto
, sizeof(send_addr
));
458 loc_addr
.sin_family
= AF_INET
;
459 loc_addr
.sin_len
= sizeof(struct sockaddr_in
);
460 loc_addr
.sin_addr
.s_addr
= htonl((127 << 24) + 1);
466 if (!compat
&& datalen
>= (int)PHDR64_LEN
) { /* can we time them? */
467 pingflags
|= F_TIMING64
;
468 phdrlen
= PHDR64_LEN
;
469 } else if (datalen
>= (int)PHDR_LEN
) { /* can we time them? */
470 pingflags
|= F_TIMING
;
475 packlen
= datalen
+ 60 + 76; /* MAXIP + MAXICMP */
477 if ((packet
= malloc(packlen
)) == NULL
)
478 err(1, "Out of memory");
480 if (pingflags
& F_PING_FILLED
) {
482 } else if (pingflags
& F_PING_RANDOM
) {
485 for (i
= phdrlen
; i
< datalen
; i
++)
486 opack_icmp
.icmp_data
[i
] = i
;
489 ident
= arc4random() & 0xFFFF;
491 if (options
& SO_DEBUG
) {
492 if (prog_setsockopt(s
, SOL_SOCKET
, SO_DEBUG
,
493 (char *)&on
, sizeof(on
)) == -1)
494 warn("Can't turn on socket debugging");
496 if (options
& SO_DONTROUTE
) {
497 if (prog_setsockopt(s
, SOL_SOCKET
, SO_DONTROUTE
,
498 (char *)&on
, sizeof(on
)) == -1)
499 warn("SO_DONTROUTE");
502 if (options
& SO_DEBUG
) {
503 if (prog_setsockopt(sloop
, SOL_SOCKET
, SO_DEBUG
,
504 (char *)&on
, sizeof(on
)) == -1)
505 warn("Can't turn on socket debugging");
507 if (options
& SO_DONTROUTE
) {
508 if (prog_setsockopt(sloop
, SOL_SOCKET
, SO_DONTROUTE
,
509 (char *)&on
, sizeof(on
)) == -1)
510 warn("SO_DONTROUTE");
513 if (pingflags
& F_SOURCE_ROUTE
) {
514 optspace
[IPOPT_OPTVAL
] = IPOPT_LSRR
;
515 optspace
[IPOPT_OLEN
] = optlen
= 7;
516 optspace
[IPOPT_OFFSET
] = IPOPT_MINOFF
;
517 (void)memcpy(&optspace
[IPOPT_MINOFF
-1], &whereto
.sin_addr
,
518 sizeof(whereto
.sin_addr
));
519 optspace
[optlen
++] = IPOPT_NOP
;
521 if (pingflags
& F_RECORD_ROUTE
) {
522 optspace
[optlen
+IPOPT_OPTVAL
] = IPOPT_RR
;
523 optspace
[optlen
+IPOPT_OLEN
] = (MAX_IPOPTLEN
-1-optlen
);
524 optspace
[optlen
+IPOPT_OFFSET
] = IPOPT_MINOFF
;
525 optlen
= MAX_IPOPTLEN
;
527 /* this leaves opack_ip 0(mod 4) aligned */
528 opack_ip
= (struct ip
*)((char *)&out_pack
.o_ip
529 + sizeof(out_pack
.o_opt
)
531 (void) memcpy(opack_ip
+ 1, optspace
, optlen
);
534 if (prog_setsockopt(s
,IPPROTO_IP
,IP_HDRINCL
,
535 (char *) &on
, sizeof(on
)) < 0)
536 err(1, "Can't set special IP header");
539 opack_ip
->ip_v
= IPVERSION
;
540 opack_ip
->ip_hl
= (sizeof(struct ip
)+optlen
) >> 2;
541 opack_ip
->ip_tos
= tos
;
542 opack_ip
->ip_off
= (pingflags
& F_DF
) ? IP_DF
: 0;
543 opack_ip
->ip_ttl
= ttl
? ttl
: MAXTTL
;
544 opack_ip
->ip_p
= IPPROTO_ICMP
;
545 opack_ip
->ip_src
= src_addr
.sin_addr
;
546 opack_ip
->ip_dst
= send_addr
.sin_addr
;
548 if (pingflags
& F_MCAST
) {
549 if (pingflags
& F_MCAST_NOLOOP
) {
551 if (prog_setsockopt(s
, IPPROTO_IP
,
553 (char *) &loop
, 1) < 0)
554 err(1, "Can't disable multicast loopback");
558 && prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_TTL
,
559 (char *) &ttl
, 1) < 0)
560 err(1, "Can't set multicast time-to-live");
562 if ((pingflags
& F_SOURCE_ADDR
)
563 && prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
,
564 (char *) &src_addr
.sin_addr
,
565 sizeof(src_addr
.sin_addr
)) < 0)
566 err(1, "Can't set multicast source interface");
568 } else if (pingflags
& F_SOURCE_ADDR
) {
569 if (prog_setsockopt(s
, IPPROTO_IP
, IP_MULTICAST_IF
,
570 (char *) &src_addr
.sin_addr
,
571 sizeof(src_addr
.sin_addr
)) < 0)
572 err(1, "Can't set source interface/address");
575 #ifdef IPSEC_POLICY_IPSEC
578 if (pingflags
& F_POLICY
) {
579 if (policy_in
!= NULL
) {
580 buf
= ipsec_set_policy(policy_in
, strlen(policy_in
));
582 errx(1, "%s", ipsec_strerror());
583 if (prog_setsockopt(s
, IPPROTO_IP
, IP_IPSEC_POLICY
,
584 buf
, ipsec_get_policylen(buf
)) < 0) {
585 err(1, "ipsec policy cannot be configured");
589 if (policy_out
!= NULL
) {
590 buf
= ipsec_set_policy(policy_out
, strlen(policy_out
));
592 errx(1, "%s", ipsec_strerror());
593 if (prog_setsockopt(s
, IPPROTO_IP
, IP_IPSEC_POLICY
,
594 buf
, ipsec_get_policylen(buf
)) < 0) {
595 err(1, "ipsec policy cannot be configured");
600 buf
= ipsec_set_policy("out bypass", strlen("out bypass"));
602 errx(1, "%s", ipsec_strerror());
603 if (prog_setsockopt(sloop
, IPPROTO_IP
, IP_IPSEC_POLICY
,
604 buf
, ipsec_get_policylen(buf
)) < 0) {
606 warnx("ipsec is not configured");
608 /* ignore it, should be okay */
616 if (pingflags
& F_AUTHHDR
) {
617 optval
= IPSEC_LEVEL_REQUIRE
;
618 #ifdef IP_AUTH_TRANS_LEVEL
619 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
,
620 (char *)&optval
, sizeof(optval
));
622 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_AUTH_LEVEL
,
623 (char *)&optval
, sizeof(optval
));
626 if (pingflags
& F_ENCRYPT
) {
627 optval
= IPSEC_LEVEL_REQUIRE
;
628 (void)prog_setsockopt(s
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
,
629 (char *)&optval
, sizeof(optval
));
631 optval
= IPSEC_LEVEL_BYPASS
;
632 #ifdef IP_AUTH_TRANS_LEVEL
633 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_AUTH_TRANS_LEVEL
,
634 (char *)&optval
, sizeof(optval
));
636 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_AUTH_LEVEL
,
637 (char *)&optval
, sizeof(optval
));
639 (void)prog_setsockopt(sloop
, IPPROTO_IP
, IP_ESP_TRANS_LEVEL
,
640 (char *)&optval
, sizeof(optval
));
642 #endif /*IPSEC_POLICY_IPSEC*/
645 (void)printf("PING %s (%s): %d data bytes\n", hostname
,
646 inet_ntoa(whereto
.sin_addr
), datalen
+ phdrlen
);
649 /* When pinging the broadcast address, you can get a lot
650 * of answers. Doing something so evil is useful if you
651 * are trying to stress the ethernet, or just want to
652 * fill the arp cache to get some stuff for /etc/ethers.
654 while (0 > prog_setsockopt(s
, SOL_SOCKET
, SO_RCVBUF
,
655 (char*)&bufspace
, sizeof(bufspace
))) {
656 if ((bufspace
-= 4096) <= 0)
657 err(1, "Cannot set the receive buffer size");
660 /* make it possible to send giant probes, but do not worry now
661 * if it fails, since we probably won't send giant probes.
663 (void)prog_setsockopt(s
, SOL_SOCKET
, SO_SNDBUF
,
664 (char*)&bufspace
, sizeof(bufspace
));
667 (void)signal(SIGINT
, prefinish
);
670 sa
.sa_handler
= prtsig
;
671 sa
.sa_flags
= SA_NOKERNINFO
;
672 sigemptyset(&sa
.sa_mask
);
673 (void)sigaction(SIGINFO
, &sa
, NULL
);
675 (void)signal(SIGQUIT
, prtsig
);
677 (void)signal(SIGCONT
, prtsig
);
679 /* fire off them quickies */
680 for (i
= 0; i
< preload
; i
++) {
681 clock_gettime(CLOCK_MONOTONIC
, &now
);
694 struct sockaddr_in from
;
696 double sec
, last
, d_last
;
697 struct pollfd fdmaskp
[1];
699 (void)clock_gettime(CLOCK_MONOTONIC
, &clear_cache
);
701 last
= timespec_to_sec(&clear_cache
) + maxwait
;
705 d_last
= 365*24*60*60;
709 clock_gettime(CLOCK_MONOTONIC
, &now
);
712 d_last
= last
- timespec_to_sec(&now
);
714 if (ntransmitted
< npackets
&& d_last
> 0) {
715 /* send if within 100 usec or late for next packet */
716 sec
= diffsec(&next_tx
, &now
);
718 (lastrcvd
&& (pingflags
& F_FLOOD
))) {
720 sec
= diffsec(&next_tx
, &now
);
728 /* For the last response, wait twice as long as the
729 * worst case seen, or 10 times as long as the
730 * maximum interpacket interval, whichever is longer.
732 sec
= MAX(2 * tmax
, 10 * interval
) -
733 diffsec(&now
, &last_tx
);
741 fdmaskp
[0].events
= POLLIN
;
742 cc
= prog_poll(fdmaskp
, 1, (int)(sec
* 1000));
753 fromlen
= sizeof(from
);
754 cc
= prog_recvfrom(s
, (char *) packet
, packlen
,
755 0, (struct sockaddr
*)&from
,
758 perror("recvfrom failed");
759 if (errno
!= EINTR
) {
762 (void)fflush(stderr
);
766 clock_gettime(CLOCK_MONOTONIC
, &now
);
767 pr_pack(packet
, cc
, &from
);
769 } while (nreceived
< npackets
770 && (nreceived
== 0 || !(pingflags
& F_ONCE
)));
777 jiggle_flush(int nl
) /* new line if there are dots */
781 if (jiggle_cnt
> 0) {
782 total_jiggled
+= jiggle_cnt
;
783 jiggle_direction
= 1;
786 } while (--jiggle_cnt
> 0);
788 } else if (jiggle_cnt
< 0) {
789 total_jiggled
-= jiggle_cnt
;
790 jiggle_direction
= -1;
793 } while (++jiggle_cnt
< 0);
797 if (total_jiggled
!= 0)
800 jiggle_direction
= -1;
803 (void)fflush(stdout
);
804 (void)fflush(stderr
);
810 /* jiggle the cursor for flood-ping
817 if (pingflags
& F_QUIET
)
820 /* do not back up into messages */
821 if (total_jiggled
+jiggle_cnt
+delta
< 0)
826 /* flush the FLOOD dots when things are quiet
827 * or occassionally to make the cursor jiggle.
829 dt
= diffsec(&last_tx
, &jiggle_time
);
830 if (dt
> 0.2 || (dt
>= 0.15 && delta
*jiggle_direction
< 0))
836 * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
837 * will be added on by the kernel. The ID field is our UNIX process ID,
838 * and the sequence number is an ascending integer. The first phdrlen bytes
839 * of the data portion are used to hold a UNIX "timeval" struct in VAX
840 * byte-order, to compute the round-trip time, or a UNIX "timespec" in native
853 opack_icmp
.icmp_code
= 0;
854 opack_icmp
.icmp_seq
= htons((u_int16_t
)(ntransmitted
));
857 /* clear the cached route in the kernel after an ICMP
858 * response such as a Redirect is seen to stop causing
859 * more such packets. Also clear the cached route
860 * periodically in case of routing changes that make
861 * black holes come and go.
863 if (clear_cache
.tv_sec
!= now
.tv_sec
) {
864 opack_icmp
.icmp_type
= ICMP_ECHOREPLY
;
865 opack_icmp
.icmp_id
= ~ident
;
866 opack_icmp
.icmp_cksum
= 0;
867 opack_icmp
.icmp_cksum
= in_cksum((u_int16_t
*)&opack_icmp
,
870 if (prog_setsockopt(sloop
,IPPROTO_IP
,IP_HDRINCL
,
871 (char *)&sw
,sizeof(sw
)) < 0)
872 err(1, "Can't turn off special IP header");
873 if (prog_sendto(sloop
, (char *) &opack_icmp
,
874 ICMP_MINLEN
, MSG_DONTROUTE
,
875 (struct sockaddr
*)&loc_addr
,
876 sizeof(struct sockaddr_in
)) < 0) {
878 * XXX: we only report this as a warning in verbose
879 * mode because people get confused when they see
880 * this error when they are running in single user
881 * mode and they have not configured lo0
883 if (pingflags
& F_VERBOSE
)
884 warn("failed to clear cached route");
887 if (prog_setsockopt(sloop
,IPPROTO_IP
,IP_HDRINCL
,
888 (char *)&sw
, sizeof(sw
)) < 0)
889 err(1, "Can't set special IP header");
891 (void)clock_gettime(CLOCK_MONOTONIC
, &clear_cache
);
895 opack_icmp
.icmp_type
= ICMP_ECHO
;
896 opack_icmp
.icmp_id
= ident
;
898 if (pingflags
& F_TIMING
) {
899 tv32
.tv32_sec
= (uint32_t)htonl(now
.tv_sec
);
900 tv32
.tv32_usec
= htonl(now
.tv_nsec
/ 1000);
901 (void) memcpy(&opack_icmp
.icmp_data
[0], &tv32
, sizeof(tv32
));
902 } else if (pingflags
& F_TIMING64
)
903 (void) memcpy(&opack_icmp
.icmp_data
[0], &now
, sizeof(now
));
905 cc
= MAX(datalen
, ICMP_MINLEN
) + phdrlen
;
906 opack_icmp
.icmp_cksum
= 0;
907 opack_icmp
.icmp_cksum
= in_cksum((u_int16_t
*)&opack_icmp
, cc
);
909 cc
+= opack_ip
->ip_hl
<<2;
910 opack_ip
->ip_len
= cc
;
911 i
= prog_sendto(s
, (char *) opack_ip
, cc
, 0,
912 (struct sockaddr
*)&send_addr
, sizeof(struct sockaddr_in
));
919 warnx("wrote %s %d chars, ret=%d", hostname
, cc
, i
);
920 (void)fflush(stderr
);
928 if (next_tx
.tv_sec
== 0) {
933 /* Transmit regularly, at always the same microsecond in the
934 * second when going at one packet per second.
935 * If we are at most 100 ms behind, send extras to get caught up.
936 * Otherwise, skip packets we were too slow to send.
938 if (diffsec(&next_tx
, &now
) <= interval
) {
940 timespecadd(&next_tx
, &interval_tv
, &next_tx
);
941 } while (diffsec(&next_tx
, &now
) < -0.1);
944 if (pingflags
& F_FLOOD
)
947 /* While the packet is going out, ready buffer for the next
948 * packet. Use a fast but not very good random number generator.
950 if (pingflags
& F_PING_RANDOM
)
965 if (pingflags
& F_FLOOD
)
968 (void)printf("%d bytes from %s: icmp_seq=%u", cc
, addr
, seqno
);
970 (void)printf(" DUP!");
971 (void)printf(" ttl=%d", ttl
);
972 if (pingflags
& (F_TIMING
|F_TIMING64
)) {
973 const unsigned int prec
= (pingflags
& F_TIMING64
) != 0 ? 6 : 3;
975 (void)printf(" time=%.*f ms", prec
, triptime
*1000.0);
979 * Send beep to stderr, since that's more likely than stdout
980 * to go to a terminal..
982 if (pingflags
& F_AUDIBLE
&& !dupflag
)
983 (void)fprintf(stderr
,"\a");
988 * Print out the packet, if it came from us. This logic is necessary
989 * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
990 * which arrive ('tis only fair). This permits multiple copies of this
991 * program to be run without having intermingled output (or statistics!).
996 struct sockaddr_in
*from
)
1002 static int old_rrlen
;
1003 static char old_rr
[MAX_IPOPTLEN
];
1004 int hlen
, dupflag
= 0, dumped
;
1005 double triptime
= 0.0;
1006 #define PR_PACK_SUB() {if (!dumped) { \
1008 pr_pack_sub(net_len, inet_ntoa(from->sin_addr), \
1009 ntohs((u_int16_t)icp->icmp_seq), \
1010 dupflag, ip->ip_ttl, triptime);}}
1012 /* Check the IP header */
1013 ip
= (struct ip
*) buf
;
1014 hlen
= ip
->ip_hl
<< 2;
1015 if (tot_len
< hlen
+ ICMP_MINLEN
) {
1016 if (pingflags
& F_VERBOSE
) {
1018 (void)printf("packet too short (%d bytes) from %s\n",
1019 tot_len
, inet_ntoa(from
->sin_addr
));
1024 /* Now the ICMP part */
1026 net_len
= tot_len
- hlen
;
1027 icp
= (struct icmp
*)(buf
+ hlen
);
1028 if (icp
->icmp_type
== ICMP_ECHOREPLY
1029 && icp
->icmp_id
== ident
) {
1031 if (icp
->icmp_seq
== htons((u_int16_t
)(ntransmitted
-1)))
1034 if (first_rx
.tv_sec
== 0)
1037 if (pingflags
& (F_TIMING
|F_TIMING64
)) {
1040 if (pingflags
& F_TIMING
) {
1043 (void)memcpy(&tv32
, icp
->icmp_data
, sizeof(tv32
));
1044 tv
.tv_sec
= (uint32_t)ntohl(tv32
.tv32_sec
);
1045 tv
.tv_nsec
= ntohl(tv32
.tv32_usec
) * 1000;
1046 } else if (pingflags
& F_TIMING64
)
1047 (void)memcpy(&tv
, icp
->icmp_data
, sizeof(tv
));
1049 memset(&tv
, 0, sizeof(tv
)); /* XXX: gcc */
1051 triptime
= diffsec(&last_rx
, &tv
);
1053 tsumsq
+= triptime
* triptime
;
1054 if (triptime
< tmin
)
1056 if (triptime
> tmax
)
1060 if (TST(ntohs((u_int16_t
)icp
->icmp_seq
))) {
1061 nrepeats
++, nreceived
--;
1064 SET(ntohs((u_int16_t
)icp
->icmp_seq
));
1067 if (tot_len
!= opack_ip
->ip_len
) {
1069 switch (opack_ip
->ip_len
- tot_len
) {
1071 if ((pongflags
& F_RECORD_ROUTE
) != 0)
1073 if ((pingflags
& F_RECORD_ROUTE
) == 0)
1075 pongflags
|= F_RECORD_ROUTE
;
1076 (void)printf("\nremote host does not "
1077 "support record route");
1080 if ((pongflags
& F_SOURCE_ROUTE
) != 0)
1082 if ((pingflags
& F_SOURCE_ROUTE
) == 0)
1084 pongflags
|= F_SOURCE_ROUTE
;
1085 (void)printf("\nremote host does not "
1086 "support source route");
1090 (void)printf("\nwrong total length %d "
1091 "instead of %d", tot_len
, opack_ip
->ip_len
);
1097 static u_int16_t last_seqno
= 0xffff;
1098 u_int16_t seqno
= ntohs((u_int16_t
)icp
->icmp_seq
);
1099 u_int16_t gap
= seqno
- (last_seqno
+ 1);
1100 if (gap
> 0 && gap
< 0x8000 &&
1101 (pingflags
& F_VERBOSE
)) {
1102 (void)printf("[*** sequence gap of %u "
1103 "packets from %u ... %u ***]\n", gap
,
1104 (u_int16_t
) (last_seqno
+ 1),
1105 (u_int16_t
) (seqno
- 1));
1106 if (pingflags
& F_QUIET
)
1114 if (pingflags
& F_QUIET
)
1117 if (!(pingflags
& F_FLOOD
))
1120 /* check the data */
1121 if ((size_t)(tot_len
- hlen
) >
1122 offsetof(struct icmp
, icmp_data
) + datalen
1123 && !(pingflags
& F_PING_RANDOM
)
1124 && memcmp(icp
->icmp_data
+ phdrlen
,
1125 opack_icmp
.icmp_data
+ phdrlen
,
1126 datalen
- phdrlen
)) {
1127 for (i
= phdrlen
; i
< datalen
; i
++) {
1128 if (icp
->icmp_data
[i
] !=
1129 opack_icmp
.icmp_data
[i
])
1133 (void)printf("\nwrong data byte #%d should have been"
1134 " %#x but was %#x", i
,
1135 (u_char
)opack_icmp
.icmp_data
[i
],
1136 (u_char
)icp
->icmp_data
[i
]);
1137 for (i
= phdrlen
; i
< datalen
; i
++) {
1139 (void)printf("\n\t");
1140 (void)printf("%2x ",(u_char
)icp
->icmp_data
[i
]);
1145 if (!pr_icmph(icp
, from
, net_len
))
1150 /* Display any IP options */
1151 cp
= buf
+ sizeof(struct ip
);
1152 while (hlen
> (int)sizeof(struct ip
)) {
1171 (void)printf("\nLSRR: ");
1179 (void)putchar('\n');
1183 j
= *++cp
; /* get length */
1184 i
= *++cp
; /* and pointer */
1193 && !memcmp(cp
, old_rr
, i
)) {
1195 (void)printf("\t(same route)");
1202 (void) memcpy(old_rr
, cp
, i
);
1206 (void)printf("RR: ");
1209 (void)printf("\nRR: ");
1218 (void)putchar('\n');
1225 (void)printf("\nNOP");
1228 case IPOPT_SECURITY
: /* RFC 1108 RIPSO BSO */
1229 case IPOPT_ESO
: /* RFC 1108 RIPSO ESO */
1230 case IPOPT_CIPSO
: /* Commercial IPSO */
1231 if ((sysconf(_SC_IP_SECOPTS
)) > 0) {
1232 i
= (unsigned)cp
[1];
1235 (void)printf("\nSEC:");
1237 (void)printf(" %02x", *cp
++);
1245 (void)printf("\nunknown option 0x%x", *cp
);
1253 (void)putchar('\n');
1254 (void)fflush(stdout
);
1261 /* Compute the IP checksum
1262 * This assumes the packet is less than 32K long.
1265 in_cksum(u_int16_t
*p
, u_int len
)
1268 int nwords
= len
>> 1;
1270 while (nwords
-- != 0)
1278 u
.c
[0] = *(u_char
*)p
;
1283 /* end-around-carry */
1284 sum
= (sum
>> 16) + (sum
& 0xffff);
1291 * compute the difference of two timespecs in seconds
1294 diffsec(struct timespec
*timenow
,
1295 struct timespec
*then
)
1297 if (timenow
->tv_sec
== 0)
1299 return (timenow
->tv_sec
- then
->tv_sec
)
1300 * 1.0 + (timenow
->tv_nsec
- then
->tv_nsec
) / 1000000000.0;
1306 timespecadd(struct timespec
*t1
,
1307 struct timespec
*t2
)
1310 t1
->tv_sec
+= t2
->tv_sec
;
1311 if ((t1
->tv_nsec
+= t2
->tv_nsec
) >= 1000000000) {
1313 t1
->tv_nsec
-= 1000000000;
1320 sec_to_timespec(const double sec
, struct timespec
*tp
)
1323 tp
->tv_nsec
= (sec
- tp
->tv_sec
) * 1000000000.0;
1328 timespec_to_sec(const struct timespec
*tp
)
1330 return tp
->tv_sec
+ tp
->tv_nsec
/ 1000000000.0;
1336 * Heavily buffered STDIO is used here, so that all the statistics
1337 * will be written with 1 sys-write call. This is nice when more
1338 * than one copy of the program is running on a terminal; it prevents
1339 * the statistics output from becomming intermingled.
1347 (void)printf("\n----%s PING Statistics----\n", hostname
);
1348 (void)printf("%d packets transmitted, ", ntransmitted
);
1349 (void)printf("%d packets received, ", nreceived
);
1351 (void)printf("+%d duplicates, ", nrepeats
);
1353 if (nreceived
> ntransmitted
)
1354 (void)printf("-- somebody's duplicating packets!");
1356 (void)printf("%.1f%% packet loss",
1357 (((ntransmitted
-nreceived
)*100.0) /
1361 if (nreceived
&& (pingflags
& (F_TIMING
|F_TIMING64
))) {
1362 double n
= nreceived
+ nrepeats
;
1363 double avg
= (tsum
/ n
);
1364 double variance
= 0.0;
1365 const unsigned int prec
= (pingflags
& F_TIMING64
) != 0 ? 6 : 3;
1367 variance
= (tsumsq
- n
*avg
*avg
) /(n
-1);
1369 printf("round-trip min/avg/max/stddev = "
1370 "%.*f/%.*f/%.*f/%.*f ms\n",
1371 prec
, tmin
* 1000.0,
1373 prec
, tmax
* 1000.0,
1374 prec
, sqrt(variance
) * 1000.0);
1375 if (pingflags
& F_FLOOD
) {
1376 double r
= diffsec(&last_rx
, &first_rx
);
1377 double t
= diffsec(&last_tx
, &first_tx
);
1382 (void)printf(" %.1f packets/sec sent, "
1383 " %.1f packets/sec received\n",
1384 ntransmitted
/t
, nreceived
/r
);
1391 * Print statistics when SIGINFO is received.
1400 (void)signal(SIGQUIT
, prtsig
);
1406 * On the first SIGINT, allow any outstanding packets to dribble in
1409 prefinish(int dummy
)
1411 if (lastrcvd
/* quit now if caught up */
1412 || nreceived
== 0) /* or if remote is dead */
1415 (void)signal(dummy
, finish
); /* do this only the 1st time */
1417 if (npackets
> ntransmitted
) /* let the normal limit work */
1418 npackets
= ntransmitted
;
1422 * Print statistics and give up.
1429 (void)signal(SIGINFO
, SIG_DFL
);
1431 (void)signal(SIGQUIT
, SIG_DFL
);
1435 exit(nreceived
> 0 ? 0 : 2);
1439 static int /* 0=do not print it */
1440 ck_pr_icmph(struct icmp
*icp
,
1441 struct sockaddr_in
*from
,
1443 int override
) /* 1=override VERBOSE if interesting */
1446 struct ip ipb
, *ip
= &ipb
;
1447 struct icmp icp2b
, *icp2
= &icp2b
;
1450 if (pingflags
& F_VERBOSE
) {
1457 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1458 hlen
= ip
->ip_hl
<< 2;
1459 if (ip
->ip_p
== IPPROTO_ICMP
1460 && hlen
+ 6 <= cc
) {
1461 (void) memcpy(icp2
, &icp
->icmp_data
[hlen
], sizeof(*icp2
));
1462 if (icp2
->icmp_id
== ident
) {
1463 /* remember to clear route cached in kernel
1464 * if this non-Echo-Reply ICMP message was for one
1467 clear_cache
.tv_sec
= 0;
1469 if (!res
&& override
1470 && (pingflags
& (F_QUIET
|F_SEMI_QUIET
)) == 0) {
1472 (void)printf("%d bytes from %s: ",
1473 cc
, pr_addr(&from
->sin_addr
));
1484 * Print a descriptive string about an ICMP header other than an echo reply.
1486 static int /* 0=printed nothing */
1487 pr_icmph(struct icmp
*icp
,
1488 struct sockaddr_in
*from
,
1491 switch (icp
->icmp_type
) {
1493 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1495 switch (icp
->icmp_code
) {
1496 case ICMP_UNREACH_NET
:
1497 (void)printf("Destination Net Unreachable");
1499 case ICMP_UNREACH_HOST
:
1500 (void)printf("Destination Host Unreachable");
1502 case ICMP_UNREACH_PROTOCOL
:
1503 (void)printf("Destination Protocol Unreachable");
1505 case ICMP_UNREACH_PORT
:
1506 (void)printf("Destination Port Unreachable");
1508 case ICMP_UNREACH_NEEDFRAG
:
1509 (void)printf("frag needed and DF set. Next MTU=%d",
1510 ntohs(icp
->icmp_nextmtu
));
1512 case ICMP_UNREACH_SRCFAIL
:
1513 (void)printf("Source Route Failed");
1515 case ICMP_UNREACH_NET_UNKNOWN
:
1516 (void)printf("Unreachable unknown net");
1518 case ICMP_UNREACH_HOST_UNKNOWN
:
1519 (void)printf("Unreachable unknown host");
1521 case ICMP_UNREACH_ISOLATED
:
1522 (void)printf("Unreachable host isolated");
1524 case ICMP_UNREACH_NET_PROHIB
:
1525 (void)printf("Net prohibited access");
1527 case ICMP_UNREACH_HOST_PROHIB
:
1528 (void)printf("Host prohibited access");
1530 case ICMP_UNREACH_TOSNET
:
1531 (void)printf("Bad TOS for net");
1533 case ICMP_UNREACH_TOSHOST
:
1534 (void)printf("Bad TOS for host");
1537 (void)printf("Communication prohibited");
1540 (void)printf("Host precedence violation");
1543 (void)printf("Precedence cutoff");
1546 (void)printf("Bad Destination Unreachable Code: %d",
1550 /* Print returned IP header information */
1554 case ICMP_SOURCEQUENCH
:
1555 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1557 (void)printf("Source Quench");
1562 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1564 switch (icp
->icmp_code
) {
1565 case ICMP_REDIRECT_NET
:
1566 (void)printf("Redirect Network");
1568 case ICMP_REDIRECT_HOST
:
1569 (void)printf("Redirect Host");
1571 case ICMP_REDIRECT_TOSNET
:
1572 (void)printf("Redirect Type of Service and Network");
1574 case ICMP_REDIRECT_TOSHOST
:
1575 (void)printf("Redirect Type of Service and Host");
1578 (void)printf("Redirect--Bad Code: %d", icp
->icmp_code
);
1581 (void)printf(" New router addr: %s",
1582 pr_addr(&icp
->icmp_hun
.ih_gwaddr
));
1587 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1589 (void)printf("Echo Request: ID=%d seq=%d",
1590 ntohs(icp
->icmp_id
), ntohs(icp
->icmp_seq
));
1593 case ICMP_ECHOREPLY
:
1594 /* displaying other's pings is too noisey */
1596 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1598 (void)printf("Echo Reply: ID=%d seq=%d",
1599 ntohs(icp
->icmp_id
), ntohs(icp
->icmp_seq
));
1605 case ICMP_ROUTERADVERT
:
1606 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1608 (void)printf("Router Discovery Advert");
1611 case ICMP_ROUTERSOLICIT
:
1612 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1614 (void)printf("Router Discovery Solicit");
1618 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1620 switch (icp
->icmp_code
) {
1621 case ICMP_TIMXCEED_INTRANS
:
1622 (void)printf("Time To Live exceeded");
1624 case ICMP_TIMXCEED_REASS
:
1625 (void)printf("Frag reassembly time exceeded");
1628 (void)printf("Time exceeded, Bad Code: %d",
1635 case ICMP_PARAMPROB
:
1636 if (!ck_pr_icmph(icp
, from
, cc
, 1))
1638 (void)printf("Parameter problem: pointer = 0x%02x",
1639 icp
->icmp_hun
.ih_pptr
);
1644 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1646 (void)printf("Timestamp");
1649 case ICMP_TSTAMPREPLY
:
1650 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1652 (void)printf("Timestamp Reply");
1656 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1658 (void)printf("Information Request");
1661 case ICMP_IREQREPLY
:
1662 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1664 (void)printf("Information Reply");
1668 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1670 (void)printf("Address Mask Request");
1673 case ICMP_MASKREPLY
:
1674 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1676 (void)printf("Address Mask Reply");
1680 if (!ck_pr_icmph(icp
, from
, cc
, 0))
1682 (void)printf("Bad ICMP type: %d", icp
->icmp_type
);
1683 if (pingflags
& F_VERBOSE
)
1692 * Print an IP header with options.
1695 pr_iph(struct icmp
*icp
,
1700 struct ip ipb
, *ip
= &ipb
;
1702 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1704 hlen
= ip
->ip_hl
<< 2;
1705 cp
= (u_char
*) &icp
->icmp_data
[20]; /* point to options */
1707 (void)printf("\n Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
1708 (void)printf(" %1x %1x %02x %04x %04x",
1709 ip
->ip_v
, ip
->ip_hl
, ip
->ip_tos
, ip
->ip_len
, ip
->ip_id
);
1710 (void)printf(" %1x %04x",
1711 ((ip
->ip_off
)&0xe000)>>13, (ip
->ip_off
)&0x1fff);
1712 (void)printf(" %02x %02x %04x",
1713 ip
->ip_ttl
, ip
->ip_p
, ip
->ip_sum
);
1714 (void)printf(" %15s ",
1715 inet_ntoa(*(struct in_addr
*)&ip
->ip_src
.s_addr
));
1716 (void)printf(" %s ", inet_ntoa(*(struct in_addr
*)&ip
->ip_dst
.s_addr
));
1717 /* dump any option bytes */
1718 while (hlen
-- > 20 && cp
< (u_char
*)icp
+cc
) {
1719 (void)printf("%02x", *cp
++);
1724 * Print an ASCII host address starting from a string of bytes.
1727 pr_saddr(u_char
*cp
)
1730 struct in_addr addr
;
1733 l
= (l
<<8) + (u_char
)*++cp
;
1734 l
= (l
<<8) + (u_char
)*++cp
;
1735 l
= (l
<<8) + (u_char
)*++cp
;
1736 addr
.s_addr
= htonl(l
);
1737 (void)printf("\t%s", (l
== 0) ? "0.0.0.0" : pr_addr(&addr
));
1742 * Return an ASCII host address
1743 * as a dotted quad and optionally with a hostname
1746 pr_addr(struct in_addr
*addr
) /* in network order */
1749 static char buf
[MAXHOSTNAMELEN
+4+16+1];
1751 if ((pingflags
& F_NUMERIC
)
1752 || !(hp
= gethostbyaddr((char *)addr
, sizeof(*addr
), AF_INET
))) {
1753 (void)snprintf(buf
, sizeof(buf
), "%s", inet_ntoa(*addr
));
1755 (void)snprintf(buf
, sizeof(buf
), "%s (%s)", hp
->h_name
,
1763 * Dump some info on a returned (via ICMP) IP packet.
1766 pr_retip(struct icmp
*icp
,
1771 struct ip ipb
, *ip
= &ipb
;
1773 (void) memcpy(ip
, icp
->icmp_data
, sizeof(*ip
));
1775 if (pingflags
& F_VERBOSE
)
1778 hlen
= ip
->ip_hl
<< 2;
1779 cp
= (u_char
*) &icp
->icmp_data
[hlen
];
1781 if (ip
->ip_p
== IPPROTO_TCP
) {
1782 if (pingflags
& F_VERBOSE
)
1783 (void)printf("\n TCP: from port %u, to port %u",
1784 (*cp
*256+*(cp
+1)), (*(cp
+2)*256+*(cp
+3)));
1785 } else if (ip
->ip_p
== IPPROTO_UDP
) {
1786 if (pingflags
& F_VERBOSE
)
1787 (void)printf("\n UDP: from port %u, to port %u",
1788 (*cp
*256+*(cp
+1)), (*(cp
+2)*256+*(cp
+3)));
1789 } else if (ip
->ip_p
== IPPROTO_ICMP
) {
1791 (void) memcpy(&icp2
, cp
, sizeof(icp2
));
1792 if (icp2
.icmp_type
== ICMP_ECHO
) {
1793 if (pingflags
& F_VERBOSE
)
1794 (void)printf("\n ID=%u icmp_seq=%u",
1795 ntohs((u_int16_t
)icp2
.icmp_id
),
1796 ntohs((u_int16_t
)icp2
.icmp_seq
));
1798 (void)printf(" for icmp_seq=%u",
1799 ntohs((u_int16_t
)icp2
.icmp_seq
));
1811 for (cp
= fill_pat
; *cp
!= '\0'; cp
++) {
1812 if (!isxdigit((unsigned char)*cp
))
1815 if (cp
== fill_pat
|| *cp
!= '\0' || (cp
-fill_pat
) > 16*2) {
1816 (void)fflush(stdout
);
1817 errx(1, "\"-p %s\": patterns must be specified with"
1818 " 1-32 hex digits\n",
1822 i
= sscanf(fill_pat
,
1823 "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1824 &pat
[0], &pat
[1], &pat
[2], &pat
[3],
1825 &pat
[4], &pat
[5], &pat
[6], &pat
[7],
1826 &pat
[8], &pat
[9], &pat
[10], &pat
[11],
1827 &pat
[12], &pat
[13], &pat
[14], &pat
[15]);
1829 for (k
= phdrlen
, j
= 0; k
<= datalen
; k
++) {
1830 opack_icmp
.icmp_data
[k
] = pat
[j
];
1835 if (!(pingflags
& F_QUIET
)) {
1836 (void)printf("PATTERN: 0x");
1838 (void)printf("%02x",
1839 (u_char
)opack_icmp
.icmp_data
[phdrlen
+ j
]);
1849 static u_int32_t rnd
;
1852 for (i
= phdrlen
; i
< datalen
; i
++) {
1853 rnd
= (3141592621U * rnd
+ 663896637U);
1854 opack_icmp
.icmp_data
[i
] = rnd
>>24;
1860 gethost(const char *arg
,
1862 struct sockaddr_in
*sa
,
1868 (void)memset(sa
, 0, sizeof(*sa
));
1869 sa
->sin_family
= AF_INET
;
1870 sa
->sin_len
= sizeof(struct sockaddr_in
);
1872 /* If it is an IP address, try to convert it to a name to
1873 * have something nice to display.
1875 if (inet_aton(name
, &sa
->sin_addr
) != 0) {
1877 if (pingflags
& F_NUMERIC
)
1880 hp
= gethostbyaddr((char *)&sa
->sin_addr
,
1881 sizeof(sa
->sin_addr
),
1883 (void)strlcpy(realname
, hp
? hp
->h_name
: name
,
1889 hp
= gethostbyname(name
);
1891 errx(1, "Cannot resolve \"%s\" (%s)",name
,hstrerror(h_errno
));
1893 if (hp
->h_addrtype
!= AF_INET
)
1894 errx(1, "%s only supported with IP", arg
);
1896 (void)memcpy(&sa
->sin_addr
, hp
->h_addr
, sizeof(sa
->sin_addr
));
1899 (void)strlcpy(realname
, hp
->h_name
, realname_len
);
1907 #ifdef IPSEC_POLICY_IPSEC
1908 #define IPSECOPT "\n [-E policy] "
1910 #define IPSECOPT "\n [-AE] "
1911 #endif /*IPSEC_POLICY_IPSEC*/
1916 (void)fprintf(stderr
, "usage: \n"
1917 "%s [-aCDdfLnoPQqRrv] [-c count] [-g gateway] [-h host]"
1918 " [-I addr] [-i interval]\n"
1919 " [-l preload] [-p pattern] [-s size] [-T ttl] [-t tos]"
1920 " [-w maxwait] " IPSECOPT
"host\n",