Home | History | Annotate | Download | only in iputils
      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 
     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
    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
    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 
    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 
    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  */
    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 
    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 
    401 static void sigexit(int signo)
    402 {
    403 	exiting = 1;
    404 	if (in_pr_addr)
    405 		longjmp(pr_addr_jmp, 0);
    406 }
    407 
    408 static void sigstatus(int signo)
    409 {
    410 	status_snapshot = 1;
    411 }
    412 
    413 
    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 
    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  */
    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  */
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
   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 
   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 
   1090 inline int is_ours(uint16_t id) {
   1091 	return using_ping_socket || id == ident;
   1092 }
   1093 
   1094