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