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
38char 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
73int options;
74
75int sndbuf;
76int ttl;
77int rtt;
78int rtt_addend;
79__u16 acked;
80
81int mx_dup_ck = MAX_DUP_CHK;
82char rcvd_tbl[MAX_DUP_CHK / 8];
83
84
85/* counters */
86long npackets;			/* max packets to transmit */
87long nreceived;			/* # of packets we got back */
88long nrepeats;			/* number of duplicates */
89long ntransmitted;		/* sequence # for outbound packets = #sent */
90long nchecksum;			/* replies with bad checksum */
91long nerrors;			/* icmp errors */
92int interval = 1000;		/* interval between packets (msec) */
93int preload;
94int deadline = 0;		/* time to die */
95int lingertime = MAXWAIT*1000;
96struct timeval start_time, cur_time;
97volatile int exiting;
98volatile int status_snapshot;
99int 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 */
104int 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] */
107int working_recverr;
108
109/* timing */
110int timing;			/* flag to do timing */
111long tmin = LONG_MAX;		/* minimum round trip time */
112long 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 */
118long long tsum;			/* sum of all times, for doing average */
119long long tsum2;
120int  pipesize = -1;
121
122int datalen = DEFDATALEN;
123
124char *hostname;
125int uid;
126int ident;			/* process id to identify our packets */
127
128static int screen_width = INT_MAX;
129
130/* Fills all the outpack, excluding ICMP header, but _including_
131 * timestamp area with supplied pattern.
132 */
133static 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
166void 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
296static void sigexit(int signo)
297{
298	exiting = 1;
299}
300
301static void sigstatus(int signo)
302{
303	status_snapshot = 1;
304}
305
306
307int __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
333static 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 */
350int 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
387resend:
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
461void 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
482void 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
574void 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
717int 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
731restamp:
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
830static 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 */
849void 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
900void 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
933static int ts_type;
934static int nroute = 0;
935static __u32 route[10];
936
937
938
939struct sockaddr_in whereto;	/* who to ping */
940int optlen = 0;
941int settos = 0;			/* Set TOS, Precendence or other QOS options */
942int icmp_sock;			/* socket file descriptor */
943u_char outpack[0x10000];
944int maxpacket = sizeof(outpack);
945
946static int broadcast_pings = 0;
947
948static char *pr_addr(__u32);
949static void pr_options(unsigned char * cp, int hlen);
950static void pr_iph(struct iphdr *ip);
951static void usage(void) __attribute__((noreturn));
952static u_short in_cksum(const u_short *addr, int len, u_short salt);
953static void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp);
954static int parsetos(char *str);
955
956static 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, }};
961int cmsg_len;
962
963struct sockaddr_in source;
964char *device;
965int pmtudisc = -1;
966
967int 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
1054out:
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 */
1067int 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 */
1131int
1132parse_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
1255u_short
1256in_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 */
1291void 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
1411void 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 */
1564void 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 */
1589char *
1590pr_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 */
1606int 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
1634void 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
1664void 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
1674int 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
1713int 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
2111void *dlopen(const char *filename, int flag) { return 0; }
2112char *dlerror(void) { return 0; }
2113void *dlsym(void *handle, const char *symbol) { return 0; }
2114int dlclose(void *handle) { return 0; }
2115