• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Mike Muuss.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 char copyright[] =
39 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
40  All rights reserved.\n";
41 #endif /* not lint */
42 
43 /*
44  *			P I N G . C
45  *
46  * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
47  * measure round-trip-delays and packet loss across network paths.
48  *
49  * Author -
50  *	Mike Muuss
51  *	U. S. Army Ballistic Research Laboratory
52  *	December, 1983
53  *
54  * Status -
55  *	Public Domain.  Distribution Unlimited.
56  * Bugs -
57  *	More statistics could always be gathered.
58  *	This program has to run SUID to ROOT to access the ICMP socket.
59  */
60 
61 #include "ping_common.h"
62 
63 #include <netinet/ip.h>
64 #include <linux/icmp.h>
65 #include <sched.h>
66 #include <sys/types.h>
67 #include <private/android_filesystem_config.h>
68 
69 #define bzero(b,sz) memset(b, 0, sz)
70 
71 /* PING COMMON */
72 
73 int options;
74 
75 int sndbuf;
76 int ttl;
77 int rtt;
78 int rtt_addend;
79 __u16 acked;
80 
81 int mx_dup_ck = MAX_DUP_CHK;
82 char rcvd_tbl[MAX_DUP_CHK / 8];
83 
84 
85 /* counters */
86 long npackets;			/* max packets to transmit */
87 long nreceived;			/* # of packets we got back */
88 long nrepeats;			/* number of duplicates */
89 long ntransmitted;		/* sequence # for outbound packets = #sent */
90 long nchecksum;			/* replies with bad checksum */
91 long nerrors;			/* icmp errors */
92 int interval = 1000;		/* interval between packets (msec) */
93 int preload;
94 int deadline = 0;		/* time to die */
95 int lingertime = MAXWAIT*1000;
96 struct timeval start_time, cur_time;
97 volatile int exiting;
98 volatile int status_snapshot;
99 int confirm = 0;
100 
101 /* Stupid workarounds for bugs/missing functionality in older linuces.
102  * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
103  * i.e. for linux-2.2 */
104 int confirm_flag = MSG_CONFIRM;
105 /* And this is workaround for bug in IP_RECVERR on raw sockets which is present
106  * in linux-2.2.[0-19], linux-2.4.[0-7] */
107 int working_recverr;
108 
109 /* timing */
110 int timing;			/* flag to do timing */
111 long tmin = LONG_MAX;		/* minimum round trip time */
112 long tmax;			/* maximum round trip time */
113 /* Message for rpm maintainers: have _shame_. If you want
114  * to fix something send the patch to me for sanity checking.
115  * "sparcfix" patch is a complete non-sense, apparenly the person
116  * prepared it was stoned.
117  */
118 long long tsum;			/* sum of all times, for doing average */
119 long long tsum2;
120 int  pipesize = -1;
121 
122 int datalen = DEFDATALEN;
123 
124 char *hostname;
125 int uid;
126 int ident;			/* process id to identify our packets */
127 
128 static int screen_width = INT_MAX;
129 
130 /* Fills all the outpack, excluding ICMP header, but _including_
131  * timestamp area with supplied pattern.
132  */
fill(char * patp)133 static void fill(char *patp)
134 {
135 	int ii, jj, kk;
136 	int pat[16];
137 	char *cp;
138 	char *bp = outpack+8;
139 
140 	for (cp = patp; *cp; cp++) {
141 		if (!isxdigit(*cp)) {
142 			fprintf(stderr,
143 				"ping: patterns must be specified as hex digits.\n");
144 			exit(2);
145 		}
146 	}
147 	ii = sscanf(patp,
148 	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
149 	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
150 	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
151 	    &pat[13], &pat[14], &pat[15]);
152 
153 	if (ii > 0) {
154 		for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
155 			for (jj = 0; jj < ii; ++jj)
156 				bp[jj + kk] = pat[jj];
157 	}
158 	if (!(options & F_QUIET)) {
159 		printf("PATTERN: 0x");
160 		for (jj = 0; jj < ii; ++jj)
161 			printf("%02x", bp[jj] & 0xFF);
162 		printf("\n");
163 	}
164 }
165 
common_options(int ch)166 void common_options(int ch)
167 {
168 	switch(ch) {
169 	case 'a':
170 		options |= F_AUDIBLE;
171 		break;
172 	case 'A':
173 		options |= F_ADAPTIVE;
174 		break;
175 	case 'c':
176 		npackets = atoi(optarg);
177 		if (npackets <= 0) {
178 			fprintf(stderr, "ping: bad number of packets to transmit.\n");
179 			exit(2);
180 		}
181 		break;
182 	case 'd':
183 		options |= F_SO_DEBUG;
184 		break;
185 	case 'f':
186 		options |= F_FLOOD;
187 		//setbuf(stdout, (char *)NULL);
188 		break;
189 	case 'i':		/* wait between sending packets */
190 	{
191 		if (strchr(optarg, '.')) {
192 			float t;
193 			if (sscanf(optarg, "%f", &t) != 1) {
194 				fprintf(stderr, "ping: bad timing interval.\n");
195 				exit(2);
196 			}
197 			interval = (int)(t*1000);
198 		} else if (sscanf(optarg, "%d", &interval) == 1) {
199 			interval *= 1000;
200 		} else {
201 			fprintf(stderr, "ping: bad timing interval.\n");
202 			exit(2);
203 		}
204 
205 		if (interval < 0) {
206 			fprintf(stderr, "ping: bad timing interval.\n");
207 			exit(2);
208 		}
209 		options |= F_INTERVAL;
210 		break;
211 	}
212 	case 'w':
213 		deadline = atoi(optarg);
214 		if (deadline < 0) {
215 			fprintf(stderr, "ping: bad wait time.\n");
216 			exit(2);
217 		}
218 		break;
219 	case 'l':
220 		preload = atoi(optarg);
221 		if (preload <= 0) {
222 			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck);
223 			exit(2);
224 		}
225 		if (preload > mx_dup_ck)
226 			preload = mx_dup_ck;
227 		if (uid && preload > 3) {
228 			fprintf(stderr, "ping: cannot set preload to value > 3\n");
229 			exit(2);
230 		}
231 		break;
232 	case 'S':
233 		sndbuf = atoi(optarg);
234 		if (sndbuf <= 0) {
235 			fprintf(stderr, "ping: bad sndbuf value.\n");
236 			exit(2);
237 		}
238 		break;
239 	case 'n':
240 		options |= F_NUMERIC;
241 		break;
242 	case 'p':		/* fill buffer with user pattern */
243 		options |= F_PINGFILLED;
244 		fill(optarg);
245 		break;
246 	case 'q':
247 		options |= F_QUIET;
248 		break;
249 	case 'r':
250 		options |= F_SO_DONTROUTE;
251 		break;
252 	case 's':		/* size of packet to send */
253 		datalen = atoi(optarg);
254 		if (datalen < 0) {
255 			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
256 			exit(2);
257 		}
258 		break;
259 	case 'v':
260 		options |= F_VERBOSE;
261 		break;
262 	case 'L':
263 		options |= F_NOLOOP;
264 		break;
265 	case 't':
266 		options |= F_TTL;
267 		ttl = atoi(optarg);
268 		if (ttl < 0 || ttl > 255) {
269 			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
270 			exit(2);
271 		}
272 		break;
273 	case 'U':
274 		options |= F_LATENCY;
275 		break;
276 	case 'B':
277 		options |= F_STRICTSOURCE;
278 		break;
279 	case 'W':
280 		lingertime = atoi(optarg);
281 		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
282 			fprintf(stderr, "ping: bad linger time.\n");
283 			exit(2);
284 		}
285 		lingertime *= 1000;
286 		break;
287 	case 'V':
288 		printf("ping utility, iputils-ss\n");
289 		exit(0);
290 	default:
291 		abort();
292 	}
293 }
294 
295 
sigexit(int signo)296 static void sigexit(int signo)
297 {
298 	exiting = 1;
299 }
300 
sigstatus(int signo)301 static void sigstatus(int signo)
302 {
303 	status_snapshot = 1;
304 }
305 
306 
__schedule_exit(int next)307 int __schedule_exit(int next)
308 {
309 	static unsigned long waittime;
310 	struct itimerval it;
311 
312 	if (waittime)
313 		return next;
314 
315 	if (nreceived) {
316 		waittime = 2 * tmax;
317 		if (waittime < 1000*interval)
318 			waittime = 1000*interval;
319 	} else
320 		waittime = lingertime*1000;
321 
322 	if (next < 0 || next < waittime/1000)
323 		next = waittime/1000;
324 
325 	it.it_interval.tv_sec = 0;
326 	it.it_interval.tv_usec = 0;
327 	it.it_value.tv_sec = waittime/1000000;
328 	it.it_value.tv_usec = waittime%1000000;
329 	setitimer(ITIMER_REAL, &it, NULL);
330 	return next;
331 }
332 
update_interval(void)333 static inline void update_interval(void)
334 {
335 	int est = rtt ? rtt/8 : interval*1000;
336 
337 	interval = (est+rtt_addend+500)/1000;
338 	if (uid && interval < MINUSERINTERVAL)
339 		interval = MINUSERINTERVAL;
340 }
341 
342 /*
343  * pinger --
344  * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
345  * will be added on by the kernel.  The ID field is our UNIX process ID,
346  * and the sequence number is an ascending integer.  The first 8 bytes
347  * of the data portion are used to hold a UNIX "timeval" struct in VAX
348  * byte-order, to compute the round-trip time.
349  */
pinger(void)350 int pinger(void)
351 {
352 	static int oom_count;
353 	static int tokens;
354 	int i;
355 
356 	/* Have we already sent enough? If we have, return an arbitrary positive value. */
357 	if (exiting || (npackets && ntransmitted >= npackets && !deadline))
358 		return 1000;
359 
360 	/* Check that packets < rate*time + preload */
361 	if (cur_time.tv_sec == 0) {
362 		gettimeofday(&cur_time, NULL);
363 		tokens = interval*(preload-1);
364 	} else {
365 		long ntokens;
366 		struct timeval tv;
367 
368 		gettimeofday(&tv, NULL);
369 		ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
370 			(tv.tv_usec-cur_time.tv_usec)/1000;
371 		if (!interval) {
372 			/* Case of unlimited flood is special;
373 			 * if we see no reply, they are limited to 100pps */
374 			if (ntokens < MININTERVAL && in_flight() >= preload)
375 				return MININTERVAL-ntokens;
376 		}
377 		ntokens += tokens;
378 		if (ntokens > interval*preload)
379 			ntokens = interval*preload;
380 		if (ntokens < interval)
381 			return interval - ntokens;
382 
383 		cur_time = tv;
384 		tokens = ntokens - interval;
385 	}
386 
387 resend:
388 	i = send_probe();
389 
390 	if (i == 0) {
391 		oom_count = 0;
392 		advance_ntransmitted();
393 		if (!(options & F_QUIET) && (options & F_FLOOD)) {
394 			/* Very silly, but without this output with
395 			 * high preload or pipe size is very confusing. */
396 			if ((preload < screen_width && pipesize < screen_width) ||
397 			    in_flight() < screen_width)
398 				write(STDOUT_FILENO, ".", 1);
399 		}
400 		return interval - tokens;
401 	}
402 
403 	/* And handle various errors... */
404 	if (i > 0) {
405 		/* Apparently, it is some fatal bug. */
406 		abort();
407 	} else if (errno == ENOBUFS || errno == ENOMEM) {
408 		int nores_interval;
409 
410 		/* Device queue overflow or OOM. Packet is not sent. */
411 		tokens = 0;
412 		/* Slowdown. This works only in adaptive mode (option -A) */
413 		rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
414 		if (options&F_ADAPTIVE)
415 			update_interval();
416 		nores_interval = SCHINT(interval/2);
417 		if (nores_interval > 500)
418 			nores_interval = 500;
419 		oom_count++;
420 		if (oom_count*nores_interval < lingertime)
421 			return nores_interval;
422 		i = 0;
423 		/* Fall to hard error. It is to avoid complete deadlock
424 		 * on stuck output device even when dealine was not requested.
425 		 * Expected timings are screwed up in any case, but we will
426 		 * exit some day. :-) */
427 	} else if (errno == EAGAIN) {
428 		/* Socket buffer is full. */
429 		tokens += interval;
430 		return MININTERVAL;
431 	} else {
432 		if ((i=receive_error_msg()) > 0) {
433 			/* An ICMP error arrived. */
434 			tokens += interval;
435 			return MININTERVAL;
436 		}
437 		/* Compatibility with old linuces. */
438 		if (i == 0 && confirm_flag && errno == EINVAL) {
439 			confirm_flag = 0;
440 			errno = 0;
441 		}
442 		if (!errno)
443 			goto resend;
444 	}
445 
446 	/* Hard local error. Pretend we sent packet. */
447 	advance_ntransmitted();
448 
449 	if (i == 0 && !(options & F_QUIET)) {
450 		if (options & F_FLOOD)
451 			write(STDOUT_FILENO, "E", 1);
452 		else
453 			perror("ping: sendmsg");
454 	}
455 	tokens = 0;
456 	return SCHINT(interval);
457 }
458 
459 /* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
460 
sock_setbufs(int icmp_sock,int alloc)461 void sock_setbufs(int icmp_sock, int alloc)
462 {
463 	int rcvbuf, hold;
464 	int tmplen = sizeof(hold);
465 
466 	if (!sndbuf)
467 		sndbuf = alloc;
468 	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
469 
470 	rcvbuf = hold = alloc * preload;
471 	if (hold < 65536)
472 		hold = 65536;
473 	setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
474 	if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
475 		if (hold < rcvbuf)
476 			fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
477 	}
478 }
479 
480 /* Protocol independent setup and parameter checks. */
481 
setup(int icmp_sock)482 void setup(int icmp_sock)
483 {
484 	int hold;
485 	struct timeval tv;
486 
487 	if ((options & F_FLOOD) && !(options & F_INTERVAL))
488 		interval = 0;
489 
490 	if (uid && interval < MINUSERINTERVAL) {
491 		fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
492 		exit(2);
493 	}
494 
495 	if (interval >= INT_MAX/preload) {
496 		fprintf(stderr, "ping: illegal preload and/or interval\n");
497 		exit(2);
498 	}
499 
500 	hold = 1;
501 	if (options & F_SO_DEBUG)
502 		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
503 	if (options & F_SO_DONTROUTE)
504 		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
505 
506 #ifdef SO_TIMESTAMP
507 	if (!(options&F_LATENCY)) {
508 		int on = 1;
509 		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
510 			fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
511 	}
512 #endif
513 
514 	/* Set some SNDTIMEO to prevent blocking forever
515 	 * on sends, when device is too slow or stalls. Just put limit
516 	 * of one second, or "interval", if it is less.
517 	 */
518 	tv.tv_sec = 1;
519 	tv.tv_usec = 0;
520 	if (interval < 1000) {
521 		tv.tv_sec = 0;
522 		tv.tv_usec = 1000 * SCHINT(interval);
523 	}
524 	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
525 
526 	/* Set RCVTIMEO to "interval". Note, it is just an optimization
527 	 * allowing to avoid redundant poll(). */
528 	tv.tv_sec = SCHINT(interval)/1000;
529 	tv.tv_usec = 1000*(SCHINT(interval)%1000);
530 	if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
531 		options |= F_FLOOD_POLL;
532 
533 	if (!(options & F_PINGFILLED)) {
534 		int i;
535 		char *p = outpack+8;
536 
537 		/* Do not forget about case of small datalen,
538 		 * fill timestamp area too!
539 		 */
540 		for (i = 0; i < datalen; ++i)
541 			*p++ = i;
542 	}
543 
544 	ident = getpid() & 0xFFFF;
545 
546 	set_signal(SIGINT, sigexit);
547 	set_signal(SIGALRM, sigexit);
548 	set_signal(SIGQUIT, sigstatus);
549 
550 	gettimeofday(&start_time, NULL);
551 
552 	if (deadline) {
553 		struct itimerval it;
554 
555 		it.it_interval.tv_sec = 0;
556 		it.it_interval.tv_usec = 0;
557 		it.it_value.tv_sec = deadline;
558 		it.it_value.tv_usec = 0;
559 		setitimer(ITIMER_REAL, &it, NULL);
560 	}
561 
562 #if 0
563 	if (isatty(STDOUT_FILENO)) {
564 		struct winsize w;
565 
566 		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
567 			if (w.ws_col > 0)
568 				screen_width = w.ws_col;
569 		}
570 	}
571 #endif
572 }
573 
main_loop(int icmp_sock,__u8 * packet,int packlen)574 void main_loop(int icmp_sock, __u8 *packet, int packlen)
575 {
576 	char addrbuf[128];
577 	char ans_data[4096];
578 	struct iovec iov;
579 	struct msghdr msg;
580 	struct cmsghdr *c;
581 	int cc;
582 	int next;
583 	int polling;
584 
585 	iov.iov_base = (char *)packet;
586 
587 	for (;;) {
588 		/* Check exit conditions. */
589 		if (exiting)
590 			break;
591 		if (npackets && nreceived + nerrors >= npackets)
592 			break;
593 		if (deadline && nerrors)
594 			break;
595 		/* Check for and do special actions. */
596 		if (status_snapshot)
597 			status();
598 
599 		/* Send probes scheduled to this time. */
600 		do {
601 			next = pinger();
602 			next = schedule_exit(next);
603 		} while (next <= 0);
604 
605 		/* "next" is time to send next probe, if positive.
606 		 * If next<=0 send now or as soon as possible. */
607 
608 		/* Technical part. Looks wicked. Could be dropped,
609 		 * if everyone used the newest kernel. :-)
610 		 * Its purpose is:
611 		 * 1. Provide intervals less than resolution of scheduler.
612 		 *    Solution: spinning.
613 		 * 2. Avoid use of poll(), when recvmsg() can provide
614 		 *    timed waiting (SO_RCVTIMEO). */
615 		polling = 0;
616 		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
617 			int recv_expected = in_flight();
618 
619 			/* If we are here, recvmsg() is unable to wait for
620 			 * required timeout. */
621 			if (1000*next <= 1000000/(int)HZ) {
622 				/* Very short timeout... So, if we wait for
623 				 * something, we sleep for MININTERVAL.
624 				 * Otherwise, spin! */
625 				if (recv_expected) {
626 					next = MININTERVAL;
627 				} else {
628 					next = 0;
629 					/* When spinning, no reasons to poll.
630 					 * Use nonblocking recvmsg() instead. */
631 					polling = MSG_DONTWAIT;
632 					/* But yield yet. */
633 					sched_yield();
634 				}
635 			}
636 
637 			if (!polling &&
638 			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
639 				struct pollfd pset;
640 				pset.fd = icmp_sock;
641 				pset.events = POLLIN|POLLERR;
642 				pset.revents = 0;
643 				if (poll(&pset, 1, next) < 1 ||
644 				    !(pset.revents&(POLLIN|POLLERR)))
645 					continue;
646 				polling = MSG_DONTWAIT;
647 			}
648 		}
649 
650 		for (;;) {
651 			struct timeval *recv_timep = NULL;
652 			struct timeval recv_time;
653 			int not_ours = 0; /* Raw socket can receive messages
654 					   * destined to other running pings. */
655 
656 			iov.iov_len = packlen;
657 			msg.msg_name = addrbuf;
658 			msg.msg_namelen = sizeof(addrbuf);
659 			msg.msg_iov = &iov;
660 			msg.msg_iovlen = 1;
661 			msg.msg_control = ans_data;
662 			msg.msg_controllen = sizeof(ans_data);
663 
664 			cc = recvmsg(icmp_sock, &msg, polling);
665 			polling = MSG_DONTWAIT;
666 
667 			if (cc < 0) {
668 				if (errno == EAGAIN || errno == EINTR)
669 					break;
670 				if (!receive_error_msg()) {
671 					if (errno) {
672 						perror("ping: recvmsg");
673 						break;
674 					}
675 					not_ours = 1;
676 				}
677 			} else {
678 
679 #ifdef SO_TIMESTAMP
680 				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
681 					if (c->cmsg_level != SOL_SOCKET ||
682 					    c->cmsg_type != SO_TIMESTAMP)
683 						continue;
684 					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
685 						continue;
686 					recv_timep = (struct timeval*)CMSG_DATA(c);
687 				}
688 #endif
689 
690 				if ((options&F_LATENCY) || recv_timep == NULL) {
691 					if ((options&F_LATENCY) ||
692 					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
693 						gettimeofday(&recv_time, NULL);
694 					recv_timep = &recv_time;
695 				}
696 
697 				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
698 			}
699 
700 			/* See? ... someone runs another ping on this host. */
701 			if (not_ours)
702 				install_filter();
703 
704 			/* If nothing is in flight, "break" returns us to pinger. */
705 			if (in_flight() == 0)
706 				break;
707 
708 			/* Otherwise, try to recvmsg() again. recvmsg()
709 			 * is nonblocking after the first iteration, so that
710 			 * if nothing is queued, it will receive EAGAIN
711 			 * and return to pinger. */
712 		}
713 	}
714 	finish();
715 }
716 
gather_statistics(__u8 * ptr,int cc,__u16 seq,int hops,int csfailed,struct timeval * tv,char * from)717 int gather_statistics(__u8 *ptr, int cc, __u16 seq, int hops,
718 		      int csfailed, struct timeval *tv, char *from)
719 {
720 	int dupflag = 0;
721 	long triptime = 0;
722 
723 	++nreceived;
724 	if (!csfailed)
725 		acknowledge(seq);
726 
727 	if (timing && cc >= 8+sizeof(struct timeval)) {
728 		struct timeval tmp_tv;
729 		memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
730 
731 restamp:
732 		tvsub(tv, &tmp_tv);
733 		triptime = tv->tv_sec * 1000000 + tv->tv_usec;
734 		if (triptime < 0) {
735 			fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
736 			triptime = 0;
737 			if (!(options & F_LATENCY)) {
738 				gettimeofday(tv, NULL);
739 				options |= F_LATENCY;
740 				goto restamp;
741 			}
742 		}
743 		if (!csfailed) {
744 			tsum += triptime;
745 			tsum2 += (long long)triptime * (long long)triptime;
746 			if (triptime < tmin)
747 				tmin = triptime;
748 			if (triptime > tmax)
749 				tmax = triptime;
750 			if (!rtt)
751 				rtt = triptime*8;
752 			else
753 				rtt += triptime-rtt/8;
754 			if (options&F_ADAPTIVE)
755 				update_interval();
756 		}
757 	}
758 
759 	if (csfailed) {
760 		++nchecksum;
761 		--nreceived;
762 	} else if (TST(seq % mx_dup_ck)) {
763 		++nrepeats;
764 		--nreceived;
765 		dupflag = 1;
766 	} else {
767 		SET(seq % mx_dup_ck);
768 		dupflag = 0;
769 	}
770 	confirm = confirm_flag;
771 
772 	if (options & F_QUIET)
773 		return 1;
774 
775 	if (options & F_FLOOD) {
776 		if (!csfailed)
777 			write(STDOUT_FILENO, "\b \b", 3);
778 		else
779 			write(STDOUT_FILENO, "\bC", 1);
780 	} else {
781 		int i;
782 		__u8 *cp, *dp;
783 		printf("%d bytes from %s: icmp_seq=%u", cc, from, seq);
784 
785 		if (hops >= 0)
786 			printf(" ttl=%d", hops);
787 
788 		if (cc < datalen+8) {
789 			printf(" (truncated)\n");
790 			return 1;
791 		}
792 		if (timing) {
793 			if (triptime >= 100000)
794 				printf(" time=%ld ms", triptime/1000);
795 			else if (triptime >= 10000)
796 				printf(" time=%ld.%01ld ms", triptime/1000,
797 				       (triptime%1000)/100);
798 			else if (triptime >= 1000)
799 				printf(" time=%ld.%02ld ms", triptime/1000,
800 				       (triptime%1000)/10);
801 			else
802 				printf(" time=%ld.%03ld ms", triptime/1000,
803 				       triptime%1000);
804 		}
805 		if (dupflag)
806 			printf(" (DUP!)");
807 		if (csfailed)
808 			printf(" (BAD CHECKSUM!)");
809 
810 		/* check the data */
811 		cp = ((u_char*)ptr) + sizeof(struct timeval);
812 		dp = &outpack[8 + sizeof(struct timeval)];
813 		for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
814 			if (*cp != *dp) {
815 				printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
816 				       i, *dp, *cp);
817 				cp = (u_char*)ptr + sizeof(struct timeval);
818 				for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
819 					if ((i % 32) == sizeof(struct timeval))
820 						printf("\n#%d\t", i);
821 					printf("%x ", *cp);
822 				}
823 				break;
824 			}
825 		}
826 	}
827 	return 0;
828 }
829 
llsqrt(long long a)830 static long llsqrt(long long a)
831 {
832 	long long prev = ~((long long)1 << 63);
833 	long long x = a;
834 
835 	if (x > 0) {
836 		while (x < prev) {
837 			prev = x;
838 			x = (x+(a/x))/2;
839 		}
840 	}
841 
842 	return (long)x;
843 }
844 
845 /*
846  * finish --
847  *	Print out statistics, and give up.
848  */
finish(void)849 void finish(void)
850 {
851 	struct timeval tv = cur_time;
852 
853 	tvsub(&tv, &start_time);
854 
855 	putchar('\n');
856 	fflush(stdout);
857 	printf("--- %s ping statistics ---\n", hostname);
858 	printf("%ld packets transmitted, ", ntransmitted);
859 	printf("%ld received", nreceived);
860 	if (nrepeats)
861 		printf(", +%ld duplicates", nrepeats);
862 	if (nchecksum)
863 		printf(", +%ld corrupted", nchecksum);
864 	if (nerrors)
865 		printf(", +%ld errors", nerrors);
866 	if (ntransmitted) {
867 		printf(", %d%% packet loss",
868 		       (int) ((((long long)(ntransmitted - nreceived)) * 100) /
869 			      ntransmitted));
870 		printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
871 	}
872 	putchar('\n');
873 
874 	if (nreceived && timing) {
875 		long tmdev;
876 
877 		tsum /= nreceived + nrepeats;
878 		tsum2 /= nreceived + nrepeats;
879 		tmdev = llsqrt(tsum2 - tsum * tsum);
880 
881 		printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
882 		       tmin/1000, tmin%1000,
883 		       (unsigned long)(tsum/1000), (long)(tsum%1000),
884 		       tmax/1000, tmax%1000,
885 		       tmdev/1000, tmdev%1000
886 		       );
887 	}
888 	if (pipesize > 1)
889 		printf(", pipe %d", pipesize);
890 	if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) {
891 		int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
892 		printf(", ipg/ewma %d.%03d/%d.%03d ms",
893 		       ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
894 	}
895 	putchar('\n');
896 	exit(!nreceived || (deadline && nreceived < npackets));
897 }
898 
899 
status(void)900 void status(void)
901 {
902 	int loss = 0;
903 	long tavg = 0;
904 
905 	status_snapshot = 0;
906 
907 	if (ntransmitted)
908 		loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
909 
910 	fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
911 
912 	if (nreceived && timing) {
913 		tavg = tsum / (nreceived + nrepeats);
914 
915 		fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
916 		       tmin/1000, tmin%1000,
917 		       tavg/1000, tavg%1000,
918 		       rtt/8000, (rtt/8)%1000,
919 		       tmax/1000, tmax%1000
920 		       );
921 	}
922 	fprintf(stderr, "\n");
923 }
924 
925 /* PING COMMON */
926 
927 #define	MAXIPLEN	60
928 #define	MAXICMPLEN	76
929 #define	NROUTES		9		/* number of record route slots */
930 #define TOS_MAX		255		/* 8-bit TOS field */
931 
932 
933 static int ts_type;
934 static int nroute = 0;
935 static __u32 route[10];
936 
937 
938 
939 struct sockaddr_in whereto;	/* who to ping */
940 int optlen = 0;
941 int settos = 0;			/* Set TOS, Precendence or other QOS options */
942 int icmp_sock;			/* socket file descriptor */
943 u_char outpack[0x10000];
944 int maxpacket = sizeof(outpack);
945 
946 static int broadcast_pings = 0;
947 
948 static char *pr_addr(__u32);
949 static void pr_options(unsigned char * cp, int hlen);
950 static void pr_iph(struct iphdr *ip);
951 static void usage(void) __attribute__((noreturn));
952 static u_short in_cksum(const u_short *addr, int len, u_short salt);
953 static void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp);
954 static int parsetos(char *str);
955 
956 static struct {
957 	struct cmsghdr cm;
958 	struct in_pktinfo ipi;
959 } cmsg = { {sizeof(struct cmsghdr) + sizeof(struct in_pktinfo), SOL_IP, IP_PKTINFO},
960 	   {0, }};
961 int cmsg_len;
962 
963 struct sockaddr_in source;
964 char *device;
965 int pmtudisc = -1;
966 
receive_error_msg()967 int receive_error_msg()
968 {
969 	int res;
970 	char cbuf[512];
971 	struct iovec  iov;
972 	struct msghdr msg;
973 	struct cmsghdr *cmsg;
974 	struct sock_extended_err *e;
975 	struct icmphdr icmph;
976 	struct sockaddr_in target;
977 	int net_errors = 0;
978 	int local_errors = 0;
979 	int saved_errno = errno;
980 
981 	iov.iov_base = &icmph;
982 	iov.iov_len = sizeof(icmph);
983 	msg.msg_name = (void*)&target;
984 	msg.msg_namelen = sizeof(target);
985 	msg.msg_iov = &iov;
986 	msg.msg_iovlen = 1;
987 	msg.msg_flags = 0;
988 	msg.msg_control = cbuf;
989 	msg.msg_controllen = sizeof(cbuf);
990 
991 	res = recvmsg(icmp_sock, &msg, MSG_ERRQUEUE|MSG_DONTWAIT);
992 	if (res < 0)
993 		goto out;
994 
995 	e = NULL;
996 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
997 		if (cmsg->cmsg_level == SOL_IP) {
998 			if (cmsg->cmsg_type == IP_RECVERR)
999 				e = (struct sock_extended_err *)CMSG_DATA(cmsg);
1000 		}
1001 	}
1002 	if (e == NULL)
1003 		abort();
1004 
1005 	if (e->ee_origin == SO_EE_ORIGIN_LOCAL) {
1006 		local_errors++;
1007 		if (options & F_QUIET)
1008 			goto out;
1009 		if (options & F_FLOOD)
1010 			write(STDOUT_FILENO, "E", 1);
1011 		else if (e->ee_errno != EMSGSIZE)
1012 			fprintf(stderr, "ping: local error: %s\n", strerror(e->ee_errno));
1013 		else
1014 			fprintf(stderr, "ping: local error: Message too long, mtu=%u\n", e->ee_info);
1015 		nerrors++;
1016 	} else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
1017 		struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);
1018 
1019 		if (res < sizeof(icmph) ||
1020 		    target.sin_addr.s_addr != whereto.sin_addr.s_addr ||
1021 		    icmph.type != ICMP_ECHO ||
1022 		    icmph.un.echo.id != ident) {
1023 			/* Not our error, not an error at all. Clear. */
1024 			saved_errno = 0;
1025 			goto out;
1026 		}
1027 
1028 		acknowledge(ntohs(icmph.un.echo.sequence));
1029 
1030 		if (!working_recverr) {
1031 			struct icmp_filter filt;
1032 			working_recverr = 1;
1033 			/* OK, it works. Add stronger filter. */
1034 			filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
1035 				      (1<<ICMP_REDIRECT)|
1036 				      (1<<ICMP_ECHOREPLY));
1037 			if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1)
1038 				perror("\rWARNING: setsockopt(ICMP_FILTER)");
1039 		}
1040 
1041 		net_errors++;
1042 		nerrors++;
1043 		if (options & F_QUIET)
1044 			goto out;
1045 		if (options & F_FLOOD) {
1046 			write(STDOUT_FILENO, "\bE", 2);
1047 		} else {
1048 			printf("From %s icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
1049 			pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL);
1050 			fflush(stdout);
1051 		}
1052 	}
1053 
1054 out:
1055 	errno = saved_errno;
1056 	return net_errors ? : -local_errors;
1057 }
1058 
1059 /*
1060  * pinger --
1061  * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
1062  * will be added on by the kernel.  The ID field is our UNIX process ID,
1063  * and the sequence number is an ascending integer.  The first 8 bytes
1064  * of the data portion are used to hold a UNIX "timeval" struct in VAX
1065  * byte-order, to compute the round-trip time.
1066  */
send_probe()1067 int send_probe()
1068 {
1069 	struct icmphdr *icp;
1070 	int cc;
1071 	int i;
1072 
1073 	icp = (struct icmphdr *)outpack;
1074 	icp->type = ICMP_ECHO;
1075 	icp->code = 0;
1076 	icp->checksum = 0;
1077 	icp->un.echo.sequence = htons(ntransmitted+1);
1078 	icp->un.echo.id = ident;			/* ID */
1079 
1080 	CLR((ntransmitted+1) % mx_dup_ck);
1081 
1082 	if (timing) {
1083 		if (options&F_LATENCY) {
1084 			static volatile int fake_fucked_egcs = sizeof(struct timeval);
1085 			struct timeval tmp_tv;
1086 			gettimeofday(&tmp_tv, NULL);
1087 			/* egcs is crap or glibc is crap, but memcpy
1088 			   does not copy anything, if len is constant! */
1089 			memcpy(icp+1, &tmp_tv, fake_fucked_egcs);
1090 		} else {
1091 			memset(icp+1, 0, sizeof(struct timeval));
1092 		}
1093 	}
1094 
1095 	cc = datalen + 8;			/* skips ICMP portion */
1096 
1097 	/* compute ICMP checksum here */
1098 	icp->checksum = in_cksum((u_short *)icp, cc, 0);
1099 
1100 	if (timing && !(options&F_LATENCY)) {
1101 		static volatile int fake_fucked_egcs = sizeof(struct timeval);
1102 	        struct timeval tmp_tv;
1103 		gettimeofday(&tmp_tv, NULL);
1104 		/* egcs is crap or glibc is crap, but memcpy
1105 		   does not copy anything, if len is constant! */
1106 		memcpy(icp+1, &tmp_tv, fake_fucked_egcs);
1107 		icp->checksum = in_cksum((u_short *)(icp+1), fake_fucked_egcs, ~icp->checksum);
1108 	}
1109 
1110         do {
1111 		static struct iovec iov = {outpack, 0};
1112 		static struct msghdr m = { &whereto, sizeof(whereto),
1113 						   &iov, 1, &cmsg, 0, 0 };
1114 		m.msg_controllen = cmsg_len;
1115 		iov.iov_len = cc;
1116 
1117 		i = sendmsg(icmp_sock, &m, confirm);
1118 		confirm = 0;
1119 	} while (0);
1120 
1121 	return (cc == i ? 0 : i);
1122 }
1123 
1124 /*
1125  * parse_reply --
1126  *	Print out the packet, if it came from us.  This logic is necessary
1127  * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
1128  * which arrive ('tis only fair).  This permits multiple copies of this
1129  * program to be run without having intermingled output (or statistics!).
1130  */
1131 int
parse_reply(struct msghdr * msg,int cc,void * addr,struct timeval * tv)1132 parse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv)
1133 {
1134 	struct sockaddr_in *from = addr;
1135 	__u8 *buf = msg->msg_iov->iov_base;
1136 	struct icmphdr *icp;
1137 	struct iphdr *ip;
1138 	int hlen;
1139 	int csfailed;
1140 
1141 	/* Check the IP header */
1142 	ip = (struct iphdr *)buf;
1143 	hlen = ip->ihl*4;
1144 	if (cc < hlen + 8 || ip->ihl < 5) {
1145 		if (options & F_VERBOSE)
1146 			fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
1147 				pr_addr(from->sin_addr.s_addr));
1148 		return 1;
1149 	}
1150 
1151 	/* Now the ICMP part */
1152 	cc -= hlen;
1153 	icp = (struct icmphdr *)(buf + hlen);
1154 	csfailed = in_cksum((u_short *)icp, cc, 0);
1155 
1156 	if (icp->type == ICMP_ECHOREPLY) {
1157 		if (icp->un.echo.id != ident)
1158 			return 1;			/* 'Twas not our ECHO */
1159 		if (gather_statistics((__u8*)(icp+1), cc,
1160 				      ntohs(icp->un.echo.sequence),
1161 				      ip->ttl, 0, tv, pr_addr(from->sin_addr.s_addr)))
1162 			return 0;
1163 	} else {
1164 		/* We fall here when a redirect or source quench arrived.
1165 		 * Also this branch processes icmp errors, when IP_RECVERR
1166 		 * is broken. */
1167 
1168 	        switch (icp->type) {
1169 		case ICMP_ECHO:
1170 			/* MUST NOT */
1171 			return 1;
1172 		case ICMP_SOURCE_QUENCH:
1173 		case ICMP_REDIRECT:
1174 		case ICMP_DEST_UNREACH:
1175 		case ICMP_TIME_EXCEEDED:
1176 		case ICMP_PARAMETERPROB:
1177 			{
1178 				struct iphdr * iph = (struct  iphdr *)(&icp[1]);
1179 				struct icmphdr *icp1 = (struct icmphdr*)((unsigned char *)iph + iph->ihl*4);
1180 				int error_pkt;
1181 				if (cc < 8+sizeof(struct iphdr)+8 ||
1182 				    cc < 8+iph->ihl*4+8)
1183 					return 1;
1184 				if (icp1->type != ICMP_ECHO ||
1185 				    iph->daddr != whereto.sin_addr.s_addr ||
1186 				    icp1->un.echo.id != ident)
1187 					return 1;
1188 				error_pkt = (icp->type != ICMP_REDIRECT &&
1189 					     icp->type != ICMP_SOURCE_QUENCH);
1190 				if (error_pkt) {
1191 					acknowledge(ntohs(icp1->un.echo.sequence));
1192 					if (working_recverr) {
1193 						return 0;
1194 					} else {
1195 						static int once;
1196 						/* Sigh, IP_RECVERR for raw socket
1197 						 * was broken until 2.4.9. So, we ignore
1198 						 * the first error and warn on the second.
1199 						 */
1200 						if (once++ == 1)
1201 							fprintf(stderr, "\rWARNING: kernel is not very fresh, upgrade is recommended.\n");
1202 						if (once == 1)
1203 							return 0;
1204 					}
1205 				}
1206 				nerrors+=error_pkt;
1207 				if (options&F_QUIET)
1208 					return !error_pkt;
1209 				if (options & F_FLOOD) {
1210 					if (error_pkt)
1211 						write(STDOUT_FILENO, "\bE", 2);
1212 					return !error_pkt;
1213 				}
1214 				printf("From %s: icmp_seq=%u ",
1215 				       pr_addr(from->sin_addr.s_addr),
1216 				       ntohs(icp1->un.echo.sequence));
1217 				if (csfailed)
1218 					printf("(BAD CHECKSUM)");
1219 				pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
1220 				return !error_pkt;
1221 			}
1222 	        default:
1223 			/* MUST NOT */
1224 			break;
1225 		}
1226 		if ((options & F_FLOOD) && !(options & (F_VERBOSE|F_QUIET))) {
1227 			if (!csfailed)
1228 				write(STDOUT_FILENO, "!E", 2);
1229 			else
1230 				write(STDOUT_FILENO, "!EC", 3);
1231 			return 0;
1232 		}
1233 		if (!(options & F_VERBOSE) || uid)
1234 			return 0;
1235 		printf("From %s: ", pr_addr(from->sin_addr.s_addr));
1236 		if (csfailed) {
1237 			printf("(BAD CHECKSUM)\n");
1238 			return 0;
1239 		}
1240 		pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
1241 		return 0;
1242 	}
1243 
1244 	if (!(options & F_FLOOD)) {
1245 		pr_options(buf + sizeof(struct iphdr), hlen);
1246 
1247 		if (options & F_AUDIBLE)
1248 			putchar('\a');
1249 		putchar('\n');
1250 		fflush(stdout);
1251 	}
1252 	return 0;
1253 }
1254 
1255 u_short
in_cksum(const u_short * addr,register int len,u_short csum)1256 in_cksum(const u_short *addr, register int len, u_short csum)
1257 {
1258 	register int nleft = len;
1259 	const u_short *w = addr;
1260 	register u_short answer;
1261 	register int sum = csum;
1262 
1263 	/*
1264 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
1265 	 *  we add sequential 16 bit words to it, and at the end, fold
1266 	 *  back all the carry bits from the top 16 bits into the lower
1267 	 *  16 bits.
1268 	 */
1269 	while (nleft > 1)  {
1270 		sum += *w++;
1271 		nleft -= 2;
1272 	}
1273 
1274 	/* mop up an odd byte, if necessary */
1275 	if (nleft == 1)
1276 		sum += htons(*(u_char *)w << 8);
1277 
1278 	/*
1279 	 * add back carry outs from top 16 bits to low 16 bits
1280 	 */
1281 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
1282 	sum += (sum >> 16);			/* add carry */
1283 	answer = ~sum;				/* truncate to 16 bits */
1284 	return (answer);
1285 }
1286 
1287 /*
1288  * pr_icmph --
1289  *	Print a descriptive string about an ICMP header.
1290  */
pr_icmph(__u8 type,__u8 code,__u32 info,struct icmphdr * icp)1291 void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp)
1292 {
1293 	switch(type) {
1294 	case ICMP_ECHOREPLY:
1295 		printf("Echo Reply\n");
1296 		/* XXX ID + Seq + Data */
1297 		break;
1298 	case ICMP_DEST_UNREACH:
1299 		switch(code) {
1300 		case ICMP_NET_UNREACH:
1301 			printf("Destination Net Unreachable\n");
1302 			break;
1303 		case ICMP_HOST_UNREACH:
1304 			printf("Destination Host Unreachable\n");
1305 			break;
1306 		case ICMP_PROT_UNREACH:
1307 			printf("Destination Protocol Unreachable\n");
1308 			break;
1309 		case ICMP_PORT_UNREACH:
1310 			printf("Destination Port Unreachable\n");
1311 			break;
1312 		case ICMP_FRAG_NEEDED:
1313 			printf("Frag needed and DF set (mtu = %u)\n", info);
1314 			break;
1315 		case ICMP_SR_FAILED:
1316 			printf("Source Route Failed\n");
1317 			break;
1318 		case ICMP_PKT_FILTERED:
1319 			printf("Packet filtered\n");
1320 			break;
1321 		default:
1322 			printf("Dest Unreachable, Bad Code: %d\n", code);
1323 			break;
1324 		}
1325 		if (icp && (options & F_VERBOSE))
1326 			pr_iph((struct iphdr*)(icp + 1));
1327 		break;
1328 	case ICMP_SOURCE_QUENCH:
1329 		printf("Source Quench\n");
1330 		if (icp && (options & F_VERBOSE))
1331 			pr_iph((struct iphdr*)(icp + 1));
1332 		break;
1333 	case ICMP_REDIRECT:
1334 		switch(code) {
1335 		case ICMP_REDIR_NET:
1336 			printf("Redirect Network");
1337 			break;
1338 		case ICMP_REDIR_HOST:
1339 			printf("Redirect Host");
1340 			break;
1341 		case ICMP_REDIR_NETTOS:
1342 			printf("Redirect Type of Service and Network");
1343 			break;
1344 		case ICMP_REDIR_HOSTTOS:
1345 			printf("Redirect Type of Service and Host");
1346 			break;
1347 		default:
1348 			printf("Redirect, Bad Code: %d", code);
1349 			break;
1350 		}
1351 		if (icp)
1352 			printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway));
1353 		if (icp && (options & F_VERBOSE))
1354 			pr_iph((struct iphdr*)(icp + 1));
1355 		break;
1356 	case ICMP_ECHO:
1357 		printf("Echo Request\n");
1358 		/* XXX ID + Seq + Data */
1359 		break;
1360 	case ICMP_TIME_EXCEEDED:
1361 		switch(code) {
1362 		case ICMP_EXC_TTL:
1363 			printf("Time to live exceeded\n");
1364 			break;
1365 		case ICMP_EXC_FRAGTIME:
1366 			printf("Frag reassembly time exceeded\n");
1367 			break;
1368 		default:
1369 			printf("Time exceeded, Bad Code: %d\n", code);
1370 			break;
1371 		}
1372 		if (icp && (options & F_VERBOSE))
1373 			pr_iph((struct iphdr*)(icp + 1));
1374 		break;
1375 	case ICMP_PARAMETERPROB:
1376 		printf("Parameter problem: pointer = %u\n", icp ? (ntohl(icp->un.gateway)>>24) : info);
1377 		if (icp && (options & F_VERBOSE))
1378 			pr_iph((struct iphdr*)(icp + 1));
1379 		break;
1380 	case ICMP_TIMESTAMP:
1381 		printf("Timestamp\n");
1382 		/* XXX ID + Seq + 3 timestamps */
1383 		break;
1384 	case ICMP_TIMESTAMPREPLY:
1385 		printf("Timestamp Reply\n");
1386 		/* XXX ID + Seq + 3 timestamps */
1387 		break;
1388 	case ICMP_INFO_REQUEST:
1389 		printf("Information Request\n");
1390 		/* XXX ID + Seq */
1391 		break;
1392 	case ICMP_INFO_REPLY:
1393 		printf("Information Reply\n");
1394 		/* XXX ID + Seq */
1395 		break;
1396 #ifdef ICMP_MASKREQ
1397 	case ICMP_MASKREQ:
1398 		printf("Address Mask Request\n");
1399 		break;
1400 #endif
1401 #ifdef ICMP_MASKREPLY
1402 	case ICMP_MASKREPLY:
1403 		printf("Address Mask Reply\n");
1404 		break;
1405 #endif
1406 	default:
1407 		printf("Bad ICMP type: %d\n", type);
1408 	}
1409 }
1410 
pr_options(unsigned char * cp,int hlen)1411 void pr_options(unsigned char * cp, int hlen)
1412 {
1413 	int i, j;
1414 	int optlen, totlen;
1415 	unsigned char * optptr;
1416 	static int old_rrlen;
1417 	static char old_rr[MAX_IPOPTLEN];
1418 
1419 	totlen = hlen-sizeof(struct iphdr);
1420 	optptr = cp;
1421 
1422 	while (totlen > 0) {
1423 		if (*optptr == IPOPT_EOL)
1424 			break;
1425 		if (*optptr == IPOPT_NOP) {
1426 			totlen--;
1427 			optptr++;
1428 			printf("\nNOP");
1429 			continue;
1430 		}
1431 		cp = optptr;
1432 		optlen = optptr[1];
1433 		if (optlen < 2 || optlen > totlen)
1434 			break;
1435 
1436 		switch (*cp) {
1437 		case IPOPT_SSRR:
1438 		case IPOPT_LSRR:
1439 			printf("\n%cSRR: ", *cp==IPOPT_SSRR ? 'S' : 'L');
1440 			j = *++cp;
1441 			i = *++cp;
1442 			i -= 4;
1443 			cp++;
1444 			if (j > IPOPT_MINOFF) {
1445 				for (;;) {
1446 					__u32 address;
1447 					memcpy(&address, cp, 4);
1448 					cp += 4;
1449 					if (address == 0)
1450 						printf("\t0.0.0.0");
1451 					else
1452 						printf("\t%s", pr_addr(address));
1453 					j -= 4;
1454 					putchar('\n');
1455 					if (j <= IPOPT_MINOFF)
1456 						break;
1457 				}
1458 			}
1459 			break;
1460 		case IPOPT_RR:
1461 			j = *++cp;		/* get length */
1462 			i = *++cp;		/* and pointer */
1463 			if (i > j)
1464 				i = j;
1465 			i -= IPOPT_MINOFF;
1466 			if (i <= 0)
1467 				continue;
1468 			if (i == old_rrlen
1469 			    && !memcmp((char *)cp, old_rr, i)
1470 			    && !(options & F_FLOOD)) {
1471 				printf("\t(same route)");
1472 				i = ((i + 3) / 4) * 4;
1473 				cp += i;
1474 				break;
1475 			}
1476 			old_rrlen = i;
1477 			memcpy((char *)cp, old_rr, i);
1478 			printf("\nRR: ");
1479 			cp++;
1480 			for (;;) {
1481 				__u32 address;
1482 				memcpy(&address, cp, 4);
1483 				cp += 4;
1484 				if (address == 0)
1485 					printf("\t0.0.0.0");
1486 				else
1487 					printf("\t%s", pr_addr(address));
1488 				i -= 4;
1489 				putchar('\n');
1490 				if (i <= 0)
1491 					break;
1492 			}
1493 			break;
1494 		case IPOPT_TS:
1495 		{
1496 			int stdtime = 0, nonstdtime = 0;
1497 			__u8 flags;
1498 			j = *++cp;		/* get length */
1499 			i = *++cp;		/* and pointer */
1500 			if (i > j)
1501 				i = j;
1502 			i -= 5;
1503 			if (i <= 0)
1504 				continue;
1505 			flags = *++cp;
1506 			printf("\nTS: ");
1507 			cp++;
1508 			for (;;) {
1509 				long l;
1510 
1511 				if ((flags&0xF) != IPOPT_TS_TSONLY) {
1512 					__u32 address;
1513 					memcpy(&address, cp, 4);
1514 					cp += 4;
1515 					if (address == 0)
1516 						printf("\t0.0.0.0");
1517 					else
1518 						printf("\t%s", pr_addr(address));
1519 					i -= 4;
1520 					if (i <= 0)
1521 						break;
1522 				}
1523 				l = *cp++;
1524 				l = (l<<8) + *cp++;
1525 				l = (l<<8) + *cp++;
1526 				l = (l<<8) + *cp++;
1527 
1528 				if  (l & 0x80000000) {
1529 					if (nonstdtime==0)
1530 						printf("\t%ld absolute not-standard", l&0x7fffffff);
1531 					else
1532 						printf("\t%ld not-standard", (l&0x7fffffff) - nonstdtime);
1533 					nonstdtime = l&0x7fffffff;
1534 				} else {
1535 					if (stdtime==0)
1536 						printf("\t%ld absolute", l);
1537 					else
1538 						printf("\t%ld", l - stdtime);
1539 					stdtime = l;
1540 				}
1541 				i -= 4;
1542 				putchar('\n');
1543 				if (i <= 0)
1544 					break;
1545 			}
1546 			if (flags>>4)
1547 				printf("Unrecorded hops: %d\n", flags>>4);
1548 			break;
1549 		}
1550 		default:
1551 			printf("\nunknown option %x", *cp);
1552 			break;
1553 		}
1554 		totlen -= optlen;
1555 		optptr += optlen;
1556 	}
1557 }
1558 
1559 
1560 /*
1561  * pr_iph --
1562  *	Print an IP header with options.
1563  */
pr_iph(struct iphdr * ip)1564 void pr_iph(struct iphdr *ip)
1565 {
1566 	int hlen;
1567 	u_char *cp;
1568 
1569 	hlen = ip->ihl << 2;
1570 	cp = (u_char *)ip + 20;		/* point to options */
1571 
1572 	printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
1573 	printf(" %1x  %1x  %02x %04x %04x",
1574 	       ip->version, ip->ihl, ip->tos, ip->tot_len, ip->id);
1575 	printf("   %1x %04x", ((ip->frag_off) & 0xe000) >> 13,
1576 	       (ip->frag_off) & 0x1fff);
1577 	printf("  %02x  %02x %04x", ip->ttl, ip->protocol, ip->check);
1578 	printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->saddr));
1579 	printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->daddr));
1580 	printf("\n");
1581 	pr_options(cp, hlen);
1582 }
1583 
1584 /*
1585  * pr_addr --
1586  *	Return an ascii host address as a dotted quad and optionally with
1587  * a hostname.
1588  */
1589 char *
pr_addr(__u32 addr)1590 pr_addr(__u32 addr)
1591 {
1592 	struct hostent *hp;
1593 	static char buf[4096];
1594 
1595 	if ((options & F_NUMERIC) ||
1596 	    !(hp = gethostbyaddr((char *)&addr, 4, AF_INET)))
1597 		sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&addr));
1598 	else
1599 		snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name,
1600 			 inet_ntoa(*(struct in_addr *)&addr));
1601 	return(buf);
1602 }
1603 
1604 
1605 /* Set Type of Service (TOS) and other Quality of Service relating bits */
parsetos(char * str)1606 int parsetos(char *str)
1607 {
1608         const char *cp;
1609         int tos;
1610         char *ep;
1611 
1612         /* handle both hex and decimal values */
1613         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1614 		cp = str + 2;
1615 		tos = (int)strtol(cp, &ep, 16);
1616         } else
1617                 tos = (int)strtol(str, &ep, 10);
1618 
1619         /* doesn't look like decimal or hex, eh? */
1620         if (*ep != '\0') {
1621         	fprintf(stderr, "ping: \"%s\" bad value for TOS\n", str);
1622         	exit(2);
1623         }
1624 
1625         if (tos > TOS_MAX) {
1626         	fprintf(stderr, "ping: the decimal value of TOS bits must be 0-254 (or zero)\n");
1627         	exit(2);
1628         }
1629 	return(tos);
1630 }
1631 
1632 #include <linux/filter.h>
1633 
install_filter(void)1634 void install_filter(void)
1635 {
1636 	static int once;
1637 	static struct sock_filter insns[] = {
1638 		BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* Skip IP header. F..g BSD... Look into ping6. */
1639 		BPF_STMT(BPF_LD|BPF_H|BPF_IND, 4), /* Load icmp echo ident */
1640 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xAAAA, 0, 1), /* Ours? */
1641 		BPF_STMT(BPF_RET|BPF_K, ~0U), /* Yes, it passes. */
1642 		BPF_STMT(BPF_LD|BPF_B|BPF_IND, 0), /* Load icmp type */
1643 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ICMP_ECHOREPLY, 1, 0), /* Echo? */
1644 		BPF_STMT(BPF_RET|BPF_K, 0xFFFFFFF), /* No. It passes. */
1645 		BPF_STMT(BPF_RET|BPF_K, 0) /* Echo with wrong ident. Reject. */
1646 	};
1647 	static struct sock_fprog filter = {
1648 		sizeof insns / sizeof(insns[0]),
1649 		insns
1650 	};
1651 
1652 	if (once)
1653 		return;
1654 	once = 1;
1655 
1656 	/* Patch bpflet for current identifier. */
1657 	insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1);
1658 
1659 	if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
1660 		perror("WARNING: failed to install socket filter\n");
1661 }
1662 
1663 
usage(void)1664 void usage(void)
1665 {
1666 	fprintf(stderr,
1667 "Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]\n"
1668 "            [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]\n"
1669 "            [-M mtu discovery hint] [-S sndbuf]\n"
1670 "            [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination\n");
1671 	exit(2);
1672 }
1673 
isInSupplementaryGroup(gid_t group)1674 int isInSupplementaryGroup(gid_t group) {
1675 	long ngroups_max;
1676 	gid_t empty[0];
1677 	gid_t *groups;
1678 	int ngroups;
1679 	int i;
1680 
1681 	if (getuid() == 0) {
1682 		// root is presumed to be in every group
1683 		return 1;
1684 	}
1685 
1686 	ngroups = getgroups(0, empty);
1687 	if (ngroups < 0) {
1688 		perror("ping: call to getgroups for sizing failed");
1689 		exit(2);
1690 	}
1691 	groups = (gid_t *) malloc((ngroups * sizeof(gid_t)));
1692 	if (groups == NULL) {
1693 		fprintf(stderr, "ping: unable to allocate memory for %d groups.  Aborting\n", ngroups);
1694 		exit(2);
1695 	}
1696 	ngroups = getgroups(ngroups, groups);
1697 	if (ngroups < 0) {
1698 		perror("ping: getgroups failed");
1699 		exit(2);
1700 	}
1701 
1702 	for (i = 0; i < ngroups; i++) {
1703 		if (group == groups[i]) {
1704 			free(groups);
1705 			return 1;
1706 		}
1707 	}
1708 
1709 	free(groups);
1710 	return 0;
1711 }
1712 
main(int argc,char * argv[])1713 int main(int argc, char *argv[])
1714 {
1715 	struct hostent *hp;
1716 	int ch, hold, packlen;
1717 	int socket_errno;
1718 	u_char *packet;
1719 	char *target, hnamebuf[MAXHOSTNAMELEN];
1720 	char rspace[3 + 4 * NROUTES + 1];	/* record route space */
1721 
1722 	icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
1723 	socket_errno = errno;
1724 
1725 	/* if we were setuid root, undo that */
1726 	if (setuid(getuid())) return -1;
1727 
1728 	if (!isInSupplementaryGroup(AID_INET)) {
1729 		fprintf(stderr, "You must have internet permissions to use ping.  Aborting.\n");
1730 		exit(2);
1731 	}
1732 
1733 	source.sin_family = AF_INET;
1734 
1735 	preload = 1;
1736 	while ((ch = getopt(argc, argv, COMMON_OPTSTR "bRT:")) != EOF) {
1737 		switch(ch) {
1738 		case 'b':
1739 		        broadcast_pings = 1;
1740 			break;
1741 		case 'Q':
1742 			settos = parsetos(optarg);
1743 			if (settos &&
1744 			    (setsockopt(icmp_sock, IPPROTO_IP, IP_TOS,
1745 					(char *)&settos, sizeof(int)) < 0)) {
1746 				perror("ping: error setting QOS sockopts");
1747 				exit(2);
1748 			}
1749 			break;
1750 		case 'R':
1751 			if (options & F_TIMESTAMP) {
1752 				fprintf(stderr, "Only one of -T or -R may be used\n");
1753 				exit(2);
1754 			}
1755 			options |= F_RROUTE;
1756 			break;
1757 		case 'T':
1758 			if (options & F_RROUTE) {
1759 				fprintf(stderr, "Only one of -T or -R may be used\n");
1760 				exit(2);
1761 			}
1762 			options |= F_TIMESTAMP;
1763 			if (strcmp(optarg, "tsonly") == 0)
1764 				ts_type = IPOPT_TS_TSONLY;
1765 			else if (strcmp(optarg, "tsandaddr") == 0)
1766 				ts_type = IPOPT_TS_TSANDADDR;
1767 			else if (strcmp(optarg, "tsprespec") == 0)
1768 				ts_type = IPOPT_TS_PRESPEC;
1769 			else {
1770 				fprintf(stderr, "Invalid timestamp type\n");
1771 				exit(2);
1772 			}
1773 			break;
1774 		case 'I':
1775 		{
1776 			char dummy;
1777 			int i1, i2, i3, i4;
1778 
1779 			if (sscanf(optarg, "%u.%u.%u.%u%c",
1780 				   &i1, &i2, &i3, &i4, &dummy) == 4) {
1781 				__u8 *ptr;
1782 				ptr = (__u8*)&source.sin_addr;
1783 				ptr[0] = i1;
1784 				ptr[1] = i2;
1785 				ptr[2] = i3;
1786 				ptr[3] = i4;
1787 				options |= F_STRICTSOURCE;
1788 			} else {
1789 				device = optarg;
1790 			}
1791 			break;
1792 		}
1793 		case 'M':
1794 			if (strcmp(optarg, "do") == 0)
1795 				pmtudisc = IP_PMTUDISC_DO;
1796 			else if (strcmp(optarg, "dont") == 0)
1797 				pmtudisc = IP_PMTUDISC_DONT;
1798 			else if (strcmp(optarg, "want") == 0)
1799 				pmtudisc = IP_PMTUDISC_WANT;
1800 			else {
1801 				fprintf(stderr, "ping: wrong value for -M: do, dont, want are valid ones.\n");
1802 				exit(2);
1803 			}
1804 			break;
1805 		case 'V':
1806 			printf("ping utility, iputils-ss\n");
1807 			exit(0);
1808 		COMMON_OPTIONS
1809 			common_options(ch);
1810 			break;
1811 		default:
1812 			usage();
1813 		}
1814 	}
1815 	argc -= optind;
1816 	argv += optind;
1817 
1818 	if (argc == 0)
1819 		usage();
1820 	if (argc > 1) {
1821 		if (options & F_RROUTE)
1822 			usage();
1823 		else if (options & F_TIMESTAMP) {
1824 			if (ts_type != IPOPT_TS_PRESPEC)
1825 				usage();
1826 			if (argc > 5)
1827 				usage();
1828 		} else {
1829 			if (argc > 10)
1830 				usage();
1831 			options |= F_SOURCEROUTE;
1832 		}
1833 	}
1834 	while (argc > 0) {
1835 		target = *argv;
1836 
1837 		bzero((char *)&whereto, sizeof(whereto));
1838 		whereto.sin_family = AF_INET;
1839 		if (inet_aton(target, &whereto.sin_addr) == 1) {
1840 			hostname = target;
1841 			if (argc == 1)
1842 				options |= F_NUMERIC;
1843 		} else {
1844 			hp = gethostbyname(target);
1845 			hp = gethostbyname(target);
1846 			hp = gethostbyname(target);
1847 			if (!hp) {
1848 				fprintf(stderr, "ping: unknown host %s\n", target);
1849 				exit(2);
1850 			}
1851 			memcpy(&whereto.sin_addr, hp->h_addr, 4);
1852 			strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
1853 			hnamebuf[sizeof(hnamebuf) - 1] = 0;
1854 			hostname = hnamebuf;
1855 		}
1856 		if (argc > 1)
1857 			route[nroute++] = whereto.sin_addr.s_addr;
1858 		argc--;
1859 		argv++;
1860 	}
1861 
1862 	if (source.sin_addr.s_addr == 0) {
1863 		int alen;
1864 		struct sockaddr_in dst = whereto;
1865 		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
1866 
1867 		if (probe_fd < 0) {
1868 			perror("socket");
1869 			exit(2);
1870 		}
1871 		if (device) {
1872 			struct ifreq ifr;
1873 			memset(&ifr, 0, sizeof(ifr));
1874 			strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
1875 			if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) {
1876 				if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
1877 					struct ip_mreqn imr;
1878 					if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) {
1879 						fprintf(stderr, "ping: unknown iface %s\n", device);
1880 						exit(2);
1881 					}
1882 					memset(&imr, 0, sizeof(imr));
1883 					imr.imr_ifindex = ifr.ifr_ifindex;
1884 					if (setsockopt(probe_fd, SOL_IP, IP_MULTICAST_IF, &imr, sizeof(imr)) == -1) {
1885 						perror("ping: IP_MULTICAST_IF");
1886 						exit(2);
1887 					}
1888 				}
1889 			}
1890 		}
1891 
1892 		if (settos &&
1893 		    setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *)&settos, sizeof(int)) < 0)
1894 			perror("Warning: error setting QOS sockopts");
1895 
1896 		dst.sin_port = htons(1025);
1897 		if (nroute)
1898 			dst.sin_addr.s_addr = route[0];
1899 		if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
1900 			if (errno == EACCES) {
1901 				if (broadcast_pings == 0) {
1902 					fprintf(stderr, "Do you want to ping broadcast? Then -b\n");
1903 					exit(2);
1904 				}
1905 				fprintf(stderr, "WARNING: pinging broadcast address\n");
1906 				if (setsockopt(probe_fd, SOL_SOCKET, SO_BROADCAST,
1907 					       &broadcast_pings, sizeof(broadcast_pings)) < 0) {
1908 					perror ("can't set broadcasting");
1909 					exit(2);
1910 				}
1911 				if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
1912 					perror("connect");
1913 					exit(2);
1914 				}
1915 			} else {
1916 				perror("connect");
1917 				exit(2);
1918 			}
1919 		}
1920 		alen = sizeof(source);
1921 		if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) {
1922 			perror("getsockname");
1923 			exit(2);
1924 		}
1925 		source.sin_port = 0;
1926 		close(probe_fd);
1927 	} while (0);
1928 
1929 	if (whereto.sin_addr.s_addr == 0)
1930 		whereto.sin_addr.s_addr = source.sin_addr.s_addr;
1931 
1932 	if (icmp_sock < 0) {
1933 		errno = socket_errno;
1934 		perror("ping: icmp open socket");
1935 		exit(2);
1936 	}
1937 
1938 	if (device) {
1939 		struct ifreq ifr;
1940 
1941 		memset(&ifr, 0, sizeof(ifr));
1942 		strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
1943 		if (ioctl(icmp_sock, SIOCGIFINDEX, &ifr) < 0) {
1944 			fprintf(stderr, "ping: unknown iface %s\n", device);
1945 			exit(2);
1946 		}
1947 		cmsg.ipi.ipi_ifindex = ifr.ifr_ifindex;
1948 		cmsg_len = sizeof(cmsg);
1949 	}
1950 
1951 	if (broadcast_pings || IN_MULTICAST(ntohl(whereto.sin_addr.s_addr))) {
1952 		if (uid) {
1953 			if (interval < 1000) {
1954 				fprintf(stderr, "ping: broadcast ping with too short interval.\n");
1955 				exit(2);
1956 			}
1957 			if (pmtudisc >= 0 && pmtudisc != IP_PMTUDISC_DO) {
1958 				fprintf(stderr, "ping: broadcast ping does not fragment.\n");
1959 				exit(2);
1960 			}
1961 		}
1962 		if (pmtudisc < 0)
1963 			pmtudisc = IP_PMTUDISC_DO;
1964 	}
1965 
1966 	if (pmtudisc >= 0) {
1967 		if (setsockopt(icmp_sock, SOL_IP, IP_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc)) == -1) {
1968 			perror("ping: IP_MTU_DISCOVER");
1969 			exit(2);
1970 		}
1971 	}
1972 
1973 	if ((options&F_STRICTSOURCE) &&
1974 	    bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
1975 		perror("bind");
1976 		exit(2);
1977 	}
1978 
1979 	if (1) {
1980 		struct icmp_filter filt;
1981 		filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
1982 			      (1<<ICMP_DEST_UNREACH)|
1983 			      (1<<ICMP_TIME_EXCEEDED)|
1984 			      (1<<ICMP_PARAMETERPROB)|
1985 			      (1<<ICMP_REDIRECT)|
1986 			      (1<<ICMP_ECHOREPLY));
1987 		if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1)
1988 			perror("WARNING: setsockopt(ICMP_FILTER)");
1989 	}
1990 
1991 	hold = 1;
1992 	if (setsockopt(icmp_sock, SOL_IP, IP_RECVERR, (char *)&hold, sizeof(hold)))
1993 		fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n");
1994 
1995 	/* record route option */
1996 	if (options & F_RROUTE) {
1997 	        bzero(rspace, sizeof(rspace));
1998 		rspace[0] = IPOPT_NOP;
1999 		rspace[1+IPOPT_OPTVAL] = IPOPT_RR;
2000 		rspace[1+IPOPT_OLEN] = sizeof(rspace)-1;
2001 		rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF;
2002 		optlen = 40;
2003 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0) {
2004 			perror("ping: record route");
2005 			exit(2);
2006 		}
2007 	}
2008 	if (options & F_TIMESTAMP) {
2009 	        bzero(rspace, sizeof(rspace));
2010 		rspace[0] = IPOPT_TIMESTAMP;
2011 		rspace[1] = (ts_type==IPOPT_TS_TSONLY ? 40 : 36);
2012 		rspace[2] = 5;
2013 		rspace[3] = ts_type;
2014 		if (ts_type == IPOPT_TS_PRESPEC) {
2015 			int i;
2016 			rspace[1] = 4+nroute*8;
2017 			for (i=0; i<nroute; i++)
2018 				*(__u32*)&rspace[4+i*8] = route[i];
2019 		}
2020 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) {
2021 			rspace[3] = 2;
2022 			if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) {
2023 				perror("ping: ts option");
2024 				exit(2);
2025 			}
2026 		}
2027 		optlen = 40;
2028 	}
2029 	if (options & F_SOURCEROUTE) {
2030 	        int i;
2031 	        bzero(rspace, sizeof(rspace));
2032 		rspace[0] = IPOPT_NOOP;
2033 		rspace[1+IPOPT_OPTVAL] = (options & F_SO_DONTROUTE) ? IPOPT_SSRR
2034 			: IPOPT_LSRR;
2035 		rspace[1+IPOPT_OLEN] = 3 + nroute*4;
2036 		rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF;
2037 		for (i=0; i<nroute; i++)
2038 			*(__u32*)&rspace[4+i*4] = route[i];
2039 
2040 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, 4 + nroute*4) < 0) {
2041 			perror("ping: record route");
2042 			exit(2);
2043 		}
2044 		optlen = 40;
2045 	}
2046 
2047 	/* Estimate memory eaten by single packet. It is rough estimate.
2048 	 * Actually, for small datalen's it depends on kernel side a lot. */
2049 	hold = datalen + 8;
2050 	hold += ((hold+511)/512)*(optlen + 20 + 16 + 64 + 160);
2051 	sock_setbufs(icmp_sock, hold);
2052 
2053 	if (broadcast_pings) {
2054 		if (setsockopt(icmp_sock, SOL_SOCKET, SO_BROADCAST,
2055 			       &broadcast_pings, sizeof(broadcast_pings)) < 0) {
2056 			perror ("ping: can't set broadcasting");
2057 			exit(2);
2058 		}
2059         }
2060 
2061 	if (options & F_NOLOOP) {
2062 		int loop = 0;
2063 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_LOOP,
2064 							&loop, 1) == -1) {
2065 			perror ("ping: can't disable multicast loopback");
2066 			exit(2);
2067 		}
2068 	}
2069 	if (options & F_TTL) {
2070 		int ittl = ttl;
2071 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_TTL,
2072 							&ttl, 1) == -1) {
2073 			perror ("ping: can't set multicast time-to-live");
2074 			exit(2);
2075 		}
2076 		if (setsockopt(icmp_sock, IPPROTO_IP, IP_TTL,
2077 							&ittl, sizeof(ittl)) == -1) {
2078 			perror ("ping: can't set unicast time-to-live");
2079 			exit(2);
2080 		}
2081 	}
2082 
2083 	if (datalen > 0xFFFF - 8 - optlen - 20) {
2084 		if (uid || datalen > sizeof(outpack)-8) {
2085 			fprintf(stderr, "Error: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen);
2086 			exit(2);
2087 		}
2088 		/* Allow small oversize to root yet. It will cause EMSGSIZE. */
2089 		fprintf(stderr, "WARNING: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen);
2090 	}
2091 
2092 	if (datalen >= sizeof(struct timeval))	/* can we time transfer */
2093 		timing = 1;
2094 	packlen = datalen + MAXIPLEN + MAXICMPLEN;
2095 	if (!(packet = (u_char *)malloc((u_int)packlen))) {
2096 		fprintf(stderr, "ping: out of memory.\n");
2097 		exit(2);
2098 	}
2099 
2100 	printf("PING %s (%s) ", hostname, inet_ntoa(whereto.sin_addr));
2101 	if (device || (options&F_STRICTSOURCE))
2102 		printf("from %s %s: ", inet_ntoa(source.sin_addr), device ?: "");
2103 	printf("%d(%d) bytes of data.\n", datalen, datalen+8+optlen+20);
2104 
2105 	setup(icmp_sock);
2106 
2107 	main_loop(icmp_sock, packet, packlen);
2108 	return 0;
2109 }
2110 
dlopen(const char * filename,int flag)2111 void *dlopen(const char *filename, int flag) { return 0; }
dlerror(void)2112 char *dlerror(void) { return 0; }
dlsym(void * handle,const char * symbol)2113 void *dlsym(void *handle, const char *symbol) { return 0; }
dlclose(void * handle)2114 int dlclose(void *handle) { return 0; }
2115