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