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