• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "ping_common.h"
2 #include <ctype.h>
3 #include <sched.h>
4 #include <math.h>
5 
6 int options;
7 
8 __u32 mark;
9 int sndbuf;
10 int ttl;
11 int rtt;
12 int rtt_addend;
13 __u16 acked;
14 
15 struct rcvd_table rcvd_tbl;
16 int using_ping_socket = 1;
17 
18 
19 /* counters */
20 long npackets;			/* max packets to transmit */
21 long nreceived;			/* # of packets we got back */
22 long nrepeats;			/* number of duplicates */
23 long ntransmitted;		/* sequence # for outbound packets = #sent */
24 long nchecksum;			/* replies with bad checksum */
25 long nerrors;			/* icmp errors */
26 int interval = 1000;		/* interval between packets (msec) */
27 int preload;
28 int deadline = 0;		/* time to die */
29 int lingertime = MAXWAIT*1000;
30 struct timeval start_time, cur_time;
31 volatile int exiting;
32 volatile int status_snapshot;
33 int confirm = 0;
34 volatile int in_pr_addr = 0;	/* pr_addr() is executing */
35 jmp_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 */
40 int 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] */
43 int working_recverr;
44 
45 /* timing */
46 int timing;			/* flag to do timing */
47 long tmin = LONG_MAX;		/* minimum round trip time */
48 long 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  */
54 long long tsum;			/* sum of all times, for doing average */
55 long long tsum2;
56 int  pipesize = -1;
57 
58 int datalen = DEFDATALEN;
59 
60 char *hostname;
61 int uid;
62 uid_t euid;
63 int ident = 0;			/* process id to identify our packets */
64 
65 static int screen_width = INT_MAX;
66 
67 #define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
68 
69 #ifdef CAPABILITIES
70 static cap_value_t cap_raw = CAP_NET_RAW;
71 static cap_value_t cap_admin = CAP_NET_ADMIN;
72 #endif
73 
limit_capabilities(void)74 void 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
modify_capability(cap_value_t cap,cap_flag_value_t on)139 int 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;
167 out:
168 	if (cap_p)
169 		cap_free(cap_p);
170 	return rc;
171 }
172 #else
modify_capability(int on)173 int 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 
drop_capabilities(void)184 void 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 
android_check_security(void)201 void 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  */
fill(char * patp)212 static 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 
common_options(int ch)253 void 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 = strtoul(optarg, &endp, 0);
298 		if (*endp != '\0') {
299 			fprintf(stderr, "ping: invalid mark %s\n", optarg);
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 
sigexit(int signo)401 static void sigexit(int signo)
402 {
403 	exiting = 1;
404 	if (in_pr_addr)
405 		longjmp(pr_addr_jmp, 0);
406 }
407 
sigstatus(int signo)408 static void sigstatus(int signo)
409 {
410 	status_snapshot = 1;
411 }
412 
413 
__schedule_exit(int next)414 int __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 
update_interval(void)440 static 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  */
print_timestamp(void)452 void 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  */
pinger(void)470 int 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 
515 resend:
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 
sock_setbufs(int icmp_sock,int alloc)589 void 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 
sock_setmark(int icmp_sock)608 void 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 
setup(int icmp_sock)629 void 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 
main_loop(int icmp_sock,__u8 * packet,int packlen)726 void 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 
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 int 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 
887 restamp:
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 
llsqrt(long long a)991 static 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  */
finish(void)1010 void 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 
status(void)1065 void 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 
is_ours(uint16_t id)1090 inline int is_ours(uint16_t id) {
1091 	return using_ping_socket || id == ident;
1092 }
1093 
1094