1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ping_common.h"
2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <ctype.h>
3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sched.h>
4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <math.h>
5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint options;
7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint mark;
9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint sndbuf;
10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ttl;
11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint rtt;
12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint rtt_addend;
13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti__u16 acked;
14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct rcvd_table rcvd_tbl;
167618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colittiint using_ping_socket = 1;
17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* counters */
20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong npackets;			/* max packets to transmit */
21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nreceived;			/* # of packets we got back */
22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nrepeats;			/* number of duplicates */
23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong ntransmitted;		/* sequence # for outbound packets = #sent */
24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nchecksum;			/* replies with bad checksum */
25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nerrors;			/* icmp errors */
26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint interval = 1000;		/* interval between packets (msec) */
27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint preload;
28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint deadline = 0;		/* time to die */
29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint lingertime = MAXWAIT*1000;
30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct timeval start_time, cur_time;
31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int exiting;
32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int status_snapshot;
33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint confirm = 0;
34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int in_pr_addr = 0;	/* pr_addr() is executing */
35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittijmp_buf pr_addr_jmp;
36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Stupid workarounds for bugs/missing functionality in older linuces.
38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * i.e. for linux-2.2 */
40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint confirm_flag = MSG_CONFIRM;
41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* And this is workaround for bug in IP_RECVERR on raw sockets which is present
42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * in linux-2.2.[0-19], linux-2.4.[0-7] */
43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint working_recverr;
44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* timing */
46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint timing;			/* flag to do timing */
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong tmin = LONG_MAX;		/* minimum round trip time */
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong tmax;			/* maximum round trip time */
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Message for rpm maintainers: have _shame_. If you want
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * to fix something send the patch to me for sanity checking.
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * "sparcfix" patch is a complete non-sense, apparenly the person
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * prepared it was stoned.
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong long tsum;			/* sum of all times, for doing average */
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong long tsum2;
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint  pipesize = -1;
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint datalen = DEFDATALEN;
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *hostname;
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint uid;
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiuid_t euid;
637618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colittiint ident = 0;			/* process id to identify our packets */
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int screen_width = INT_MAX;
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_value_t cap_raw = CAP_NET_RAW;
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_value_t cap_admin = CAP_NET_ADMIN;
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid limit_capabilities(void)
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap_cur_p;
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap_p;
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_flag_value_t cap_ok;
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_cur_p = cap_get_proc();
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_cur_p) {
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_get_proc");
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_p = cap_init();
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_p) {
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_init");
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_ok = CAP_CLEAR;
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok);
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok != CAP_CLEAR)
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET);
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_ok = CAP_CLEAR;
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok);
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok != CAP_CLEAR)
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET);
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_set_proc(cap_p) < 0) {
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_set_proc");
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: prctl");
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setuid(getuid()) < 0) {
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("setuid");
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: prctl");
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_p);
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_cur_p);
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	uid = getuid();
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	euid = geteuid();
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef CAPABILITIES
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (seteuid(uid)) {
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: setuid");
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint modify_capability(cap_value_t cap, cap_flag_value_t on)
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap_p = cap_get_proc();
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_flag_value_t cap_ok;
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int rc = -1;
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!cap_p) {
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_get_proc");
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out;
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_ok = CAP_CLEAR;
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok);
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_ok == CAP_CLEAR) {
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rc = on ? -1 : 0;
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out;
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on);
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_set_proc(cap_p) < 0) {
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_set_proc");
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out;
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap_p);
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rc = 0;
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout:
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_p)
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cap_free(cap_p);
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return rc;
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint modify_capability(int on)
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (seteuid(on ? euid : getuid())) {
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("seteuid");
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid drop_capabilities(void)
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_t cap = cap_init();
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cap_set_proc(cap) < 0) {
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: cap_set_proc");
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cap_free(cap);
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setuid(getuid())) {
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		perror("ping: setuid");
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(-1);
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
201924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colittivoid android_check_security(void)
202924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti{
203924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti	if (getauxval(AT_SECURE) != 0) {
204924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti		fprintf(stderr, "This version of ping should NOT run with privileges. Aborting\n");
205924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti		exit(1);
206924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti	}
207924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti}
208924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Fills all the outpack, excluding ICMP header, but _including_
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * timestamp area with supplied pattern.
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void fill(char *patp)
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int ii, jj, kk;
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int pat[16];
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *cp;
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u_char *bp = outpack+8;
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setlocale(LC_ALL, "C");
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (cp = patp; *cp; cp++) {
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!isxdigit(*cp)) {
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr,
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				"ping: patterns must be specified as hex digits.\n");
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	ii = sscanf(patp,
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	    &pat[13], &pat[14], &pat[15]);
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ii > 0) {
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			for (jj = 0; jj < ii; ++jj)
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				bp[jj + kk] = pat[jj];
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!(options & F_QUIET)) {
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("PATTERN: 0x");
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (jj = 0; jj < ii; ++jj)
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf("%02x", bp[jj] & 0xFF);
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("\n");
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setlocale(LC_ALL, "");
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid common_options(int ch)
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	switch(ch) {
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'a':
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_AUDIBLE;
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'A':
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_ADAPTIVE;
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'c':
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		npackets = atoi(optarg);
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (npackets <= 0) {
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad number of packets to transmit.\n");
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'd':
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_SO_DEBUG;
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'D':
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_PTIMEOFDAY;
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'i':		/* wait between sending packets */
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	{
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		double dbl;
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char *ep;
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		errno = 0;
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		dbl = strtod(optarg, &ep);
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (errno || *ep != '\0' ||
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		    !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) {
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad timing interval\n");
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		interval = (int)(dbl * 1000);
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_INTERVAL;
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'm':
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	{
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char *endp;
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		mark = (int)strtoul(optarg, &endp, 10);
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (mark < 0 || *endp != '\0') {
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "mark cannot be negative\n");
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_MARK;
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'w':
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		deadline = atoi(optarg);
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (deadline < 0) {
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad wait time.\n");
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'l':
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		preload = atoi(optarg);
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (preload <= 0) {
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", MAX_DUP_CHK);
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (preload > MAX_DUP_CHK)
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			preload = MAX_DUP_CHK;
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (uid && preload > 3) {
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: cannot set preload to value > 3\n");
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'O':
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_OUTSTANDING;
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'S':
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sndbuf = atoi(optarg);
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (sndbuf <= 0) {
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad sndbuf value.\n");
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'f':
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_FLOOD;
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		setbuf(stdout, (char *)NULL);
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* fallthrough to numeric - avoid gethostbyaddr during flood */
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'n':
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_NUMERIC;
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'p':		/* fill buffer with user pattern */
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_PINGFILLED;
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fill(optarg);
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'q':
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_QUIET;
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'r':
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_SO_DONTROUTE;
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 's':		/* size of packet to send */
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		datalen = atoi(optarg);
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (datalen < 0) {
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (datalen > maxpacket - 8) {
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: packet size too large: %d\n",
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				datalen);
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'v':
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_VERBOSE;
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'L':
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_NOLOOP;
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 't':
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_TTL;
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ttl = atoi(optarg);
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ttl < 0 || ttl > 255) {
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'U':
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_LATENCY;
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'B':
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_STRICTSOURCE;
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'W':
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		lingertime = atoi(optarg);
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "ping: bad linger time.\n");
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			exit(2);
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		lingertime *= 1000;
391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		break;
392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	case 'V':
393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("ping utility, iputils-%s\n", SNAPSHOT);
394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(0);
395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	default:
396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		abort();
397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sigexit(int signo)
402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	exiting = 1;
404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (in_pr_addr)
405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		longjmp(pr_addr_jmp, 0);
406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sigstatus(int signo)
409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	status_snapshot = 1;
411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint __schedule_exit(int next)
415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static unsigned long waittime;
417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct itimerval it;
418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (waittime)
420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return next;
421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nreceived) {
423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		waittime = 2 * tmax;
424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (waittime < 1000*interval)
425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			waittime = 1000*interval;
426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else
427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		waittime = lingertime*1000;
428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (next < 0 || next < waittime/1000)
430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		next = waittime/1000;
431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	it.it_interval.tv_sec = 0;
433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	it.it_interval.tv_usec = 0;
434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	it.it_value.tv_sec = waittime/1000000;
435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	it.it_value.tv_usec = waittime%1000000;
436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setitimer(ITIMER_REAL, &it, NULL);
437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return next;
438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic inline void update_interval(void)
441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int est = rtt ? rtt/8 : interval*1000;
443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	interval = (est+rtt_addend+500)/1000;
445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (uid && interval < MINUSERINTERVAL)
446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		interval = MINUSERINTERVAL;
447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Print timestamp
451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid print_timestamp(void)
453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_PTIMEOFDAY) {
455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct timeval tv;
456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		gettimeofday(&tv, NULL);
457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("[%lu.%06lu] ",
458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * pinger --
464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * will be added on by the kernel.  The ID field is our UNIX process ID,
466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * and the sequence number is an ascending integer.  The first 8 bytes
467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * of the data portion are used to hold a UNIX "timeval" struct in VAX
468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * byte-order, to compute the round-trip time.
469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pinger(void)
471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static int oom_count;
473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	static int tokens;
474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Have we already sent enough? If we have, return an arbitrary positive value. */
477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (exiting || (npackets && ntransmitted >= npackets && !deadline))
478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 1000;
479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Check that packets < rate*time + preload */
481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (cur_time.tv_sec == 0) {
482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		gettimeofday(&cur_time, NULL);
483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tokens = interval*(preload-1);
484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		long ntokens;
486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct timeval tv;
487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		gettimeofday(&tv, NULL);
489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			(tv.tv_usec-cur_time.tv_usec)/1000;
491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!interval) {
492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* Case of unlimited flood is special;
493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * if we see no reply, they are limited to 100pps */
494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ntokens < MININTERVAL && in_flight() >= preload)
495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return MININTERVAL-ntokens;
496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ntokens += tokens;
498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ntokens > interval*preload)
499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			ntokens = interval*preload;
500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ntokens < interval)
501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return interval - ntokens;
502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cur_time = tv;
504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tokens = ntokens - interval;
505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_OUTSTANDING) {
508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ntransmitted > 0 && !rcvd_test(ntransmitted)) {
509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			print_timestamp();
510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK));
511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fflush(stdout);
512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiresend:
516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i = send_probe();
517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (i == 0) {
519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		oom_count = 0;
520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		advance_ntransmitted();
521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!(options & F_QUIET) && (options & F_FLOOD)) {
522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* Very silly, but without this output with
523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * high preload or pipe size is very confusing. */
524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if ((preload < screen_width && pipesize < screen_width) ||
525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    in_flight() < screen_width)
526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				write_stdout(".", 1);
527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return interval - tokens;
529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* And handle various errors... */
532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (i > 0) {
533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Apparently, it is some fatal bug. */
534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		abort();
535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else if (errno == ENOBUFS || errno == ENOMEM) {
536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int nores_interval;
537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Device queue overflow or OOM. Packet is not sent. */
539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tokens = 0;
540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Slowdown. This works only in adaptive mode (option -A) */
541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (options&F_ADAPTIVE)
543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			update_interval();
544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		nores_interval = SCHINT(interval/2);
545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (nores_interval > 500)
546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			nores_interval = 500;
547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		oom_count++;
548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (oom_count*nores_interval < lingertime)
549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return nores_interval;
550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i = 0;
551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Fall to hard error. It is to avoid complete deadlock
552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * on stuck output device even when dealine was not requested.
553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * Expected timings are screwed up in any case, but we will
554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * exit some day. :-) */
555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else if (errno == EAGAIN) {
556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Socket buffer is full. */
557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tokens += interval;
558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return MININTERVAL;
559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if ((i=receive_error_msg()) > 0) {
561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* An ICMP error arrived. */
562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			tokens += interval;
563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return MININTERVAL;
564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Compatibility with old linuces. */
566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (i == 0 && confirm_flag && errno == EINVAL) {
567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			confirm_flag = 0;
568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			errno = 0;
569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!errno)
571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto resend;
572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Hard local error. Pretend we sent packet. */
575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	advance_ntransmitted();
576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (i == 0 && !(options & F_QUIET)) {
578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (options & F_FLOOD)
579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			write_stdout("E", 1);
580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		else
581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			perror("ping: sendmsg");
582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tokens = 0;
584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return SCHINT(interval);
585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid sock_setbufs(int icmp_sock, int alloc)
590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int rcvbuf, hold;
592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	socklen_t tmplen = sizeof(hold);
593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!sndbuf)
595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sndbuf = alloc;
596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rcvbuf = hold = alloc * preload;
599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (hold < 65536)
600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		hold = 65536;
601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (hold < rcvbuf)
604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Protocol independent setup and parameter checks. */
609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid setup(int icmp_sock)
611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int hold;
613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct timeval tv;
614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigset_t sset;
615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if ((options & F_FLOOD) && !(options & F_INTERVAL))
617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		interval = 0;
618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (uid && interval < MINUSERINTERVAL) {
620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(2);
622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (interval >= INT_MAX/preload) {
625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fprintf(stderr, "ping: illegal preload and/or interval\n");
626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		exit(2);
627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	hold = 1;
630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_SO_DEBUG)
631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_SO_DONTROUTE)
633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SO_TIMESTAMP
636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!(options&F_LATENCY)) {
637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int on = 1;
638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
642eadaaeadfa3d5fcf49f433896e9244f0a10a5f63Lorenzo Colitti#ifdef SO_MARK
643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_MARK) {
644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int ret;
645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		enable_capability_admin();
647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		ret = setsockopt(icmp_sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		disable_capability_admin();
649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ret == -1) {
651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* we probably dont wanna exit since old kernels
652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * dont support mark ..
653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			*/
654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "Warning: Failed to set mark %d\n", mark);
655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
657eadaaeadfa3d5fcf49f433896e9244f0a10a5f63Lorenzo Colitti#endif
658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Set some SNDTIMEO to prevent blocking forever
660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * on sends, when device is too slow or stalls. Just put limit
661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * of one second, or "interval", if it is less.
662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 */
663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tv.tv_sec = 1;
664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tv.tv_usec = 0;
665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (interval < 1000) {
666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tv.tv_sec = 0;
667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tv.tv_usec = 1000 * SCHINT(interval);
668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Set RCVTIMEO to "interval". Note, it is just an optimization
672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 * allowing to avoid redundant poll(). */
673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tv.tv_sec = SCHINT(interval)/1000;
674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tv.tv_usec = 1000*(SCHINT(interval)%1000);
675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		options |= F_FLOOD_POLL;
677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!(options & F_PINGFILLED)) {
679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int i;
680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		u_char *p = outpack+8;
681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Do not forget about case of small datalen,
683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * fill timestamp area too!
684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 */
685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (i = 0; i < datalen; ++i)
686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			*p++ = i;
687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
6897618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti	if (!using_ping_socket)
6905df1daf326001b8d7d91a8b726ded17e09309952Lorenzo Colitti		ident = htons(getpid() & 0xFFFF);
691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	set_signal(SIGINT, sigexit);
693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	set_signal(SIGALRM, sigexit);
694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	set_signal(SIGQUIT, sigstatus);
695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigemptyset(&sset);
697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sigprocmask(SIG_SETMASK, &sset, NULL);
698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	gettimeofday(&start_time, NULL);
700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (deadline) {
702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct itimerval it;
703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		it.it_interval.tv_sec = 0;
705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		it.it_interval.tv_usec = 0;
706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		it.it_value.tv_sec = deadline;
707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		it.it_value.tv_usec = 0;
708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		setitimer(ITIMER_REAL, &it, NULL);
709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (isatty(STDOUT_FILENO)) {
712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct winsize w;
713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (w.ws_col > 0)
716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				screen_width = w.ws_col;
717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid main_loop(int icmp_sock, __u8 *packet, int packlen)
722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char addrbuf[128];
724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char ans_data[4096];
725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iovec iov;
726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct msghdr msg;
727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct cmsghdr *c;
728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int cc;
729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int next;
730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int polling;
731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iov.iov_base = (char *)packet;
733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (;;) {
735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Check exit conditions. */
736313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (exiting)
737313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
738313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (npackets && nreceived + nerrors >= npackets)
739313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
740313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (deadline && nerrors)
741313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
742313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Check for and do special actions. */
743313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (status_snapshot)
744313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			status();
745313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
746313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Send probes scheduled to this time. */
747313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		do {
748313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			next = pinger();
749313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			next = schedule_exit(next);
750313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		} while (next <= 0);
751313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
752313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* "next" is time to send next probe, if positive.
753313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * If next<=0 send now or as soon as possible. */
754313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
755313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* Technical part. Looks wicked. Could be dropped,
756313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * if everyone used the newest kernel. :-)
757313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * Its purpose is:
758313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * 1. Provide intervals less than resolution of scheduler.
759313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 *    Solution: spinning.
760313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 * 2. Avoid use of poll(), when recvmsg() can provide
761313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 *    timed waiting (SO_RCVTIMEO). */
762313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		polling = 0;
763313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
764313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			int recv_expected = in_flight();
765313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
766313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* If we are here, recvmsg() is unable to wait for
767313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * required timeout. */
768313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
769313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				/* Very short timeout... So, if we wait for
770313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				 * something, we sleep for MININTERVAL.
771313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				 * Otherwise, spin! */
772313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (recv_expected) {
773313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					next = MININTERVAL;
774313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else {
775313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					next = 0;
776313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					/* When spinning, no reasons to poll.
777313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					 * Use nonblocking recvmsg() instead. */
778313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					polling = MSG_DONTWAIT;
779313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					/* But yield yet. */
780313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					sched_yield();
781313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
782313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
783313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
784313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!polling &&
785313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
786313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				struct pollfd pset;
787313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				pset.fd = icmp_sock;
788313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				pset.events = POLLIN|POLLERR;
789313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				pset.revents = 0;
790313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (poll(&pset, 1, next) < 1 ||
791313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				    !(pset.revents&(POLLIN|POLLERR)))
792313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					continue;
793313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				polling = MSG_DONTWAIT;
794313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
795313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
796313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
797313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (;;) {
798313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			struct timeval *recv_timep = NULL;
799313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			struct timeval recv_time;
800313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			int not_ours = 0; /* Raw socket can receive messages
801313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					   * destined to other running pings. */
802313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
803313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			iov.iov_len = packlen;
804313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(&msg, 0, sizeof(msg));
805313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_name = addrbuf;
806313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_namelen = sizeof(addrbuf);
807313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_iov = &iov;
808313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_iovlen = 1;
809313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_control = ans_data;
810313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			msg.msg_controllen = sizeof(ans_data);
811313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
812313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			cc = recvmsg(icmp_sock, &msg, polling);
813313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			polling = MSG_DONTWAIT;
814313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
815313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (cc < 0) {
816313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (errno == EAGAIN || errno == EINTR)
817313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					break;
818313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (!receive_error_msg()) {
819313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (errno) {
820313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						perror("ping: recvmsg");
821313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						break;
822313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					}
823313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					not_ours = 1;
824313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
825313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} else {
826313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
827313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SO_TIMESTAMP
828313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
829313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (c->cmsg_level != SOL_SOCKET ||
830313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					    c->cmsg_type != SO_TIMESTAMP)
831313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						continue;
832313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
833313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						continue;
834313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					recv_timep = (struct timeval*)CMSG_DATA(c);
835313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
836313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
837313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
838313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if ((options&F_LATENCY) || recv_timep == NULL) {
839313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if ((options&F_LATENCY) ||
840313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
841313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						gettimeofday(&recv_time, NULL);
842313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					recv_timep = &recv_time;
843313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
844313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
845313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
846313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
847313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
848313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* See? ... someone runs another ping on this host. */
8497618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti			if (not_ours && !using_ping_socket)
850313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				install_filter();
851313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
852313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* If nothing is in flight, "break" returns us to pinger. */
853313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (in_flight() == 0)
854313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
855313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
856313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			/* Otherwise, try to recvmsg() again. recvmsg()
857313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * is nonblocking after the first iteration, so that
858313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * if nothing is queued, it will receive EAGAIN
859313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			 * and return to pinger. */
860313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
861313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
862313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	finish();
863313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
864313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
865313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint gather_statistics(__u8 *icmph, int icmplen,
866313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      int cc, __u16 seq, int hops,
867313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      int csfailed, struct timeval *tv, char *from,
868313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      void (*pr_reply)(__u8 *icmph, int cc))
869313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
870313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int dupflag = 0;
871313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	long triptime = 0;
872313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u8 *ptr = icmph + icmplen;
873313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
874313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	++nreceived;
875313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!csfailed)
876313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		acknowledge(seq);
877313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
878313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (timing && cc >= 8+sizeof(struct timeval)) {
879313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct timeval tmp_tv;
880313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
881313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
882313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittirestamp:
883313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tvsub(tv, &tmp_tv);
884313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		triptime = tv->tv_sec * 1000000 + tv->tv_usec;
885313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (triptime < 0) {
886313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
887313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			triptime = 0;
888313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!(options & F_LATENCY)) {
889313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				gettimeofday(tv, NULL);
890313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				options |= F_LATENCY;
891313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				goto restamp;
892313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
893313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
894313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!csfailed) {
895313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			tsum += triptime;
896313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			tsum2 += (long long)triptime * (long long)triptime;
897313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (triptime < tmin)
898313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				tmin = triptime;
899313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (triptime > tmax)
900313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				tmax = triptime;
901313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!rtt)
902313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				rtt = triptime*8;
903313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else
904313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				rtt += triptime-rtt/8;
905313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (options&F_ADAPTIVE)
906313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				update_interval();
907313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
908313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
909313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
910313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (csfailed) {
911313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		++nchecksum;
912313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		--nreceived;
913313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else if (rcvd_test(seq)) {
914313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		++nrepeats;
915313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		--nreceived;
916313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		dupflag = 1;
917313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
918313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		rcvd_set(seq);
919313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		dupflag = 0;
920313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
921313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	confirm = confirm_flag;
922313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
923313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_QUIET)
924313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 1;
925313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
926313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (options & F_FLOOD) {
927313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!csfailed)
928313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			write_stdout("\b \b", 3);
929313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		else
930313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			write_stdout("\bC", 2);
931313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
932313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int i;
933313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		__u8 *cp, *dp;
934313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
935313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		print_timestamp();
936313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("%d bytes from %s:", cc, from);
937313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
938313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pr_reply)
939313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pr_reply(icmph, cc);
940313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
941313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (hops >= 0)
942313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf(" ttl=%d", hops);
943313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
944313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (cc < datalen+8) {
945313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf(" (truncated)\n");
946313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return 1;
947313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
948313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (timing) {
949313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (triptime >= 100000)
950313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				printf(" time=%ld ms", triptime/1000);
951313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else if (triptime >= 10000)
952313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				printf(" time=%ld.%01ld ms", triptime/1000,
953313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				       (triptime%1000)/100);
954313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else if (triptime >= 1000)
955313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				printf(" time=%ld.%02ld ms", triptime/1000,
956313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				       (triptime%1000)/10);
957313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else
958313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				printf(" time=%ld.%03ld ms", triptime/1000,
959313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				       triptime%1000);
960313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
961313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (dupflag)
962313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf(" (DUP!)");
963313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (csfailed)
964313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printf(" (BAD CHECKSUM!)");
965313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
966313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		/* check the data */
967313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		cp = ((u_char*)ptr) + sizeof(struct timeval);
968313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		dp = &outpack[8 + sizeof(struct timeval)];
969313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
970313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (*cp != *dp) {
971313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
972313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				       i, *dp, *cp);
973313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				cp = (u_char*)ptr + sizeof(struct timeval);
974313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
975313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if ((i % 32) == sizeof(struct timeval))
976313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						printf("\n#%d\t", i);
977313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					printf("%x ", *cp);
978313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
979313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
980313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
981313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
982313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
983313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
984313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
985313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
986313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic long llsqrt(long long a)
987313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
988313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	long long prev = ~((long long)1 << 63);
989313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	long long x = a;
990313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
991313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (x > 0) {
992313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		while (x < prev) {
993313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			prev = x;
994313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			x = (x+(a/x))/2;
995313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
996313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
997313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
998313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return (long)x;
999313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
1000313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1001313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
1002313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * finish --
1003313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *	Print out statistics, and give up.
1004313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
1005313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid finish(void)
1006313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
1007313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct timeval tv = cur_time;
1008313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *comma = "";
1009313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1010313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	tvsub(&tv, &start_time);
1011313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1012313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	putchar('\n');
1013313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fflush(stdout);
1014313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	printf("--- %s ping statistics ---\n", hostname);
1015313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	printf("%ld packets transmitted, ", ntransmitted);
1016313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	printf("%ld received", nreceived);
1017313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nrepeats)
1018313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf(", +%ld duplicates", nrepeats);
1019313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nchecksum)
1020313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf(", +%ld corrupted", nchecksum);
1021313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nerrors)
1022313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf(", +%ld errors", nerrors);
1023313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ntransmitted) {
1024313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf(", %d%% packet loss",
1025313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (int) ((((long long)(ntransmitted - nreceived)) * 100) /
1026313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      ntransmitted));
1027313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
1028313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
1029313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	putchar('\n');
1030313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1031313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nreceived && timing) {
1032313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		long tmdev;
1033313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1034313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tsum /= nreceived + nrepeats;
1035313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tsum2 /= nreceived + nrepeats;
1036313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tmdev = llsqrt(tsum2 - tsum * tsum);
1037313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1038313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
1039313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (long)tmin/1000, (long)tmin%1000,
1040313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (unsigned long)(tsum/1000), (long)(tsum%1000),
1041313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (long)tmax/1000, (long)tmax%1000,
1042313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (long)tmdev/1000, (long)tmdev%1000
1043313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       );
1044313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		comma = ", ";
1045313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
1046313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pipesize > 1) {
1047313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("%spipe %d", comma, pipesize);
1048313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		comma = ", ";
1049313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
1050313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) {
1051313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
1052313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printf("%sipg/ewma %d.%03d/%d.%03d ms",
1053313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
1054313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
1055313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	putchar('\n');
1056313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	exit(!nreceived || (deadline && nreceived < npackets));
1057313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
1058313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1059313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1060313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid status(void)
1061313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
1062313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int loss = 0;
1063313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	long tavg = 0;
1064313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1065313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	status_snapshot = 0;
1066313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1067313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (ntransmitted)
1068313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
1069313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1070313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
1071313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1072313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nreceived && timing) {
1073313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		tavg = tsum / (nreceived + nrepeats);
1074313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1075313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
1076313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (long)tmin/1000, (long)tmin%1000,
1077313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       tavg/1000, tavg%1000,
1078313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       rtt/8000, (rtt/8)%1000,
1079313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       (long)tmax/1000, (long)tmax%1000
1080313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		       );
1081313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
1082313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	fprintf(stderr, "\n");
1083313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
1084313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
1085ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colittiinline int is_ours(uint16_t id) {
10867618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti	return using_ping_socket || id == ident;
1087ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colitti}
1088ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colitti
1089