xref: /aosp_15_r20/external/iputils/ping_common.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
1*bd1f8aebSAndroid Build Coastguard Worker #include "ping_common.h"
2*bd1f8aebSAndroid Build Coastguard Worker #include <ctype.h>
3*bd1f8aebSAndroid Build Coastguard Worker #include <sched.h>
4*bd1f8aebSAndroid Build Coastguard Worker #include <math.h>
5*bd1f8aebSAndroid Build Coastguard Worker 
6*bd1f8aebSAndroid Build Coastguard Worker int options;
7*bd1f8aebSAndroid Build Coastguard Worker 
8*bd1f8aebSAndroid Build Coastguard Worker __u32 mark;
9*bd1f8aebSAndroid Build Coastguard Worker int sndbuf;
10*bd1f8aebSAndroid Build Coastguard Worker int ttl;
11*bd1f8aebSAndroid Build Coastguard Worker int rtt;
12*bd1f8aebSAndroid Build Coastguard Worker int rtt_addend;
13*bd1f8aebSAndroid Build Coastguard Worker __u16 acked;
14*bd1f8aebSAndroid Build Coastguard Worker 
15*bd1f8aebSAndroid Build Coastguard Worker struct rcvd_table rcvd_tbl;
16*bd1f8aebSAndroid Build Coastguard Worker int using_ping_socket = 1;
17*bd1f8aebSAndroid Build Coastguard Worker 
18*bd1f8aebSAndroid Build Coastguard Worker 
19*bd1f8aebSAndroid Build Coastguard Worker /* counters */
20*bd1f8aebSAndroid Build Coastguard Worker long npackets;			/* max packets to transmit */
21*bd1f8aebSAndroid Build Coastguard Worker long nreceived;			/* # of packets we got back */
22*bd1f8aebSAndroid Build Coastguard Worker long nrepeats;			/* number of duplicates */
23*bd1f8aebSAndroid Build Coastguard Worker long ntransmitted;		/* sequence # for outbound packets = #sent */
24*bd1f8aebSAndroid Build Coastguard Worker long nchecksum;			/* replies with bad checksum */
25*bd1f8aebSAndroid Build Coastguard Worker long nerrors;			/* icmp errors */
26*bd1f8aebSAndroid Build Coastguard Worker int interval = 1000;		/* interval between packets (msec) */
27*bd1f8aebSAndroid Build Coastguard Worker int preload;
28*bd1f8aebSAndroid Build Coastguard Worker int deadline = 0;		/* time to die */
29*bd1f8aebSAndroid Build Coastguard Worker int lingertime = MAXWAIT*1000;
30*bd1f8aebSAndroid Build Coastguard Worker struct timeval start_time, cur_time;
31*bd1f8aebSAndroid Build Coastguard Worker volatile int exiting;
32*bd1f8aebSAndroid Build Coastguard Worker volatile int status_snapshot;
33*bd1f8aebSAndroid Build Coastguard Worker int confirm = 0;
34*bd1f8aebSAndroid Build Coastguard Worker volatile int in_pr_addr = 0;	/* pr_addr() is executing */
35*bd1f8aebSAndroid Build Coastguard Worker jmp_buf pr_addr_jmp;
36*bd1f8aebSAndroid Build Coastguard Worker 
37*bd1f8aebSAndroid Build Coastguard Worker /* Stupid workarounds for bugs/missing functionality in older linuces.
38*bd1f8aebSAndroid Build Coastguard Worker  * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
39*bd1f8aebSAndroid Build Coastguard Worker  * i.e. for linux-2.2 */
40*bd1f8aebSAndroid Build Coastguard Worker int confirm_flag = MSG_CONFIRM;
41*bd1f8aebSAndroid Build Coastguard Worker /* And this is workaround for bug in IP_RECVERR on raw sockets which is present
42*bd1f8aebSAndroid Build Coastguard Worker  * in linux-2.2.[0-19], linux-2.4.[0-7] */
43*bd1f8aebSAndroid Build Coastguard Worker int working_recverr;
44*bd1f8aebSAndroid Build Coastguard Worker 
45*bd1f8aebSAndroid Build Coastguard Worker /* timing */
46*bd1f8aebSAndroid Build Coastguard Worker int timing;			/* flag to do timing */
47*bd1f8aebSAndroid Build Coastguard Worker long tmin = LONG_MAX;		/* minimum round trip time */
48*bd1f8aebSAndroid Build Coastguard Worker long tmax;			/* maximum round trip time */
49*bd1f8aebSAndroid Build Coastguard Worker /* Message for rpm maintainers: have _shame_. If you want
50*bd1f8aebSAndroid Build Coastguard Worker  * to fix something send the patch to me for sanity checking.
51*bd1f8aebSAndroid Build Coastguard Worker  * "sparcfix" patch is a complete non-sense, apparenly the person
52*bd1f8aebSAndroid Build Coastguard Worker  * prepared it was stoned.
53*bd1f8aebSAndroid Build Coastguard Worker  */
54*bd1f8aebSAndroid Build Coastguard Worker long long tsum;			/* sum of all times, for doing average */
55*bd1f8aebSAndroid Build Coastguard Worker long long tsum2;
56*bd1f8aebSAndroid Build Coastguard Worker int  pipesize = -1;
57*bd1f8aebSAndroid Build Coastguard Worker 
58*bd1f8aebSAndroid Build Coastguard Worker int datalen = DEFDATALEN;
59*bd1f8aebSAndroid Build Coastguard Worker 
60*bd1f8aebSAndroid Build Coastguard Worker char *hostname;
61*bd1f8aebSAndroid Build Coastguard Worker int uid;
62*bd1f8aebSAndroid Build Coastguard Worker uid_t euid;
63*bd1f8aebSAndroid Build Coastguard Worker int ident = 0;			/* process id to identify our packets */
64*bd1f8aebSAndroid Build Coastguard Worker 
65*bd1f8aebSAndroid Build Coastguard Worker static int screen_width = INT_MAX;
66*bd1f8aebSAndroid Build Coastguard Worker 
67*bd1f8aebSAndroid Build Coastguard Worker #define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
68*bd1f8aebSAndroid Build Coastguard Worker 
69*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
70*bd1f8aebSAndroid Build Coastguard Worker static cap_value_t cap_raw = CAP_NET_RAW;
71*bd1f8aebSAndroid Build Coastguard Worker static cap_value_t cap_admin = CAP_NET_ADMIN;
72*bd1f8aebSAndroid Build Coastguard Worker #endif
73*bd1f8aebSAndroid Build Coastguard Worker 
limit_capabilities(void)74*bd1f8aebSAndroid Build Coastguard Worker void limit_capabilities(void)
75*bd1f8aebSAndroid Build Coastguard Worker {
76*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
77*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap_cur_p;
78*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap_p;
79*bd1f8aebSAndroid Build Coastguard Worker 	cap_flag_value_t cap_ok;
80*bd1f8aebSAndroid Build Coastguard Worker 
81*bd1f8aebSAndroid Build Coastguard Worker 	cap_cur_p = cap_get_proc();
82*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_cur_p) {
83*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_get_proc");
84*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
85*bd1f8aebSAndroid Build Coastguard Worker 	}
86*bd1f8aebSAndroid Build Coastguard Worker 
87*bd1f8aebSAndroid Build Coastguard Worker 	cap_p = cap_init();
88*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_p) {
89*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_init");
90*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
91*bd1f8aebSAndroid Build Coastguard Worker 	}
92*bd1f8aebSAndroid Build Coastguard Worker 
93*bd1f8aebSAndroid Build Coastguard Worker 	cap_ok = CAP_CLEAR;
94*bd1f8aebSAndroid Build Coastguard Worker 	cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok);
95*bd1f8aebSAndroid Build Coastguard Worker 
96*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok != CAP_CLEAR)
97*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET);
98*bd1f8aebSAndroid Build Coastguard Worker 
99*bd1f8aebSAndroid Build Coastguard Worker 	cap_ok = CAP_CLEAR;
100*bd1f8aebSAndroid Build Coastguard Worker 	cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok);
101*bd1f8aebSAndroid Build Coastguard Worker 
102*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok != CAP_CLEAR)
103*bd1f8aebSAndroid Build Coastguard Worker 		cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET);
104*bd1f8aebSAndroid Build Coastguard Worker 
105*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_set_proc(cap_p) < 0) {
106*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_set_proc");
107*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
108*bd1f8aebSAndroid Build Coastguard Worker 	}
109*bd1f8aebSAndroid Build Coastguard Worker 
110*bd1f8aebSAndroid Build Coastguard Worker 	if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
111*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: prctl");
112*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
113*bd1f8aebSAndroid Build Coastguard Worker 	}
114*bd1f8aebSAndroid Build Coastguard Worker 
115*bd1f8aebSAndroid Build Coastguard Worker 	if (setuid(getuid()) < 0) {
116*bd1f8aebSAndroid Build Coastguard Worker 		perror("setuid");
117*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
118*bd1f8aebSAndroid Build Coastguard Worker 	}
119*bd1f8aebSAndroid Build Coastguard Worker 
120*bd1f8aebSAndroid Build Coastguard Worker 	if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
121*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: prctl");
122*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
123*bd1f8aebSAndroid Build Coastguard Worker 	}
124*bd1f8aebSAndroid Build Coastguard Worker 
125*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_p);
126*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_cur_p);
127*bd1f8aebSAndroid Build Coastguard Worker #endif
128*bd1f8aebSAndroid Build Coastguard Worker 	uid = getuid();
129*bd1f8aebSAndroid Build Coastguard Worker 	euid = geteuid();
130*bd1f8aebSAndroid Build Coastguard Worker #ifndef CAPABILITIES
131*bd1f8aebSAndroid Build Coastguard Worker 	if (seteuid(uid)) {
132*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: setuid");
133*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
134*bd1f8aebSAndroid Build Coastguard Worker 	}
135*bd1f8aebSAndroid Build Coastguard Worker #endif
136*bd1f8aebSAndroid Build Coastguard Worker }
137*bd1f8aebSAndroid Build Coastguard Worker 
138*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
modify_capability(cap_value_t cap,cap_flag_value_t on)139*bd1f8aebSAndroid Build Coastguard Worker int modify_capability(cap_value_t cap, cap_flag_value_t on)
140*bd1f8aebSAndroid Build Coastguard Worker {
141*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap_p = cap_get_proc();
142*bd1f8aebSAndroid Build Coastguard Worker 	cap_flag_value_t cap_ok;
143*bd1f8aebSAndroid Build Coastguard Worker 	int rc = -1;
144*bd1f8aebSAndroid Build Coastguard Worker 
145*bd1f8aebSAndroid Build Coastguard Worker 	if (!cap_p) {
146*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_get_proc");
147*bd1f8aebSAndroid Build Coastguard Worker 		goto out;
148*bd1f8aebSAndroid Build Coastguard Worker 	}
149*bd1f8aebSAndroid Build Coastguard Worker 
150*bd1f8aebSAndroid Build Coastguard Worker 	cap_ok = CAP_CLEAR;
151*bd1f8aebSAndroid Build Coastguard Worker 	cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok);
152*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_ok == CAP_CLEAR) {
153*bd1f8aebSAndroid Build Coastguard Worker 		rc = on ? -1 : 0;
154*bd1f8aebSAndroid Build Coastguard Worker 		goto out;
155*bd1f8aebSAndroid Build Coastguard Worker 	}
156*bd1f8aebSAndroid Build Coastguard Worker 
157*bd1f8aebSAndroid Build Coastguard Worker 	cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on);
158*bd1f8aebSAndroid Build Coastguard Worker 
159*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_set_proc(cap_p) < 0) {
160*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_set_proc");
161*bd1f8aebSAndroid Build Coastguard Worker 		goto out;
162*bd1f8aebSAndroid Build Coastguard Worker 	}
163*bd1f8aebSAndroid Build Coastguard Worker 
164*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap_p);
165*bd1f8aebSAndroid Build Coastguard Worker 
166*bd1f8aebSAndroid Build Coastguard Worker 	rc = 0;
167*bd1f8aebSAndroid Build Coastguard Worker out:
168*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_p)
169*bd1f8aebSAndroid Build Coastguard Worker 		cap_free(cap_p);
170*bd1f8aebSAndroid Build Coastguard Worker 	return rc;
171*bd1f8aebSAndroid Build Coastguard Worker }
172*bd1f8aebSAndroid Build Coastguard Worker #else
modify_capability(int on)173*bd1f8aebSAndroid Build Coastguard Worker int modify_capability(int on)
174*bd1f8aebSAndroid Build Coastguard Worker {
175*bd1f8aebSAndroid Build Coastguard Worker 	if (seteuid(on ? euid : getuid())) {
176*bd1f8aebSAndroid Build Coastguard Worker 		perror("seteuid");
177*bd1f8aebSAndroid Build Coastguard Worker 		return -1;
178*bd1f8aebSAndroid Build Coastguard Worker 	}
179*bd1f8aebSAndroid Build Coastguard Worker 
180*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
181*bd1f8aebSAndroid Build Coastguard Worker }
182*bd1f8aebSAndroid Build Coastguard Worker #endif
183*bd1f8aebSAndroid Build Coastguard Worker 
drop_capabilities(void)184*bd1f8aebSAndroid Build Coastguard Worker void drop_capabilities(void)
185*bd1f8aebSAndroid Build Coastguard Worker {
186*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
187*bd1f8aebSAndroid Build Coastguard Worker 	cap_t cap = cap_init();
188*bd1f8aebSAndroid Build Coastguard Worker 	if (cap_set_proc(cap) < 0) {
189*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: cap_set_proc");
190*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
191*bd1f8aebSAndroid Build Coastguard Worker 	}
192*bd1f8aebSAndroid Build Coastguard Worker 	cap_free(cap);
193*bd1f8aebSAndroid Build Coastguard Worker #else
194*bd1f8aebSAndroid Build Coastguard Worker 	if (setuid(getuid())) {
195*bd1f8aebSAndroid Build Coastguard Worker 		perror("ping: setuid");
196*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
197*bd1f8aebSAndroid Build Coastguard Worker 	}
198*bd1f8aebSAndroid Build Coastguard Worker #endif
199*bd1f8aebSAndroid Build Coastguard Worker }
200*bd1f8aebSAndroid Build Coastguard Worker 
android_check_security(void)201*bd1f8aebSAndroid Build Coastguard Worker void android_check_security(void)
202*bd1f8aebSAndroid Build Coastguard Worker {
203*bd1f8aebSAndroid Build Coastguard Worker 	if (getauxval(AT_SECURE) != 0) {
204*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, "This version of ping should NOT run with privileges. Aborting\n");
205*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
206*bd1f8aebSAndroid Build Coastguard Worker 	}
207*bd1f8aebSAndroid Build Coastguard Worker }
208*bd1f8aebSAndroid Build Coastguard Worker 
209*bd1f8aebSAndroid Build Coastguard Worker /* Fills all the outpack, excluding ICMP header, but _including_
210*bd1f8aebSAndroid Build Coastguard Worker  * timestamp area with supplied pattern.
211*bd1f8aebSAndroid Build Coastguard Worker  */
fill(char * patp)212*bd1f8aebSAndroid Build Coastguard Worker static void fill(char *patp)
213*bd1f8aebSAndroid Build Coastguard Worker {
214*bd1f8aebSAndroid Build Coastguard Worker 	int ii, jj, kk;
215*bd1f8aebSAndroid Build Coastguard Worker 	int pat[16];
216*bd1f8aebSAndroid Build Coastguard Worker 	char *cp;
217*bd1f8aebSAndroid Build Coastguard Worker 	u_char *bp = outpack+8;
218*bd1f8aebSAndroid Build Coastguard Worker 
219*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
220*bd1f8aebSAndroid Build Coastguard Worker 	setlocale(LC_ALL, "C");
221*bd1f8aebSAndroid Build Coastguard Worker #endif
222*bd1f8aebSAndroid Build Coastguard Worker 
223*bd1f8aebSAndroid Build Coastguard Worker 	for (cp = patp; *cp; cp++) {
224*bd1f8aebSAndroid Build Coastguard Worker 		if (!isxdigit(*cp)) {
225*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr,
226*bd1f8aebSAndroid Build Coastguard Worker 				"ping: patterns must be specified as hex digits.\n");
227*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
228*bd1f8aebSAndroid Build Coastguard Worker 		}
229*bd1f8aebSAndroid Build Coastguard Worker 	}
230*bd1f8aebSAndroid Build Coastguard Worker 	ii = sscanf(patp,
231*bd1f8aebSAndroid Build Coastguard Worker 	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
232*bd1f8aebSAndroid Build Coastguard Worker 	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
233*bd1f8aebSAndroid Build Coastguard Worker 	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
234*bd1f8aebSAndroid Build Coastguard Worker 	    &pat[13], &pat[14], &pat[15]);
235*bd1f8aebSAndroid Build Coastguard Worker 
236*bd1f8aebSAndroid Build Coastguard Worker 	if (ii > 0) {
237*bd1f8aebSAndroid Build Coastguard Worker 		for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
238*bd1f8aebSAndroid Build Coastguard Worker 			for (jj = 0; jj < ii; ++jj)
239*bd1f8aebSAndroid Build Coastguard Worker 				bp[jj + kk] = pat[jj];
240*bd1f8aebSAndroid Build Coastguard Worker 	}
241*bd1f8aebSAndroid Build Coastguard Worker 	if (!(options & F_QUIET)) {
242*bd1f8aebSAndroid Build Coastguard Worker 		printf("PATTERN: 0x");
243*bd1f8aebSAndroid Build Coastguard Worker 		for (jj = 0; jj < ii; ++jj)
244*bd1f8aebSAndroid Build Coastguard Worker 			printf("%02x", bp[jj] & 0xFF);
245*bd1f8aebSAndroid Build Coastguard Worker 		printf("\n");
246*bd1f8aebSAndroid Build Coastguard Worker 	}
247*bd1f8aebSAndroid Build Coastguard Worker 
248*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
249*bd1f8aebSAndroid Build Coastguard Worker 	setlocale(LC_ALL, "");
250*bd1f8aebSAndroid Build Coastguard Worker #endif
251*bd1f8aebSAndroid Build Coastguard Worker }
252*bd1f8aebSAndroid Build Coastguard Worker 
common_options(int ch)253*bd1f8aebSAndroid Build Coastguard Worker void common_options(int ch)
254*bd1f8aebSAndroid Build Coastguard Worker {
255*bd1f8aebSAndroid Build Coastguard Worker 	switch(ch) {
256*bd1f8aebSAndroid Build Coastguard Worker 	case 'a':
257*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_AUDIBLE;
258*bd1f8aebSAndroid Build Coastguard Worker 		break;
259*bd1f8aebSAndroid Build Coastguard Worker 	case 'A':
260*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_ADAPTIVE;
261*bd1f8aebSAndroid Build Coastguard Worker 		break;
262*bd1f8aebSAndroid Build Coastguard Worker 	case 'c':
263*bd1f8aebSAndroid Build Coastguard Worker 		npackets = atoi(optarg);
264*bd1f8aebSAndroid Build Coastguard Worker 		if (npackets <= 0) {
265*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad number of packets to transmit.\n");
266*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
267*bd1f8aebSAndroid Build Coastguard Worker 		}
268*bd1f8aebSAndroid Build Coastguard Worker 		break;
269*bd1f8aebSAndroid Build Coastguard Worker 	case 'd':
270*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_SO_DEBUG;
271*bd1f8aebSAndroid Build Coastguard Worker 		break;
272*bd1f8aebSAndroid Build Coastguard Worker 	case 'D':
273*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_PTIMEOFDAY;
274*bd1f8aebSAndroid Build Coastguard Worker 		break;
275*bd1f8aebSAndroid Build Coastguard Worker 	case 'i':		/* wait between sending packets */
276*bd1f8aebSAndroid Build Coastguard Worker 	{
277*bd1f8aebSAndroid Build Coastguard Worker 		double dbl;
278*bd1f8aebSAndroid Build Coastguard Worker 		char *ep;
279*bd1f8aebSAndroid Build Coastguard Worker 
280*bd1f8aebSAndroid Build Coastguard Worker 		errno = 0;
281*bd1f8aebSAndroid Build Coastguard Worker 		dbl = strtod(optarg, &ep);
282*bd1f8aebSAndroid Build Coastguard Worker 
283*bd1f8aebSAndroid Build Coastguard Worker 		if (errno || *ep != '\0' ||
284*bd1f8aebSAndroid Build Coastguard Worker 		    !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) {
285*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad timing interval\n");
286*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
287*bd1f8aebSAndroid Build Coastguard Worker 		}
288*bd1f8aebSAndroid Build Coastguard Worker 
289*bd1f8aebSAndroid Build Coastguard Worker 		interval = (int)(dbl * 1000);
290*bd1f8aebSAndroid Build Coastguard Worker 
291*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_INTERVAL;
292*bd1f8aebSAndroid Build Coastguard Worker 		break;
293*bd1f8aebSAndroid Build Coastguard Worker 	}
294*bd1f8aebSAndroid Build Coastguard Worker 	case 'm':
295*bd1f8aebSAndroid Build Coastguard Worker 	{
296*bd1f8aebSAndroid Build Coastguard Worker 		char *endp;
297*bd1f8aebSAndroid Build Coastguard Worker 		mark = strtoul(optarg, &endp, 0);
298*bd1f8aebSAndroid Build Coastguard Worker 		if (*endp != '\0') {
299*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: invalid mark %s\n", optarg);
300*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
301*bd1f8aebSAndroid Build Coastguard Worker 		}
302*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_MARK;
303*bd1f8aebSAndroid Build Coastguard Worker 		break;
304*bd1f8aebSAndroid Build Coastguard Worker 	}
305*bd1f8aebSAndroid Build Coastguard Worker 	case 'w':
306*bd1f8aebSAndroid Build Coastguard Worker 		deadline = atoi(optarg);
307*bd1f8aebSAndroid Build Coastguard Worker 		if (deadline < 0) {
308*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad wait time.\n");
309*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
310*bd1f8aebSAndroid Build Coastguard Worker 		}
311*bd1f8aebSAndroid Build Coastguard Worker 		break;
312*bd1f8aebSAndroid Build Coastguard Worker 	case 'l':
313*bd1f8aebSAndroid Build Coastguard Worker 		preload = atoi(optarg);
314*bd1f8aebSAndroid Build Coastguard Worker 		if (preload <= 0) {
315*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", MAX_DUP_CHK);
316*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
317*bd1f8aebSAndroid Build Coastguard Worker 		}
318*bd1f8aebSAndroid Build Coastguard Worker 		if (preload > MAX_DUP_CHK)
319*bd1f8aebSAndroid Build Coastguard Worker 			preload = MAX_DUP_CHK;
320*bd1f8aebSAndroid Build Coastguard Worker 		if (uid && preload > 3) {
321*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: cannot set preload to value > 3\n");
322*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
323*bd1f8aebSAndroid Build Coastguard Worker 		}
324*bd1f8aebSAndroid Build Coastguard Worker 		break;
325*bd1f8aebSAndroid Build Coastguard Worker 	case 'O':
326*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_OUTSTANDING;
327*bd1f8aebSAndroid Build Coastguard Worker 		break;
328*bd1f8aebSAndroid Build Coastguard Worker 	case 'S':
329*bd1f8aebSAndroid Build Coastguard Worker 		sndbuf = atoi(optarg);
330*bd1f8aebSAndroid Build Coastguard Worker 		if (sndbuf <= 0) {
331*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad sndbuf value.\n");
332*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
333*bd1f8aebSAndroid Build Coastguard Worker 		}
334*bd1f8aebSAndroid Build Coastguard Worker 		break;
335*bd1f8aebSAndroid Build Coastguard Worker 	case 'f':
336*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_FLOOD;
337*bd1f8aebSAndroid Build Coastguard Worker 		setbuf(stdout, (char *)NULL);
338*bd1f8aebSAndroid Build Coastguard Worker 		/* fallthrough to numeric - avoid gethostbyaddr during flood */
339*bd1f8aebSAndroid Build Coastguard Worker 	case 'n':
340*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_NUMERIC;
341*bd1f8aebSAndroid Build Coastguard Worker 		break;
342*bd1f8aebSAndroid Build Coastguard Worker 	case 'p':		/* fill buffer with user pattern */
343*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_PINGFILLED;
344*bd1f8aebSAndroid Build Coastguard Worker 		fill(optarg);
345*bd1f8aebSAndroid Build Coastguard Worker 		break;
346*bd1f8aebSAndroid Build Coastguard Worker 	case 'q':
347*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_QUIET;
348*bd1f8aebSAndroid Build Coastguard Worker 		break;
349*bd1f8aebSAndroid Build Coastguard Worker 	case 'r':
350*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_SO_DONTROUTE;
351*bd1f8aebSAndroid Build Coastguard Worker 		break;
352*bd1f8aebSAndroid Build Coastguard Worker 	case 's':		/* size of packet to send */
353*bd1f8aebSAndroid Build Coastguard Worker 		datalen = atoi(optarg);
354*bd1f8aebSAndroid Build Coastguard Worker 		if (datalen < 0) {
355*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
356*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
357*bd1f8aebSAndroid Build Coastguard Worker 		}
358*bd1f8aebSAndroid Build Coastguard Worker 		if (datalen > maxpacket - 8) {
359*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: packet size too large: %d\n",
360*bd1f8aebSAndroid Build Coastguard Worker 				datalen);
361*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
362*bd1f8aebSAndroid Build Coastguard Worker 		}
363*bd1f8aebSAndroid Build Coastguard Worker 		break;
364*bd1f8aebSAndroid Build Coastguard Worker 	case 'v':
365*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_VERBOSE;
366*bd1f8aebSAndroid Build Coastguard Worker 		break;
367*bd1f8aebSAndroid Build Coastguard Worker 	case 'L':
368*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_NOLOOP;
369*bd1f8aebSAndroid Build Coastguard Worker 		break;
370*bd1f8aebSAndroid Build Coastguard Worker 	case 't':
371*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_TTL;
372*bd1f8aebSAndroid Build Coastguard Worker 		ttl = atoi(optarg);
373*bd1f8aebSAndroid Build Coastguard Worker 		if (ttl < 0 || ttl > 255) {
374*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
375*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
376*bd1f8aebSAndroid Build Coastguard Worker 		}
377*bd1f8aebSAndroid Build Coastguard Worker 		break;
378*bd1f8aebSAndroid Build Coastguard Worker 	case 'U':
379*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_LATENCY;
380*bd1f8aebSAndroid Build Coastguard Worker 		break;
381*bd1f8aebSAndroid Build Coastguard Worker 	case 'B':
382*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_STRICTSOURCE;
383*bd1f8aebSAndroid Build Coastguard Worker 		break;
384*bd1f8aebSAndroid Build Coastguard Worker 	case 'W':
385*bd1f8aebSAndroid Build Coastguard Worker 		lingertime = atoi(optarg);
386*bd1f8aebSAndroid Build Coastguard Worker 		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
387*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "ping: bad linger time.\n");
388*bd1f8aebSAndroid Build Coastguard Worker 			exit(2);
389*bd1f8aebSAndroid Build Coastguard Worker 		}
390*bd1f8aebSAndroid Build Coastguard Worker 		lingertime *= 1000;
391*bd1f8aebSAndroid Build Coastguard Worker 		break;
392*bd1f8aebSAndroid Build Coastguard Worker 	case 'V':
393*bd1f8aebSAndroid Build Coastguard Worker 		printf("ping utility, iputils-%s\n", SNAPSHOT);
394*bd1f8aebSAndroid Build Coastguard Worker 		exit(0);
395*bd1f8aebSAndroid Build Coastguard Worker 	default:
396*bd1f8aebSAndroid Build Coastguard Worker 		abort();
397*bd1f8aebSAndroid Build Coastguard Worker 	}
398*bd1f8aebSAndroid Build Coastguard Worker }
399*bd1f8aebSAndroid Build Coastguard Worker 
400*bd1f8aebSAndroid Build Coastguard Worker 
sigexit(int signo)401*bd1f8aebSAndroid Build Coastguard Worker static void sigexit(int signo)
402*bd1f8aebSAndroid Build Coastguard Worker {
403*bd1f8aebSAndroid Build Coastguard Worker 	exiting = 1;
404*bd1f8aebSAndroid Build Coastguard Worker 	if (in_pr_addr)
405*bd1f8aebSAndroid Build Coastguard Worker 		longjmp(pr_addr_jmp, 0);
406*bd1f8aebSAndroid Build Coastguard Worker }
407*bd1f8aebSAndroid Build Coastguard Worker 
sigstatus(int signo)408*bd1f8aebSAndroid Build Coastguard Worker static void sigstatus(int signo)
409*bd1f8aebSAndroid Build Coastguard Worker {
410*bd1f8aebSAndroid Build Coastguard Worker 	status_snapshot = 1;
411*bd1f8aebSAndroid Build Coastguard Worker }
412*bd1f8aebSAndroid Build Coastguard Worker 
413*bd1f8aebSAndroid Build Coastguard Worker 
__schedule_exit(int next)414*bd1f8aebSAndroid Build Coastguard Worker int __schedule_exit(int next)
415*bd1f8aebSAndroid Build Coastguard Worker {
416*bd1f8aebSAndroid Build Coastguard Worker 	static unsigned long waittime;
417*bd1f8aebSAndroid Build Coastguard Worker 	struct itimerval it;
418*bd1f8aebSAndroid Build Coastguard Worker 
419*bd1f8aebSAndroid Build Coastguard Worker 	if (waittime)
420*bd1f8aebSAndroid Build Coastguard Worker 		return next;
421*bd1f8aebSAndroid Build Coastguard Worker 
422*bd1f8aebSAndroid Build Coastguard Worker 	if (nreceived) {
423*bd1f8aebSAndroid Build Coastguard Worker 		waittime = 2 * tmax;
424*bd1f8aebSAndroid Build Coastguard Worker 		if (waittime < 1000*interval)
425*bd1f8aebSAndroid Build Coastguard Worker 			waittime = 1000*interval;
426*bd1f8aebSAndroid Build Coastguard Worker 	} else
427*bd1f8aebSAndroid Build Coastguard Worker 		waittime = lingertime*1000;
428*bd1f8aebSAndroid Build Coastguard Worker 
429*bd1f8aebSAndroid Build Coastguard Worker 	if (next < 0 || next < waittime/1000)
430*bd1f8aebSAndroid Build Coastguard Worker 		next = waittime/1000;
431*bd1f8aebSAndroid Build Coastguard Worker 
432*bd1f8aebSAndroid Build Coastguard Worker 	it.it_interval.tv_sec = 0;
433*bd1f8aebSAndroid Build Coastguard Worker 	it.it_interval.tv_usec = 0;
434*bd1f8aebSAndroid Build Coastguard Worker 	it.it_value.tv_sec = waittime/1000000;
435*bd1f8aebSAndroid Build Coastguard Worker 	it.it_value.tv_usec = waittime%1000000;
436*bd1f8aebSAndroid Build Coastguard Worker 	setitimer(ITIMER_REAL, &it, NULL);
437*bd1f8aebSAndroid Build Coastguard Worker 	return next;
438*bd1f8aebSAndroid Build Coastguard Worker }
439*bd1f8aebSAndroid Build Coastguard Worker 
update_interval(void)440*bd1f8aebSAndroid Build Coastguard Worker static inline void update_interval(void)
441*bd1f8aebSAndroid Build Coastguard Worker {
442*bd1f8aebSAndroid Build Coastguard Worker 	int est = rtt ? rtt/8 : interval*1000;
443*bd1f8aebSAndroid Build Coastguard Worker 
444*bd1f8aebSAndroid Build Coastguard Worker 	interval = (est+rtt_addend+500)/1000;
445*bd1f8aebSAndroid Build Coastguard Worker 	if (uid && interval < MINUSERINTERVAL)
446*bd1f8aebSAndroid Build Coastguard Worker 		interval = MINUSERINTERVAL;
447*bd1f8aebSAndroid Build Coastguard Worker }
448*bd1f8aebSAndroid Build Coastguard Worker 
449*bd1f8aebSAndroid Build Coastguard Worker /*
450*bd1f8aebSAndroid Build Coastguard Worker  * Print timestamp
451*bd1f8aebSAndroid Build Coastguard Worker  */
print_timestamp(void)452*bd1f8aebSAndroid Build Coastguard Worker void print_timestamp(void)
453*bd1f8aebSAndroid Build Coastguard Worker {
454*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_PTIMEOFDAY) {
455*bd1f8aebSAndroid Build Coastguard Worker 		struct timeval tv;
456*bd1f8aebSAndroid Build Coastguard Worker 		gettimeofday(&tv, NULL);
457*bd1f8aebSAndroid Build Coastguard Worker 		printf("[%lu.%06lu] ",
458*bd1f8aebSAndroid Build Coastguard Worker 		       (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
459*bd1f8aebSAndroid Build Coastguard Worker 	}
460*bd1f8aebSAndroid Build Coastguard Worker }
461*bd1f8aebSAndroid Build Coastguard Worker 
462*bd1f8aebSAndroid Build Coastguard Worker /*
463*bd1f8aebSAndroid Build Coastguard Worker  * pinger --
464*bd1f8aebSAndroid Build Coastguard Worker  * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
465*bd1f8aebSAndroid Build Coastguard Worker  * will be added on by the kernel.  The ID field is our UNIX process ID,
466*bd1f8aebSAndroid Build Coastguard Worker  * and the sequence number is an ascending integer.  The first 8 bytes
467*bd1f8aebSAndroid Build Coastguard Worker  * of the data portion are used to hold a UNIX "timeval" struct in VAX
468*bd1f8aebSAndroid Build Coastguard Worker  * byte-order, to compute the round-trip time.
469*bd1f8aebSAndroid Build Coastguard Worker  */
pinger(void)470*bd1f8aebSAndroid Build Coastguard Worker int pinger(void)
471*bd1f8aebSAndroid Build Coastguard Worker {
472*bd1f8aebSAndroid Build Coastguard Worker 	static int oom_count;
473*bd1f8aebSAndroid Build Coastguard Worker 	static int tokens;
474*bd1f8aebSAndroid Build Coastguard Worker 	int i;
475*bd1f8aebSAndroid Build Coastguard Worker 
476*bd1f8aebSAndroid Build Coastguard Worker 	/* Have we already sent enough? If we have, return an arbitrary positive value. */
477*bd1f8aebSAndroid Build Coastguard Worker 	if (exiting || (npackets && ntransmitted >= npackets && !deadline))
478*bd1f8aebSAndroid Build Coastguard Worker 		return 1000;
479*bd1f8aebSAndroid Build Coastguard Worker 
480*bd1f8aebSAndroid Build Coastguard Worker 	/* Check that packets < rate*time + preload */
481*bd1f8aebSAndroid Build Coastguard Worker 	if (cur_time.tv_sec == 0) {
482*bd1f8aebSAndroid Build Coastguard Worker 		gettimeofday(&cur_time, NULL);
483*bd1f8aebSAndroid Build Coastguard Worker 		tokens = interval*(preload-1);
484*bd1f8aebSAndroid Build Coastguard Worker 	} else {
485*bd1f8aebSAndroid Build Coastguard Worker 		long ntokens;
486*bd1f8aebSAndroid Build Coastguard Worker 		struct timeval tv;
487*bd1f8aebSAndroid Build Coastguard Worker 
488*bd1f8aebSAndroid Build Coastguard Worker 		gettimeofday(&tv, NULL);
489*bd1f8aebSAndroid Build Coastguard Worker 		ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
490*bd1f8aebSAndroid Build Coastguard Worker 			(tv.tv_usec-cur_time.tv_usec)/1000;
491*bd1f8aebSAndroid Build Coastguard Worker 		if (!interval) {
492*bd1f8aebSAndroid Build Coastguard Worker 			/* Case of unlimited flood is special;
493*bd1f8aebSAndroid Build Coastguard Worker 			 * if we see no reply, they are limited to 100pps */
494*bd1f8aebSAndroid Build Coastguard Worker 			if (ntokens < MININTERVAL && in_flight() >= preload)
495*bd1f8aebSAndroid Build Coastguard Worker 				return MININTERVAL-ntokens;
496*bd1f8aebSAndroid Build Coastguard Worker 		}
497*bd1f8aebSAndroid Build Coastguard Worker 		ntokens += tokens;
498*bd1f8aebSAndroid Build Coastguard Worker 		if (ntokens > interval*preload)
499*bd1f8aebSAndroid Build Coastguard Worker 			ntokens = interval*preload;
500*bd1f8aebSAndroid Build Coastguard Worker 		if (ntokens < interval)
501*bd1f8aebSAndroid Build Coastguard Worker 			return interval - ntokens;
502*bd1f8aebSAndroid Build Coastguard Worker 
503*bd1f8aebSAndroid Build Coastguard Worker 		cur_time = tv;
504*bd1f8aebSAndroid Build Coastguard Worker 		tokens = ntokens - interval;
505*bd1f8aebSAndroid Build Coastguard Worker 	}
506*bd1f8aebSAndroid Build Coastguard Worker 
507*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_OUTSTANDING) {
508*bd1f8aebSAndroid Build Coastguard Worker 		if (ntransmitted > 0 && !rcvd_test(ntransmitted)) {
509*bd1f8aebSAndroid Build Coastguard Worker 			print_timestamp();
510*bd1f8aebSAndroid Build Coastguard Worker 			printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK));
511*bd1f8aebSAndroid Build Coastguard Worker 			fflush(stdout);
512*bd1f8aebSAndroid Build Coastguard Worker 		}
513*bd1f8aebSAndroid Build Coastguard Worker 	}
514*bd1f8aebSAndroid Build Coastguard Worker 
515*bd1f8aebSAndroid Build Coastguard Worker resend:
516*bd1f8aebSAndroid Build Coastguard Worker 	i = send_probe();
517*bd1f8aebSAndroid Build Coastguard Worker 
518*bd1f8aebSAndroid Build Coastguard Worker 	if (i == 0) {
519*bd1f8aebSAndroid Build Coastguard Worker 		oom_count = 0;
520*bd1f8aebSAndroid Build Coastguard Worker 		advance_ntransmitted();
521*bd1f8aebSAndroid Build Coastguard Worker 		if (!(options & F_QUIET) && (options & F_FLOOD)) {
522*bd1f8aebSAndroid Build Coastguard Worker 			/* Very silly, but without this output with
523*bd1f8aebSAndroid Build Coastguard Worker 			 * high preload or pipe size is very confusing. */
524*bd1f8aebSAndroid Build Coastguard Worker 			if ((preload < screen_width && pipesize < screen_width) ||
525*bd1f8aebSAndroid Build Coastguard Worker 			    in_flight() < screen_width)
526*bd1f8aebSAndroid Build Coastguard Worker 				write_stdout(".", 1);
527*bd1f8aebSAndroid Build Coastguard Worker 		}
528*bd1f8aebSAndroid Build Coastguard Worker 		return interval - tokens;
529*bd1f8aebSAndroid Build Coastguard Worker 	}
530*bd1f8aebSAndroid Build Coastguard Worker 
531*bd1f8aebSAndroid Build Coastguard Worker 	/* And handle various errors... */
532*bd1f8aebSAndroid Build Coastguard Worker 	if (i > 0) {
533*bd1f8aebSAndroid Build Coastguard Worker 		/* Apparently, it is some fatal bug. */
534*bd1f8aebSAndroid Build Coastguard Worker 		abort();
535*bd1f8aebSAndroid Build Coastguard Worker 	} else if (errno == ENOBUFS || errno == ENOMEM) {
536*bd1f8aebSAndroid Build Coastguard Worker 		int nores_interval;
537*bd1f8aebSAndroid Build Coastguard Worker 
538*bd1f8aebSAndroid Build Coastguard Worker 		/* Device queue overflow or OOM. Packet is not sent. */
539*bd1f8aebSAndroid Build Coastguard Worker 		tokens = 0;
540*bd1f8aebSAndroid Build Coastguard Worker 		/* Slowdown. This works only in adaptive mode (option -A) */
541*bd1f8aebSAndroid Build Coastguard Worker 		rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
542*bd1f8aebSAndroid Build Coastguard Worker 		if (options&F_ADAPTIVE)
543*bd1f8aebSAndroid Build Coastguard Worker 			update_interval();
544*bd1f8aebSAndroid Build Coastguard Worker 		nores_interval = SCHINT(interval/2);
545*bd1f8aebSAndroid Build Coastguard Worker 		if (nores_interval > 500)
546*bd1f8aebSAndroid Build Coastguard Worker 			nores_interval = 500;
547*bd1f8aebSAndroid Build Coastguard Worker 		oom_count++;
548*bd1f8aebSAndroid Build Coastguard Worker 		if (oom_count*nores_interval < lingertime)
549*bd1f8aebSAndroid Build Coastguard Worker 			return nores_interval;
550*bd1f8aebSAndroid Build Coastguard Worker 		i = 0;
551*bd1f8aebSAndroid Build Coastguard Worker 		/* Fall to hard error. It is to avoid complete deadlock
552*bd1f8aebSAndroid Build Coastguard Worker 		 * on stuck output device even when dealine was not requested.
553*bd1f8aebSAndroid Build Coastguard Worker 		 * Expected timings are screwed up in any case, but we will
554*bd1f8aebSAndroid Build Coastguard Worker 		 * exit some day. :-) */
555*bd1f8aebSAndroid Build Coastguard Worker 	} else if (errno == EAGAIN) {
556*bd1f8aebSAndroid Build Coastguard Worker 		/* Socket buffer is full. */
557*bd1f8aebSAndroid Build Coastguard Worker 		tokens += interval;
558*bd1f8aebSAndroid Build Coastguard Worker 		return MININTERVAL;
559*bd1f8aebSAndroid Build Coastguard Worker 	} else {
560*bd1f8aebSAndroid Build Coastguard Worker 		if ((i=receive_error_msg()) > 0) {
561*bd1f8aebSAndroid Build Coastguard Worker 			/* An ICMP error arrived. */
562*bd1f8aebSAndroid Build Coastguard Worker 			tokens += interval;
563*bd1f8aebSAndroid Build Coastguard Worker 			return MININTERVAL;
564*bd1f8aebSAndroid Build Coastguard Worker 		}
565*bd1f8aebSAndroid Build Coastguard Worker 		/* Compatibility with old linuces. */
566*bd1f8aebSAndroid Build Coastguard Worker 		if (i == 0 && confirm_flag && errno == EINVAL) {
567*bd1f8aebSAndroid Build Coastguard Worker 			confirm_flag = 0;
568*bd1f8aebSAndroid Build Coastguard Worker 			errno = 0;
569*bd1f8aebSAndroid Build Coastguard Worker 		}
570*bd1f8aebSAndroid Build Coastguard Worker 		if (!errno)
571*bd1f8aebSAndroid Build Coastguard Worker 			goto resend;
572*bd1f8aebSAndroid Build Coastguard Worker 	}
573*bd1f8aebSAndroid Build Coastguard Worker 
574*bd1f8aebSAndroid Build Coastguard Worker 	/* Hard local error. Pretend we sent packet. */
575*bd1f8aebSAndroid Build Coastguard Worker 	advance_ntransmitted();
576*bd1f8aebSAndroid Build Coastguard Worker 
577*bd1f8aebSAndroid Build Coastguard Worker 	if (i == 0 && !(options & F_QUIET)) {
578*bd1f8aebSAndroid Build Coastguard Worker 		if (options & F_FLOOD)
579*bd1f8aebSAndroid Build Coastguard Worker 			write_stdout("E", 1);
580*bd1f8aebSAndroid Build Coastguard Worker 		else
581*bd1f8aebSAndroid Build Coastguard Worker 			perror("ping: sendmsg");
582*bd1f8aebSAndroid Build Coastguard Worker 	}
583*bd1f8aebSAndroid Build Coastguard Worker 	tokens = 0;
584*bd1f8aebSAndroid Build Coastguard Worker 	return SCHINT(interval);
585*bd1f8aebSAndroid Build Coastguard Worker }
586*bd1f8aebSAndroid Build Coastguard Worker 
587*bd1f8aebSAndroid Build Coastguard Worker /* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
588*bd1f8aebSAndroid Build Coastguard Worker 
sock_setbufs(int icmp_sock,int alloc)589*bd1f8aebSAndroid Build Coastguard Worker void sock_setbufs(int icmp_sock, int alloc)
590*bd1f8aebSAndroid Build Coastguard Worker {
591*bd1f8aebSAndroid Build Coastguard Worker 	int rcvbuf, hold;
592*bd1f8aebSAndroid Build Coastguard Worker 	socklen_t tmplen = sizeof(hold);
593*bd1f8aebSAndroid Build Coastguard Worker 
594*bd1f8aebSAndroid Build Coastguard Worker 	if (!sndbuf)
595*bd1f8aebSAndroid Build Coastguard Worker 		sndbuf = alloc;
596*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
597*bd1f8aebSAndroid Build Coastguard Worker 
598*bd1f8aebSAndroid Build Coastguard Worker 	rcvbuf = hold = alloc * preload;
599*bd1f8aebSAndroid Build Coastguard Worker 	if (hold < 65536)
600*bd1f8aebSAndroid Build Coastguard Worker 		hold = 65536;
601*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
602*bd1f8aebSAndroid Build Coastguard Worker 	if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
603*bd1f8aebSAndroid Build Coastguard Worker 		if (hold < rcvbuf)
604*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
605*bd1f8aebSAndroid Build Coastguard Worker 	}
606*bd1f8aebSAndroid Build Coastguard Worker }
607*bd1f8aebSAndroid Build Coastguard Worker 
sock_setmark(int icmp_sock)608*bd1f8aebSAndroid Build Coastguard Worker void sock_setmark(int icmp_sock) {
609*bd1f8aebSAndroid Build Coastguard Worker #ifdef SO_MARK
610*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_MARK) {
611*bd1f8aebSAndroid Build Coastguard Worker 		int ret;
612*bd1f8aebSAndroid Build Coastguard Worker 
613*bd1f8aebSAndroid Build Coastguard Worker 		enable_capability_admin();
614*bd1f8aebSAndroid Build Coastguard Worker 		ret = setsockopt(icmp_sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
615*bd1f8aebSAndroid Build Coastguard Worker 		disable_capability_admin();
616*bd1f8aebSAndroid Build Coastguard Worker 
617*bd1f8aebSAndroid Build Coastguard Worker 		if (ret == -1) {
618*bd1f8aebSAndroid Build Coastguard Worker 			/* we probably dont wanna exit since old kernels
619*bd1f8aebSAndroid Build Coastguard Worker 			 * dont support mark ..
620*bd1f8aebSAndroid Build Coastguard Worker 			*/
621*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "Warning: Failed to set mark %d\n", mark);
622*bd1f8aebSAndroid Build Coastguard Worker 		}
623*bd1f8aebSAndroid Build Coastguard Worker 	}
624*bd1f8aebSAndroid Build Coastguard Worker #endif
625*bd1f8aebSAndroid Build Coastguard Worker }
626*bd1f8aebSAndroid Build Coastguard Worker 
627*bd1f8aebSAndroid Build Coastguard Worker /* Protocol independent setup and parameter checks. */
628*bd1f8aebSAndroid Build Coastguard Worker 
setup(int icmp_sock)629*bd1f8aebSAndroid Build Coastguard Worker void setup(int icmp_sock)
630*bd1f8aebSAndroid Build Coastguard Worker {
631*bd1f8aebSAndroid Build Coastguard Worker 	int hold;
632*bd1f8aebSAndroid Build Coastguard Worker 	struct timeval tv;
633*bd1f8aebSAndroid Build Coastguard Worker 	sigset_t sset;
634*bd1f8aebSAndroid Build Coastguard Worker 
635*bd1f8aebSAndroid Build Coastguard Worker 	if ((options & F_FLOOD) && !(options & F_INTERVAL))
636*bd1f8aebSAndroid Build Coastguard Worker 		interval = 0;
637*bd1f8aebSAndroid Build Coastguard Worker 
638*bd1f8aebSAndroid Build Coastguard Worker 	if (uid && interval < MINUSERINTERVAL) {
639*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
640*bd1f8aebSAndroid Build Coastguard Worker 		exit(2);
641*bd1f8aebSAndroid Build Coastguard Worker 	}
642*bd1f8aebSAndroid Build Coastguard Worker 
643*bd1f8aebSAndroid Build Coastguard Worker 	if (interval >= INT_MAX/preload) {
644*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, "ping: illegal preload and/or interval\n");
645*bd1f8aebSAndroid Build Coastguard Worker 		exit(2);
646*bd1f8aebSAndroid Build Coastguard Worker 	}
647*bd1f8aebSAndroid Build Coastguard Worker 
648*bd1f8aebSAndroid Build Coastguard Worker 	hold = 1;
649*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_SO_DEBUG)
650*bd1f8aebSAndroid Build Coastguard Worker 		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
651*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_SO_DONTROUTE)
652*bd1f8aebSAndroid Build Coastguard Worker 		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
653*bd1f8aebSAndroid Build Coastguard Worker 
654*bd1f8aebSAndroid Build Coastguard Worker #ifdef SO_TIMESTAMP
655*bd1f8aebSAndroid Build Coastguard Worker 	if (!(options&F_LATENCY)) {
656*bd1f8aebSAndroid Build Coastguard Worker 		int on = 1;
657*bd1f8aebSAndroid Build Coastguard Worker 		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
658*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
659*bd1f8aebSAndroid Build Coastguard Worker 	}
660*bd1f8aebSAndroid Build Coastguard Worker #endif
661*bd1f8aebSAndroid Build Coastguard Worker 
662*bd1f8aebSAndroid Build Coastguard Worker 	sock_setmark(icmp_sock);
663*bd1f8aebSAndroid Build Coastguard Worker 
664*bd1f8aebSAndroid Build Coastguard Worker 	/* Set some SNDTIMEO to prevent blocking forever
665*bd1f8aebSAndroid Build Coastguard Worker 	 * on sends, when device is too slow or stalls. Just put limit
666*bd1f8aebSAndroid Build Coastguard Worker 	 * of one second, or "interval", if it is less.
667*bd1f8aebSAndroid Build Coastguard Worker 	 */
668*bd1f8aebSAndroid Build Coastguard Worker 	tv.tv_sec = 1;
669*bd1f8aebSAndroid Build Coastguard Worker 	tv.tv_usec = 0;
670*bd1f8aebSAndroid Build Coastguard Worker 	if (interval < 1000) {
671*bd1f8aebSAndroid Build Coastguard Worker 		tv.tv_sec = 0;
672*bd1f8aebSAndroid Build Coastguard Worker 		tv.tv_usec = 1000 * SCHINT(interval);
673*bd1f8aebSAndroid Build Coastguard Worker 	}
674*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
675*bd1f8aebSAndroid Build Coastguard Worker 
676*bd1f8aebSAndroid Build Coastguard Worker 	/* Set RCVTIMEO to "interval". Note, it is just an optimization
677*bd1f8aebSAndroid Build Coastguard Worker 	 * allowing to avoid redundant poll(). */
678*bd1f8aebSAndroid Build Coastguard Worker 	tv.tv_sec = SCHINT(interval)/1000;
679*bd1f8aebSAndroid Build Coastguard Worker 	tv.tv_usec = 1000*(SCHINT(interval)%1000);
680*bd1f8aebSAndroid Build Coastguard Worker 	if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
681*bd1f8aebSAndroid Build Coastguard Worker 		options |= F_FLOOD_POLL;
682*bd1f8aebSAndroid Build Coastguard Worker 
683*bd1f8aebSAndroid Build Coastguard Worker 	if (!(options & F_PINGFILLED)) {
684*bd1f8aebSAndroid Build Coastguard Worker 		int i;
685*bd1f8aebSAndroid Build Coastguard Worker 		u_char *p = outpack+8;
686*bd1f8aebSAndroid Build Coastguard Worker 
687*bd1f8aebSAndroid Build Coastguard Worker 		/* Do not forget about case of small datalen,
688*bd1f8aebSAndroid Build Coastguard Worker 		 * fill timestamp area too!
689*bd1f8aebSAndroid Build Coastguard Worker 		 */
690*bd1f8aebSAndroid Build Coastguard Worker 		for (i = 0; i < datalen; ++i)
691*bd1f8aebSAndroid Build Coastguard Worker 			*p++ = i;
692*bd1f8aebSAndroid Build Coastguard Worker 	}
693*bd1f8aebSAndroid Build Coastguard Worker 
694*bd1f8aebSAndroid Build Coastguard Worker 	if (!using_ping_socket)
695*bd1f8aebSAndroid Build Coastguard Worker 		ident = htons(getpid() & 0xFFFF);
696*bd1f8aebSAndroid Build Coastguard Worker 
697*bd1f8aebSAndroid Build Coastguard Worker 	set_signal(SIGINT, sigexit);
698*bd1f8aebSAndroid Build Coastguard Worker 	set_signal(SIGALRM, sigexit);
699*bd1f8aebSAndroid Build Coastguard Worker 	set_signal(SIGQUIT, sigstatus);
700*bd1f8aebSAndroid Build Coastguard Worker 
701*bd1f8aebSAndroid Build Coastguard Worker 	sigemptyset(&sset);
702*bd1f8aebSAndroid Build Coastguard Worker 	sigprocmask(SIG_SETMASK, &sset, NULL);
703*bd1f8aebSAndroid Build Coastguard Worker 
704*bd1f8aebSAndroid Build Coastguard Worker 	gettimeofday(&start_time, NULL);
705*bd1f8aebSAndroid Build Coastguard Worker 
706*bd1f8aebSAndroid Build Coastguard Worker 	if (deadline) {
707*bd1f8aebSAndroid Build Coastguard Worker 		struct itimerval it;
708*bd1f8aebSAndroid Build Coastguard Worker 
709*bd1f8aebSAndroid Build Coastguard Worker 		it.it_interval.tv_sec = 0;
710*bd1f8aebSAndroid Build Coastguard Worker 		it.it_interval.tv_usec = 0;
711*bd1f8aebSAndroid Build Coastguard Worker 		it.it_value.tv_sec = deadline;
712*bd1f8aebSAndroid Build Coastguard Worker 		it.it_value.tv_usec = 0;
713*bd1f8aebSAndroid Build Coastguard Worker 		setitimer(ITIMER_REAL, &it, NULL);
714*bd1f8aebSAndroid Build Coastguard Worker 	}
715*bd1f8aebSAndroid Build Coastguard Worker 
716*bd1f8aebSAndroid Build Coastguard Worker 	if (isatty(STDOUT_FILENO)) {
717*bd1f8aebSAndroid Build Coastguard Worker 		struct winsize w;
718*bd1f8aebSAndroid Build Coastguard Worker 
719*bd1f8aebSAndroid Build Coastguard Worker 		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
720*bd1f8aebSAndroid Build Coastguard Worker 			if (w.ws_col > 0)
721*bd1f8aebSAndroid Build Coastguard Worker 				screen_width = w.ws_col;
722*bd1f8aebSAndroid Build Coastguard Worker 		}
723*bd1f8aebSAndroid Build Coastguard Worker 	}
724*bd1f8aebSAndroid Build Coastguard Worker }
725*bd1f8aebSAndroid Build Coastguard Worker 
main_loop(int icmp_sock,__u8 * packet,int packlen)726*bd1f8aebSAndroid Build Coastguard Worker void main_loop(int icmp_sock, __u8 *packet, int packlen)
727*bd1f8aebSAndroid Build Coastguard Worker {
728*bd1f8aebSAndroid Build Coastguard Worker 	char addrbuf[128];
729*bd1f8aebSAndroid Build Coastguard Worker 	char ans_data[4096];
730*bd1f8aebSAndroid Build Coastguard Worker 	struct iovec iov;
731*bd1f8aebSAndroid Build Coastguard Worker 	struct msghdr msg;
732*bd1f8aebSAndroid Build Coastguard Worker 	struct cmsghdr *c;
733*bd1f8aebSAndroid Build Coastguard Worker 	int cc;
734*bd1f8aebSAndroid Build Coastguard Worker 	int next;
735*bd1f8aebSAndroid Build Coastguard Worker 	int polling;
736*bd1f8aebSAndroid Build Coastguard Worker 
737*bd1f8aebSAndroid Build Coastguard Worker 	iov.iov_base = (char *)packet;
738*bd1f8aebSAndroid Build Coastguard Worker 
739*bd1f8aebSAndroid Build Coastguard Worker 	for (;;) {
740*bd1f8aebSAndroid Build Coastguard Worker 		/* Check exit conditions. */
741*bd1f8aebSAndroid Build Coastguard Worker 		if (exiting)
742*bd1f8aebSAndroid Build Coastguard Worker 			break;
743*bd1f8aebSAndroid Build Coastguard Worker 		if (npackets && nreceived + nerrors >= npackets)
744*bd1f8aebSAndroid Build Coastguard Worker 			break;
745*bd1f8aebSAndroid Build Coastguard Worker 		if (deadline && nerrors)
746*bd1f8aebSAndroid Build Coastguard Worker 			break;
747*bd1f8aebSAndroid Build Coastguard Worker 		/* Check for and do special actions. */
748*bd1f8aebSAndroid Build Coastguard Worker 		if (status_snapshot)
749*bd1f8aebSAndroid Build Coastguard Worker 			status();
750*bd1f8aebSAndroid Build Coastguard Worker 
751*bd1f8aebSAndroid Build Coastguard Worker 		/* Send probes scheduled to this time. */
752*bd1f8aebSAndroid Build Coastguard Worker 		do {
753*bd1f8aebSAndroid Build Coastguard Worker 			next = pinger();
754*bd1f8aebSAndroid Build Coastguard Worker 			next = schedule_exit(next);
755*bd1f8aebSAndroid Build Coastguard Worker 		} while (next <= 0);
756*bd1f8aebSAndroid Build Coastguard Worker 
757*bd1f8aebSAndroid Build Coastguard Worker 		/* "next" is time to send next probe, if positive.
758*bd1f8aebSAndroid Build Coastguard Worker 		 * If next<=0 send now or as soon as possible. */
759*bd1f8aebSAndroid Build Coastguard Worker 
760*bd1f8aebSAndroid Build Coastguard Worker 		/* Technical part. Looks wicked. Could be dropped,
761*bd1f8aebSAndroid Build Coastguard Worker 		 * if everyone used the newest kernel. :-)
762*bd1f8aebSAndroid Build Coastguard Worker 		 * Its purpose is:
763*bd1f8aebSAndroid Build Coastguard Worker 		 * 1. Provide intervals less than resolution of scheduler.
764*bd1f8aebSAndroid Build Coastguard Worker 		 *    Solution: spinning.
765*bd1f8aebSAndroid Build Coastguard Worker 		 * 2. Avoid use of poll(), when recvmsg() can provide
766*bd1f8aebSAndroid Build Coastguard Worker 		 *    timed waiting (SO_RCVTIMEO). */
767*bd1f8aebSAndroid Build Coastguard Worker 		polling = 0;
768*bd1f8aebSAndroid Build Coastguard Worker 		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
769*bd1f8aebSAndroid Build Coastguard Worker 			int recv_expected = in_flight();
770*bd1f8aebSAndroid Build Coastguard Worker 
771*bd1f8aebSAndroid Build Coastguard Worker 			/* If we are here, recvmsg() is unable to wait for
772*bd1f8aebSAndroid Build Coastguard Worker 			 * required timeout. */
773*bd1f8aebSAndroid Build Coastguard Worker 			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
774*bd1f8aebSAndroid Build Coastguard Worker 				/* Very short timeout... So, if we wait for
775*bd1f8aebSAndroid Build Coastguard Worker 				 * something, we sleep for MININTERVAL.
776*bd1f8aebSAndroid Build Coastguard Worker 				 * Otherwise, spin! */
777*bd1f8aebSAndroid Build Coastguard Worker 				if (recv_expected) {
778*bd1f8aebSAndroid Build Coastguard Worker 					next = MININTERVAL;
779*bd1f8aebSAndroid Build Coastguard Worker 				} else {
780*bd1f8aebSAndroid Build Coastguard Worker 					next = 0;
781*bd1f8aebSAndroid Build Coastguard Worker 					/* When spinning, no reasons to poll.
782*bd1f8aebSAndroid Build Coastguard Worker 					 * Use nonblocking recvmsg() instead. */
783*bd1f8aebSAndroid Build Coastguard Worker 					polling = MSG_DONTWAIT;
784*bd1f8aebSAndroid Build Coastguard Worker 					/* But yield yet. */
785*bd1f8aebSAndroid Build Coastguard Worker 					sched_yield();
786*bd1f8aebSAndroid Build Coastguard Worker 				}
787*bd1f8aebSAndroid Build Coastguard Worker 			}
788*bd1f8aebSAndroid Build Coastguard Worker 
789*bd1f8aebSAndroid Build Coastguard Worker 			if (!polling &&
790*bd1f8aebSAndroid Build Coastguard Worker 			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
791*bd1f8aebSAndroid Build Coastguard Worker 				struct pollfd pset;
792*bd1f8aebSAndroid Build Coastguard Worker 				pset.fd = icmp_sock;
793*bd1f8aebSAndroid Build Coastguard Worker 				pset.events = POLLIN|POLLERR;
794*bd1f8aebSAndroid Build Coastguard Worker 				pset.revents = 0;
795*bd1f8aebSAndroid Build Coastguard Worker 				if (poll(&pset, 1, next) < 1 ||
796*bd1f8aebSAndroid Build Coastguard Worker 				    !(pset.revents&(POLLIN|POLLERR)))
797*bd1f8aebSAndroid Build Coastguard Worker 					continue;
798*bd1f8aebSAndroid Build Coastguard Worker 				polling = MSG_DONTWAIT;
799*bd1f8aebSAndroid Build Coastguard Worker 			}
800*bd1f8aebSAndroid Build Coastguard Worker 		}
801*bd1f8aebSAndroid Build Coastguard Worker 
802*bd1f8aebSAndroid Build Coastguard Worker 		for (;;) {
803*bd1f8aebSAndroid Build Coastguard Worker 			struct timeval *recv_timep = NULL;
804*bd1f8aebSAndroid Build Coastguard Worker 			struct timeval recv_time;
805*bd1f8aebSAndroid Build Coastguard Worker 			int not_ours = 0; /* Raw socket can receive messages
806*bd1f8aebSAndroid Build Coastguard Worker 					   * destined to other running pings. */
807*bd1f8aebSAndroid Build Coastguard Worker 
808*bd1f8aebSAndroid Build Coastguard Worker 			iov.iov_len = packlen;
809*bd1f8aebSAndroid Build Coastguard Worker 			memset(&msg, 0, sizeof(msg));
810*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_name = addrbuf;
811*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_namelen = sizeof(addrbuf);
812*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_iov = &iov;
813*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_iovlen = 1;
814*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_control = ans_data;
815*bd1f8aebSAndroid Build Coastguard Worker 			msg.msg_controllen = sizeof(ans_data);
816*bd1f8aebSAndroid Build Coastguard Worker 
817*bd1f8aebSAndroid Build Coastguard Worker 			cc = recvmsg(icmp_sock, &msg, polling);
818*bd1f8aebSAndroid Build Coastguard Worker 			polling = MSG_DONTWAIT;
819*bd1f8aebSAndroid Build Coastguard Worker 
820*bd1f8aebSAndroid Build Coastguard Worker 			if (cc < 0) {
821*bd1f8aebSAndroid Build Coastguard Worker 				if (errno == EAGAIN || errno == EINTR)
822*bd1f8aebSAndroid Build Coastguard Worker 					break;
823*bd1f8aebSAndroid Build Coastguard Worker 				if (!receive_error_msg()) {
824*bd1f8aebSAndroid Build Coastguard Worker 					if (errno) {
825*bd1f8aebSAndroid Build Coastguard Worker 						perror("ping: recvmsg");
826*bd1f8aebSAndroid Build Coastguard Worker 						break;
827*bd1f8aebSAndroid Build Coastguard Worker 					}
828*bd1f8aebSAndroid Build Coastguard Worker 					not_ours = 1;
829*bd1f8aebSAndroid Build Coastguard Worker 				}
830*bd1f8aebSAndroid Build Coastguard Worker 			} else {
831*bd1f8aebSAndroid Build Coastguard Worker 
832*bd1f8aebSAndroid Build Coastguard Worker #ifdef SO_TIMESTAMP
833*bd1f8aebSAndroid Build Coastguard Worker 				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
834*bd1f8aebSAndroid Build Coastguard Worker 					if (c->cmsg_level != SOL_SOCKET ||
835*bd1f8aebSAndroid Build Coastguard Worker 					    c->cmsg_type != SO_TIMESTAMP)
836*bd1f8aebSAndroid Build Coastguard Worker 						continue;
837*bd1f8aebSAndroid Build Coastguard Worker 					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
838*bd1f8aebSAndroid Build Coastguard Worker 						continue;
839*bd1f8aebSAndroid Build Coastguard Worker 					recv_timep = (struct timeval*)CMSG_DATA(c);
840*bd1f8aebSAndroid Build Coastguard Worker 				}
841*bd1f8aebSAndroid Build Coastguard Worker #endif
842*bd1f8aebSAndroid Build Coastguard Worker 
843*bd1f8aebSAndroid Build Coastguard Worker 				if ((options&F_LATENCY) || recv_timep == NULL) {
844*bd1f8aebSAndroid Build Coastguard Worker 					if ((options&F_LATENCY) ||
845*bd1f8aebSAndroid Build Coastguard Worker 					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
846*bd1f8aebSAndroid Build Coastguard Worker 						gettimeofday(&recv_time, NULL);
847*bd1f8aebSAndroid Build Coastguard Worker 					recv_timep = &recv_time;
848*bd1f8aebSAndroid Build Coastguard Worker 				}
849*bd1f8aebSAndroid Build Coastguard Worker 
850*bd1f8aebSAndroid Build Coastguard Worker 				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
851*bd1f8aebSAndroid Build Coastguard Worker 			}
852*bd1f8aebSAndroid Build Coastguard Worker 
853*bd1f8aebSAndroid Build Coastguard Worker 			/* See? ... someone runs another ping on this host. */
854*bd1f8aebSAndroid Build Coastguard Worker 			if (not_ours && !using_ping_socket)
855*bd1f8aebSAndroid Build Coastguard Worker 				install_filter();
856*bd1f8aebSAndroid Build Coastguard Worker 
857*bd1f8aebSAndroid Build Coastguard Worker 			/* If nothing is in flight, "break" returns us to pinger. */
858*bd1f8aebSAndroid Build Coastguard Worker 			if (in_flight() == 0)
859*bd1f8aebSAndroid Build Coastguard Worker 				break;
860*bd1f8aebSAndroid Build Coastguard Worker 
861*bd1f8aebSAndroid Build Coastguard Worker 			/* Otherwise, try to recvmsg() again. recvmsg()
862*bd1f8aebSAndroid Build Coastguard Worker 			 * is nonblocking after the first iteration, so that
863*bd1f8aebSAndroid Build Coastguard Worker 			 * if nothing is queued, it will receive EAGAIN
864*bd1f8aebSAndroid Build Coastguard Worker 			 * and return to pinger. */
865*bd1f8aebSAndroid Build Coastguard Worker 		}
866*bd1f8aebSAndroid Build Coastguard Worker 	}
867*bd1f8aebSAndroid Build Coastguard Worker 	finish();
868*bd1f8aebSAndroid Build Coastguard Worker }
869*bd1f8aebSAndroid Build Coastguard Worker 
gather_statistics(__u8 * icmph,int icmplen,int cc,__u16 seq,int hops,int csfailed,struct timeval * tv,char * from,void (* pr_reply)(__u8 * icmph,int cc))870*bd1f8aebSAndroid Build Coastguard Worker int gather_statistics(__u8 *icmph, int icmplen,
871*bd1f8aebSAndroid Build Coastguard Worker 		      int cc, __u16 seq, int hops,
872*bd1f8aebSAndroid Build Coastguard Worker 		      int csfailed, struct timeval *tv, char *from,
873*bd1f8aebSAndroid Build Coastguard Worker 		      void (*pr_reply)(__u8 *icmph, int cc))
874*bd1f8aebSAndroid Build Coastguard Worker {
875*bd1f8aebSAndroid Build Coastguard Worker 	int dupflag = 0;
876*bd1f8aebSAndroid Build Coastguard Worker 	long triptime = 0;
877*bd1f8aebSAndroid Build Coastguard Worker 	__u8 *ptr = icmph + icmplen;
878*bd1f8aebSAndroid Build Coastguard Worker 
879*bd1f8aebSAndroid Build Coastguard Worker 	++nreceived;
880*bd1f8aebSAndroid Build Coastguard Worker 	if (!csfailed)
881*bd1f8aebSAndroid Build Coastguard Worker 		acknowledge(seq);
882*bd1f8aebSAndroid Build Coastguard Worker 
883*bd1f8aebSAndroid Build Coastguard Worker 	if (timing && cc >= 8+sizeof(struct timeval)) {
884*bd1f8aebSAndroid Build Coastguard Worker 		struct timeval tmp_tv;
885*bd1f8aebSAndroid Build Coastguard Worker 		memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
886*bd1f8aebSAndroid Build Coastguard Worker 
887*bd1f8aebSAndroid Build Coastguard Worker restamp:
888*bd1f8aebSAndroid Build Coastguard Worker 		tvsub(tv, &tmp_tv);
889*bd1f8aebSAndroid Build Coastguard Worker 		triptime = tv->tv_sec * 1000000 + tv->tv_usec;
890*bd1f8aebSAndroid Build Coastguard Worker 		if (triptime < 0) {
891*bd1f8aebSAndroid Build Coastguard Worker 			fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
892*bd1f8aebSAndroid Build Coastguard Worker 			triptime = 0;
893*bd1f8aebSAndroid Build Coastguard Worker 			if (!(options & F_LATENCY)) {
894*bd1f8aebSAndroid Build Coastguard Worker 				gettimeofday(tv, NULL);
895*bd1f8aebSAndroid Build Coastguard Worker 				options |= F_LATENCY;
896*bd1f8aebSAndroid Build Coastguard Worker 				goto restamp;
897*bd1f8aebSAndroid Build Coastguard Worker 			}
898*bd1f8aebSAndroid Build Coastguard Worker 		}
899*bd1f8aebSAndroid Build Coastguard Worker 		if (!csfailed) {
900*bd1f8aebSAndroid Build Coastguard Worker 			tsum += triptime;
901*bd1f8aebSAndroid Build Coastguard Worker 			tsum2 += (long long)triptime * (long long)triptime;
902*bd1f8aebSAndroid Build Coastguard Worker 			if (triptime < tmin)
903*bd1f8aebSAndroid Build Coastguard Worker 				tmin = triptime;
904*bd1f8aebSAndroid Build Coastguard Worker 			if (triptime > tmax)
905*bd1f8aebSAndroid Build Coastguard Worker 				tmax = triptime;
906*bd1f8aebSAndroid Build Coastguard Worker 			if (!rtt)
907*bd1f8aebSAndroid Build Coastguard Worker 				rtt = triptime*8;
908*bd1f8aebSAndroid Build Coastguard Worker 			else
909*bd1f8aebSAndroid Build Coastguard Worker 				rtt += triptime-rtt/8;
910*bd1f8aebSAndroid Build Coastguard Worker 			if (options&F_ADAPTIVE)
911*bd1f8aebSAndroid Build Coastguard Worker 				update_interval();
912*bd1f8aebSAndroid Build Coastguard Worker 		}
913*bd1f8aebSAndroid Build Coastguard Worker 	}
914*bd1f8aebSAndroid Build Coastguard Worker 
915*bd1f8aebSAndroid Build Coastguard Worker 	if (csfailed) {
916*bd1f8aebSAndroid Build Coastguard Worker 		++nchecksum;
917*bd1f8aebSAndroid Build Coastguard Worker 		--nreceived;
918*bd1f8aebSAndroid Build Coastguard Worker 	} else if (rcvd_test(seq)) {
919*bd1f8aebSAndroid Build Coastguard Worker 		++nrepeats;
920*bd1f8aebSAndroid Build Coastguard Worker 		--nreceived;
921*bd1f8aebSAndroid Build Coastguard Worker 		dupflag = 1;
922*bd1f8aebSAndroid Build Coastguard Worker 	} else {
923*bd1f8aebSAndroid Build Coastguard Worker 		rcvd_set(seq);
924*bd1f8aebSAndroid Build Coastguard Worker 		dupflag = 0;
925*bd1f8aebSAndroid Build Coastguard Worker 	}
926*bd1f8aebSAndroid Build Coastguard Worker 	confirm = confirm_flag;
927*bd1f8aebSAndroid Build Coastguard Worker 
928*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_QUIET)
929*bd1f8aebSAndroid Build Coastguard Worker 		return 1;
930*bd1f8aebSAndroid Build Coastguard Worker 
931*bd1f8aebSAndroid Build Coastguard Worker 	if (options & F_FLOOD) {
932*bd1f8aebSAndroid Build Coastguard Worker 		if (!csfailed)
933*bd1f8aebSAndroid Build Coastguard Worker 			write_stdout("\b \b", 3);
934*bd1f8aebSAndroid Build Coastguard Worker 		else
935*bd1f8aebSAndroid Build Coastguard Worker 			write_stdout("\bC", 2);
936*bd1f8aebSAndroid Build Coastguard Worker 	} else {
937*bd1f8aebSAndroid Build Coastguard Worker 		int i;
938*bd1f8aebSAndroid Build Coastguard Worker 		__u8 *cp, *dp;
939*bd1f8aebSAndroid Build Coastguard Worker 
940*bd1f8aebSAndroid Build Coastguard Worker 		print_timestamp();
941*bd1f8aebSAndroid Build Coastguard Worker 		printf("%d bytes from %s:", cc, from);
942*bd1f8aebSAndroid Build Coastguard Worker 
943*bd1f8aebSAndroid Build Coastguard Worker 		if (pr_reply)
944*bd1f8aebSAndroid Build Coastguard Worker 			pr_reply(icmph, cc);
945*bd1f8aebSAndroid Build Coastguard Worker 
946*bd1f8aebSAndroid Build Coastguard Worker 		if (hops >= 0)
947*bd1f8aebSAndroid Build Coastguard Worker 			printf(" ttl=%d", hops);
948*bd1f8aebSAndroid Build Coastguard Worker 
949*bd1f8aebSAndroid Build Coastguard Worker 		if (cc < datalen+8) {
950*bd1f8aebSAndroid Build Coastguard Worker 			printf(" (truncated)\n");
951*bd1f8aebSAndroid Build Coastguard Worker 			return 1;
952*bd1f8aebSAndroid Build Coastguard Worker 		}
953*bd1f8aebSAndroid Build Coastguard Worker 		if (timing) {
954*bd1f8aebSAndroid Build Coastguard Worker 			if (triptime >= 100000)
955*bd1f8aebSAndroid Build Coastguard Worker 				printf(" time=%ld ms", triptime/1000);
956*bd1f8aebSAndroid Build Coastguard Worker 			else if (triptime >= 10000)
957*bd1f8aebSAndroid Build Coastguard Worker 				printf(" time=%ld.%01ld ms", triptime/1000,
958*bd1f8aebSAndroid Build Coastguard Worker 				       (triptime%1000)/100);
959*bd1f8aebSAndroid Build Coastguard Worker 			else if (triptime >= 1000)
960*bd1f8aebSAndroid Build Coastguard Worker 				printf(" time=%ld.%02ld ms", triptime/1000,
961*bd1f8aebSAndroid Build Coastguard Worker 				       (triptime%1000)/10);
962*bd1f8aebSAndroid Build Coastguard Worker 			else
963*bd1f8aebSAndroid Build Coastguard Worker 				printf(" time=%ld.%03ld ms", triptime/1000,
964*bd1f8aebSAndroid Build Coastguard Worker 				       triptime%1000);
965*bd1f8aebSAndroid Build Coastguard Worker 		}
966*bd1f8aebSAndroid Build Coastguard Worker 		if (dupflag)
967*bd1f8aebSAndroid Build Coastguard Worker 			printf(" (DUP!)");
968*bd1f8aebSAndroid Build Coastguard Worker 		if (csfailed)
969*bd1f8aebSAndroid Build Coastguard Worker 			printf(" (BAD CHECKSUM!)");
970*bd1f8aebSAndroid Build Coastguard Worker 
971*bd1f8aebSAndroid Build Coastguard Worker 		/* check the data */
972*bd1f8aebSAndroid Build Coastguard Worker 		cp = ((u_char*)ptr) + sizeof(struct timeval);
973*bd1f8aebSAndroid Build Coastguard Worker 		dp = &outpack[8 + sizeof(struct timeval)];
974*bd1f8aebSAndroid Build Coastguard Worker 		for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
975*bd1f8aebSAndroid Build Coastguard Worker 			if (*cp != *dp) {
976*bd1f8aebSAndroid Build Coastguard Worker 				printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
977*bd1f8aebSAndroid Build Coastguard Worker 				       i, *dp, *cp);
978*bd1f8aebSAndroid Build Coastguard Worker 				cp = (u_char*)ptr + sizeof(struct timeval);
979*bd1f8aebSAndroid Build Coastguard Worker 				for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
980*bd1f8aebSAndroid Build Coastguard Worker 					if ((i % 32) == sizeof(struct timeval))
981*bd1f8aebSAndroid Build Coastguard Worker 						printf("\n#%d\t", i);
982*bd1f8aebSAndroid Build Coastguard Worker 					printf("%x ", *cp);
983*bd1f8aebSAndroid Build Coastguard Worker 				}
984*bd1f8aebSAndroid Build Coastguard Worker 				break;
985*bd1f8aebSAndroid Build Coastguard Worker 			}
986*bd1f8aebSAndroid Build Coastguard Worker 		}
987*bd1f8aebSAndroid Build Coastguard Worker 	}
988*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
989*bd1f8aebSAndroid Build Coastguard Worker }
990*bd1f8aebSAndroid Build Coastguard Worker 
llsqrt(long long a)991*bd1f8aebSAndroid Build Coastguard Worker static long llsqrt(long long a)
992*bd1f8aebSAndroid Build Coastguard Worker {
993*bd1f8aebSAndroid Build Coastguard Worker 	long long prev = ~((long long)1 << 63);
994*bd1f8aebSAndroid Build Coastguard Worker 	long long x = a;
995*bd1f8aebSAndroid Build Coastguard Worker 
996*bd1f8aebSAndroid Build Coastguard Worker 	if (x > 0) {
997*bd1f8aebSAndroid Build Coastguard Worker 		while (x < prev) {
998*bd1f8aebSAndroid Build Coastguard Worker 			prev = x;
999*bd1f8aebSAndroid Build Coastguard Worker 			x = (x+(a/x))/2;
1000*bd1f8aebSAndroid Build Coastguard Worker 		}
1001*bd1f8aebSAndroid Build Coastguard Worker 	}
1002*bd1f8aebSAndroid Build Coastguard Worker 
1003*bd1f8aebSAndroid Build Coastguard Worker 	return (long)x;
1004*bd1f8aebSAndroid Build Coastguard Worker }
1005*bd1f8aebSAndroid Build Coastguard Worker 
1006*bd1f8aebSAndroid Build Coastguard Worker /*
1007*bd1f8aebSAndroid Build Coastguard Worker  * finish --
1008*bd1f8aebSAndroid Build Coastguard Worker  *	Print out statistics, and give up.
1009*bd1f8aebSAndroid Build Coastguard Worker  */
finish(void)1010*bd1f8aebSAndroid Build Coastguard Worker void finish(void)
1011*bd1f8aebSAndroid Build Coastguard Worker {
1012*bd1f8aebSAndroid Build Coastguard Worker 	struct timeval tv = cur_time;
1013*bd1f8aebSAndroid Build Coastguard Worker 	char *comma = "";
1014*bd1f8aebSAndroid Build Coastguard Worker 
1015*bd1f8aebSAndroid Build Coastguard Worker 	tvsub(&tv, &start_time);
1016*bd1f8aebSAndroid Build Coastguard Worker 
1017*bd1f8aebSAndroid Build Coastguard Worker 	putchar('\n');
1018*bd1f8aebSAndroid Build Coastguard Worker 	fflush(stdout);
1019*bd1f8aebSAndroid Build Coastguard Worker 	printf("--- %s ping statistics ---\n", hostname);
1020*bd1f8aebSAndroid Build Coastguard Worker 	printf("%ld packets transmitted, ", ntransmitted);
1021*bd1f8aebSAndroid Build Coastguard Worker 	printf("%ld received", nreceived);
1022*bd1f8aebSAndroid Build Coastguard Worker 	if (nrepeats)
1023*bd1f8aebSAndroid Build Coastguard Worker 		printf(", +%ld duplicates", nrepeats);
1024*bd1f8aebSAndroid Build Coastguard Worker 	if (nchecksum)
1025*bd1f8aebSAndroid Build Coastguard Worker 		printf(", +%ld corrupted", nchecksum);
1026*bd1f8aebSAndroid Build Coastguard Worker 	if (nerrors)
1027*bd1f8aebSAndroid Build Coastguard Worker 		printf(", +%ld errors", nerrors);
1028*bd1f8aebSAndroid Build Coastguard Worker 	if (ntransmitted) {
1029*bd1f8aebSAndroid Build Coastguard Worker 		printf(", %d%% packet loss",
1030*bd1f8aebSAndroid Build Coastguard Worker 		       (int) ((((long long)(ntransmitted - nreceived)) * 100) /
1031*bd1f8aebSAndroid Build Coastguard Worker 			      ntransmitted));
1032*bd1f8aebSAndroid Build Coastguard Worker 		printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
1033*bd1f8aebSAndroid Build Coastguard Worker 	}
1034*bd1f8aebSAndroid Build Coastguard Worker 	putchar('\n');
1035*bd1f8aebSAndroid Build Coastguard Worker 
1036*bd1f8aebSAndroid Build Coastguard Worker 	if (nreceived && timing) {
1037*bd1f8aebSAndroid Build Coastguard Worker 		long tmdev;
1038*bd1f8aebSAndroid Build Coastguard Worker 
1039*bd1f8aebSAndroid Build Coastguard Worker 		tsum /= nreceived + nrepeats;
1040*bd1f8aebSAndroid Build Coastguard Worker 		tsum2 /= nreceived + nrepeats;
1041*bd1f8aebSAndroid Build Coastguard Worker 		tmdev = llsqrt(tsum2 - tsum * tsum);
1042*bd1f8aebSAndroid Build Coastguard Worker 
1043*bd1f8aebSAndroid Build Coastguard Worker 		printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
1044*bd1f8aebSAndroid Build Coastguard Worker 		       (long)tmin/1000, (long)tmin%1000,
1045*bd1f8aebSAndroid Build Coastguard Worker 		       (unsigned long)(tsum/1000), (long)(tsum%1000),
1046*bd1f8aebSAndroid Build Coastguard Worker 		       (long)tmax/1000, (long)tmax%1000,
1047*bd1f8aebSAndroid Build Coastguard Worker 		       (long)tmdev/1000, (long)tmdev%1000
1048*bd1f8aebSAndroid Build Coastguard Worker 		       );
1049*bd1f8aebSAndroid Build Coastguard Worker 		comma = ", ";
1050*bd1f8aebSAndroid Build Coastguard Worker 	}
1051*bd1f8aebSAndroid Build Coastguard Worker 	if (pipesize > 1) {
1052*bd1f8aebSAndroid Build Coastguard Worker 		printf("%spipe %d", comma, pipesize);
1053*bd1f8aebSAndroid Build Coastguard Worker 		comma = ", ";
1054*bd1f8aebSAndroid Build Coastguard Worker 	}
1055*bd1f8aebSAndroid Build Coastguard Worker 	if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) {
1056*bd1f8aebSAndroid Build Coastguard Worker 		int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
1057*bd1f8aebSAndroid Build Coastguard Worker 		printf("%sipg/ewma %d.%03d/%d.%03d ms",
1058*bd1f8aebSAndroid Build Coastguard Worker 		       comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
1059*bd1f8aebSAndroid Build Coastguard Worker 	}
1060*bd1f8aebSAndroid Build Coastguard Worker 	putchar('\n');
1061*bd1f8aebSAndroid Build Coastguard Worker 	exit(!nreceived || (deadline && nreceived < npackets));
1062*bd1f8aebSAndroid Build Coastguard Worker }
1063*bd1f8aebSAndroid Build Coastguard Worker 
1064*bd1f8aebSAndroid Build Coastguard Worker 
status(void)1065*bd1f8aebSAndroid Build Coastguard Worker void status(void)
1066*bd1f8aebSAndroid Build Coastguard Worker {
1067*bd1f8aebSAndroid Build Coastguard Worker 	int loss = 0;
1068*bd1f8aebSAndroid Build Coastguard Worker 	long tavg = 0;
1069*bd1f8aebSAndroid Build Coastguard Worker 
1070*bd1f8aebSAndroid Build Coastguard Worker 	status_snapshot = 0;
1071*bd1f8aebSAndroid Build Coastguard Worker 
1072*bd1f8aebSAndroid Build Coastguard Worker 	if (ntransmitted)
1073*bd1f8aebSAndroid Build Coastguard Worker 		loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
1074*bd1f8aebSAndroid Build Coastguard Worker 
1075*bd1f8aebSAndroid Build Coastguard Worker 	fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
1076*bd1f8aebSAndroid Build Coastguard Worker 
1077*bd1f8aebSAndroid Build Coastguard Worker 	if (nreceived && timing) {
1078*bd1f8aebSAndroid Build Coastguard Worker 		tavg = tsum / (nreceived + nrepeats);
1079*bd1f8aebSAndroid Build Coastguard Worker 
1080*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
1081*bd1f8aebSAndroid Build Coastguard Worker 		       (long)tmin/1000, (long)tmin%1000,
1082*bd1f8aebSAndroid Build Coastguard Worker 		       tavg/1000, tavg%1000,
1083*bd1f8aebSAndroid Build Coastguard Worker 		       rtt/8000, (rtt/8)%1000,
1084*bd1f8aebSAndroid Build Coastguard Worker 		       (long)tmax/1000, (long)tmax%1000
1085*bd1f8aebSAndroid Build Coastguard Worker 		       );
1086*bd1f8aebSAndroid Build Coastguard Worker 	}
1087*bd1f8aebSAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
1088*bd1f8aebSAndroid Build Coastguard Worker }
1089*bd1f8aebSAndroid Build Coastguard Worker 
is_ours(uint16_t id)1090*bd1f8aebSAndroid Build Coastguard Worker inline int is_ours(uint16_t id) {
1091*bd1f8aebSAndroid Build Coastguard Worker 	return using_ping_socket || id == ident;
1092*bd1f8aebSAndroid Build Coastguard Worker }
1093*bd1f8aebSAndroid Build Coastguard Worker 
1094