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