10baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
20baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Copyright (c) 1989 The Regents of the University of California.
30baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * All rights reserved.
40baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
50baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * This code is derived from software contributed to Berkeley by
60baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Mike Muuss.
70baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
80baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Redistribution and use in source and binary forms, with or without
90baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * modification, are permitted provided that the following conditions
100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * are met:
110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    documentation and/or other materials provided with the distribution.
160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 3. All advertising materials mentioning features or use of this software
170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    must display the following acknowledgement:
180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	This product includes software developed by the University of
190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	California, Berkeley and its contributors.
200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 4. Neither the name of the University nor the names of its contributors
210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    may be used to endorse or promote products derived from this software
220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *    without specific prior written permission.
230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * SUCH DAMAGE.
350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#ifndef lint
380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar copyright[] =
390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project All rights reserved.\n";
410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif /* not lint */
420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *			P I N G . C
450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * measure round-trip-delays and packet loss across network paths.
480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Author -
500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Mike Muuss
510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	U. S. Army Ballistic Research Laboratory
520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	December, 1983
530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *
540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Status -
550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Public Domain.  Distribution Unlimited.
560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * Bugs -
570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	More statistics could always be gathered.
580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	This program has to run SUID to ROOT to access the ICMP socket.
590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#include "ping_common.h"
620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#include <netinet/ip.h>
640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#include <linux/icmp.h>
650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#include <sched.h>
661fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich#include <sys/types.h>
671fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich#include <private/android_filesystem_config.h>
680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#define bzero(b,sz) memset(b, 0, sz)
700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* PING COMMON */
720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint options;
740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint sndbuf;
760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint ttl;
770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint rtt;
780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint rtt_addend;
790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project__u16 acked;
800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint mx_dup_ck = MAX_DUP_CHK;
820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar rcvd_tbl[MAX_DUP_CHK / 8];
830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* counters */
860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong npackets;			/* max packets to transmit */
870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong nreceived;			/* # of packets we got back */
880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong nrepeats;			/* number of duplicates */
890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong ntransmitted;		/* sequence # for outbound packets = #sent */
900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong nchecksum;			/* replies with bad checksum */
910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong nerrors;			/* icmp errors */
920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint interval = 1000;		/* interval between packets (msec) */
930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint preload;
940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint deadline = 0;		/* time to die */
950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint lingertime = MAXWAIT*1000;
960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstruct timeval start_time, cur_time;
970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvolatile int exiting;
980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvolatile int status_snapshot;
990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint confirm = 0;
1000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Stupid workarounds for bugs/missing functionality in older linuces.
1020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
1030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * i.e. for linux-2.2 */
1040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint confirm_flag = MSG_CONFIRM;
1050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* And this is workaround for bug in IP_RECVERR on raw sockets which is present
1060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * in linux-2.2.[0-19], linux-2.4.[0-7] */
1070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint working_recverr;
1080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* timing */
1100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint timing;			/* flag to do timing */
1110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong tmin = LONG_MAX;		/* minimum round trip time */
1120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong tmax;			/* maximum round trip time */
1130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Message for rpm maintainers: have _shame_. If you want
1140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * to fix something send the patch to me for sanity checking.
1150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * "sparcfix" patch is a complete non-sense, apparenly the person
1160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * prepared it was stoned.
1170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
1180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong long tsum;			/* sum of all times, for doing average */
1190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectlong long tsum2;
1200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint  pipesize = -1;
1210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint datalen = DEFDATALEN;
1230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar *hostname;
1250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint uid;
1260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint ident;			/* process id to identify our packets */
1270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic int screen_width = INT_MAX;
1290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Fills all the outpack, excluding ICMP header, but _including_
1310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * timestamp area with supplied pattern.
1320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
1330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void fill(char *patp)
1340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
1350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int ii, jj, kk;
1360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int pat[16];
1370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char *cp;
1380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char *bp = outpack+8;
1390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	for (cp = patp; *cp; cp++) {
1410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!isxdigit(*cp)) {
1420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr,
1430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				"ping: patterns must be specified as hex digits.\n");
1440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
1450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
1460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
1470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	ii = sscanf(patp,
1480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
1500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
1510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    &pat[13], &pat[14], &pat[15]);
1520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (ii > 0) {
1540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii)
1550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			for (jj = 0; jj < ii; ++jj)
1560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				bp[jj + kk] = pat[jj];
1570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
1580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!(options & F_QUIET)) {
1590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("PATTERN: 0x");
1600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (jj = 0; jj < ii; ++jj)
1610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("%02x", bp[jj] & 0xFF);
1620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("\n");
1630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
1640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
1650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
1660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid common_options(int ch)
1670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
1680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	switch(ch) {
1690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'a':
1700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_AUDIBLE;
1710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
1720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'A':
1730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_ADAPTIVE;
1740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
1750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'c':
1760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		npackets = atoi(optarg);
1770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (npackets <= 0) {
1780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad number of packets to transmit.\n");
1790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
1800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
1810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
1820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'd':
1830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_SO_DEBUG;
1840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
1850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'f':
1860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_FLOOD;
1870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		//setbuf(stdout, (char *)NULL);
1880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
1890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'i':		/* wait between sending packets */
1900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	{
1910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (strchr(optarg, '.')) {
1920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			float t;
1930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (sscanf(optarg, "%f", &t) != 1) {
1940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "ping: bad timing interval.\n");
1950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
1960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
1970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			interval = (int)(t*1000);
1980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else if (sscanf(optarg, "%d", &interval) == 1) {
1990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			interval *= 1000;
2000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else {
2010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad timing interval.\n");
2020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
2050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (interval < 0) {
2060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad timing interval.\n");
2070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_INTERVAL;
2100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
2120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'w':
2130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		deadline = atoi(optarg);
2140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (deadline < 0) {
2150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad wait time.\n");
2160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'l':
2200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		preload = atoi(optarg);
2210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (preload <= 0) {
2220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck);
2230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (preload > mx_dup_ck)
2260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			preload = mx_dup_ck;
2270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (uid && preload > 3) {
2280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: cannot set preload to value > 3\n");
2290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'S':
2330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sndbuf = atoi(optarg);
2340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (sndbuf <= 0) {
2350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad sndbuf value.\n");
2360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'n':
2400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_NUMERIC;
2410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'p':		/* fill buffer with user pattern */
2430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_PINGFILLED;
2440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fill(optarg);
2450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'q':
2470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_QUIET;
2480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'r':
2500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_SO_DONTROUTE;
2510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 's':		/* size of packet to send */
2530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		datalen = atoi(optarg);
2540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (datalen < 0) {
2550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
2560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'v':
2600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_VERBOSE;
2610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'L':
2630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_NOLOOP;
2640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 't':
2660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_TTL;
2670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		ttl = atoi(optarg);
2680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ttl < 0 || ttl > 255) {
2690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
2700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'U':
2740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_LATENCY;
2750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'B':
2770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_STRICTSOURCE;
2780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'W':
2800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		lingertime = atoi(optarg);
2810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
2820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: bad linger time.\n");
2830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
2840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
2850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		lingertime *= 1000;
2860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
2870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case 'V':
2880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("ping utility, iputils-ss\n");
2890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(0);
2900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	default:
2910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		abort();
2920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
2930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
2940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
2950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
2960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void sigexit(int signo)
2970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
2980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	exiting = 1;
2990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
3000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void sigstatus(int signo)
3020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
3030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	status_snapshot = 1;
3040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
3050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint __schedule_exit(int next)
3080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
3090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static unsigned long waittime;
3100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct itimerval it;
3110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (waittime)
3130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return next;
3140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nreceived) {
3160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		waittime = 2 * tmax;
3170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (waittime < 1000*interval)
3180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			waittime = 1000*interval;
3190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else
3200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		waittime = lingertime*1000;
3210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (next < 0 || next < waittime/1000)
3230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		next = waittime/1000;
3240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	it.it_interval.tv_sec = 0;
3260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	it.it_interval.tv_usec = 0;
3270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	it.it_value.tv_sec = waittime/1000000;
3280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	it.it_value.tv_usec = waittime%1000000;
3290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	setitimer(ITIMER_REAL, &it, NULL);
3300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return next;
3310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
3320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic inline void update_interval(void)
3340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
3350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int est = rtt ? rtt/8 : interval*1000;
3360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	interval = (est+rtt_addend+500)/1000;
3380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (uid && interval < MINUSERINTERVAL)
3390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		interval = MINUSERINTERVAL;
3400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
3410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
3430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * pinger --
3440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
3450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * will be added on by the kernel.  The ID field is our UNIX process ID,
3460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * and the sequence number is an ascending integer.  The first 8 bytes
3470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * of the data portion are used to hold a UNIX "timeval" struct in VAX
3480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * byte-order, to compute the round-trip time.
3490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
3500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint pinger(void)
3510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
3520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static int oom_count;
3530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static int tokens;
3540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int i;
3550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Have we already sent enough? If we have, return an arbitrary positive value. */
3570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (exiting || (npackets && ntransmitted >= npackets && !deadline))
3580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return 1000;
3590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Check that packets < rate*time + preload */
3610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (cur_time.tv_sec == 0) {
3620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		gettimeofday(&cur_time, NULL);
3630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tokens = interval*(preload-1);
3640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else {
3650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		long ntokens;
3660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct timeval tv;
3670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		gettimeofday(&tv, NULL);
3690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
3700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			(tv.tv_usec-cur_time.tv_usec)/1000;
3710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!interval) {
3720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* Case of unlimited flood is special;
3730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * if we see no reply, they are limited to 100pps */
3740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (ntokens < MININTERVAL && in_flight() >= preload)
3750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				return MININTERVAL-ntokens;
3760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
3770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		ntokens += tokens;
3780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ntokens > interval*preload)
3790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			ntokens = interval*preload;
3800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ntokens < interval)
3810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return interval - ntokens;
3820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cur_time = tv;
3840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tokens = ntokens - interval;
3850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
3860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectresend:
3880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	i = send_probe();
3890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
3900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (i == 0) {
3910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		oom_count = 0;
3920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		advance_ntransmitted();
3930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!(options & F_QUIET) && (options & F_FLOOD)) {
3940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* Very silly, but without this output with
3950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * high preload or pipe size is very confusing. */
3960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if ((preload < screen_width && pipesize < screen_width) ||
3970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			    in_flight() < screen_width)
3980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				write(STDOUT_FILENO, ".", 1);
3990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
4000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return interval - tokens;
4010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* And handle various errors... */
4040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (i > 0) {
4050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Apparently, it is some fatal bug. */
4060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		abort();
4070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else if (errno == ENOBUFS || errno == ENOMEM) {
4080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int nores_interval;
4090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Device queue overflow or OOM. Packet is not sent. */
4110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tokens = 0;
4120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Slowdown. This works only in adaptive mode (option -A) */
4130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
4140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options&F_ADAPTIVE)
4150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			update_interval();
4160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		nores_interval = SCHINT(interval/2);
4170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (nores_interval > 500)
4180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			nores_interval = 500;
4190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		oom_count++;
4200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (oom_count*nores_interval < lingertime)
4210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return nores_interval;
4220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		i = 0;
4230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Fall to hard error. It is to avoid complete deadlock
4240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * on stuck output device even when dealine was not requested.
4250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * Expected timings are screwed up in any case, but we will
4260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * exit some day. :-) */
4270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else if (errno == EAGAIN) {
4280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Socket buffer is full. */
4290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tokens += interval;
4300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return MININTERVAL;
4310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else {
4320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if ((i=receive_error_msg()) > 0) {
4330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* An ICMP error arrived. */
4340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			tokens += interval;
4350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return MININTERVAL;
4360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
4370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Compatibility with old linuces. */
4380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (i == 0 && confirm_flag && errno == EINVAL) {
4390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			confirm_flag = 0;
4400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			errno = 0;
4410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
4420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!errno)
4430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			goto resend;
4440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Hard local error. Pretend we sent packet. */
4470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	advance_ntransmitted();
4480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (i == 0 && !(options & F_QUIET)) {
4500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_FLOOD)
4510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			write(STDOUT_FILENO, "E", 1);
4520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		else
4530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("ping: sendmsg");
4540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tokens = 0;
4560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return SCHINT(interval);
4570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
4580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
4600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid sock_setbufs(int icmp_sock, int alloc)
4620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
4630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int rcvbuf, hold;
4640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int tmplen = sizeof(hold);
4650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!sndbuf)
4670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sndbuf = alloc;
4680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
4690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	rcvbuf = hold = alloc * preload;
4710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (hold < 65536)
4720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		hold = 65536;
4730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
4740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
4750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (hold < rcvbuf)
4760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
4770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
4790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Protocol independent setup and parameter checks. */
4810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid setup(int icmp_sock)
4830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
4840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int hold;
4850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct timeval tv;
4860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if ((options & F_FLOOD) && !(options & F_INTERVAL))
4880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		interval = 0;
4890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (uid && interval < MINUSERINTERVAL) {
4910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL);
4920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(2);
4930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
4950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (interval >= INT_MAX/preload) {
4960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, "ping: illegal preload and/or interval\n");
4970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(2);
4980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
4990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hold = 1;
5010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_SO_DEBUG)
5020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
5030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_SO_DONTROUTE)
5040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
5050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#ifdef SO_TIMESTAMP
5070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!(options&F_LATENCY)) {
5080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int on = 1;
5090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
5100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
5110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
5120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif
5130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Set some SNDTIMEO to prevent blocking forever
5150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 * on sends, when device is too slow or stalls. Just put limit
5160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 * of one second, or "interval", if it is less.
5170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 */
5180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tv.tv_sec = 1;
5190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tv.tv_usec = 0;
5200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (interval < 1000) {
5210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tv.tv_sec = 0;
5220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tv.tv_usec = 1000 * SCHINT(interval);
5230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
5240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
5250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Set RCVTIMEO to "interval". Note, it is just an optimization
5270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 * allowing to avoid redundant poll(). */
5280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tv.tv_sec = SCHINT(interval)/1000;
5290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tv.tv_usec = 1000*(SCHINT(interval)%1000);
5300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
5310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		options |= F_FLOOD_POLL;
5320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!(options & F_PINGFILLED)) {
5340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int i;
5350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		char *p = outpack+8;
5360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Do not forget about case of small datalen,
5380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * fill timestamp area too!
5390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 */
5400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (i = 0; i < datalen; ++i)
5410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			*p++ = i;
5420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
5430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	ident = getpid() & 0xFFFF;
5450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	set_signal(SIGINT, sigexit);
5470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	set_signal(SIGALRM, sigexit);
5480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	set_signal(SIGQUIT, sigstatus);
5490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	gettimeofday(&start_time, NULL);
5510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (deadline) {
5530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct itimerval it;
5540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		it.it_interval.tv_sec = 0;
5560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		it.it_interval.tv_usec = 0;
5570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		it.it_value.tv_sec = deadline;
5580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		it.it_value.tv_usec = 0;
5590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		setitimer(ITIMER_REAL, &it, NULL);
5600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
5610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#if 0
5630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (isatty(STDOUT_FILENO)) {
5640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct winsize w;
5650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
5670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (w.ws_col > 0)
5680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				screen_width = w.ws_col;
5690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
5700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
5710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif
5720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
5730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid main_loop(int icmp_sock, __u8 *packet, int packlen)
5750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
5760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char addrbuf[128];
5770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char ans_data[4096];
5780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct iovec iov;
5790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct msghdr msg;
5800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct cmsghdr *c;
5810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int cc;
5820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int next;
5830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int polling;
5840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	iov.iov_base = (char *)packet;
5860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	for (;;) {
5880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Check exit conditions. */
5890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (exiting)
5900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
5910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (npackets && nreceived + nerrors >= npackets)
5920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
5930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (deadline && nerrors)
5940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
5950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Check for and do special actions. */
5960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (status_snapshot)
5970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			status();
5980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
5990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Send probes scheduled to this time. */
6000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		do {
6010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			next = pinger();
6020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			next = schedule_exit(next);
6030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} while (next <= 0);
6040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* "next" is time to send next probe, if positive.
6060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * If next<=0 send now or as soon as possible. */
6070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Technical part. Looks wicked. Could be dropped,
6090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * if everyone used the newest kernel. :-)
6100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * Its purpose is:
6110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * 1. Provide intervals less than resolution of scheduler.
6120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 *    Solution: spinning.
6130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * 2. Avoid use of poll(), when recvmsg() can provide
6140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 *    timed waiting (SO_RCVTIMEO). */
6150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		polling = 0;
6160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
6170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			int recv_expected = in_flight();
6180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* If we are here, recvmsg() is unable to wait for
6200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * required timeout. */
6210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (1000*next <= 1000000/(int)HZ) {
6220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				/* Very short timeout... So, if we wait for
6230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				 * something, we sleep for MININTERVAL.
6240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				 * Otherwise, spin! */
6250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (recv_expected) {
6260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					next = MININTERVAL;
6270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				} else {
6280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					next = 0;
6290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					/* When spinning, no reasons to poll.
6300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					 * Use nonblocking recvmsg() instead. */
6310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					polling = MSG_DONTWAIT;
6320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					/* But yield yet. */
6330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					sched_yield();
6340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
6350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
6360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (!polling &&
6380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
6390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				struct pollfd pset;
6400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pset.fd = icmp_sock;
6410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pset.events = POLLIN|POLLERR;
6420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pset.revents = 0;
6430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (poll(&pset, 1, next) < 1 ||
6440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				    !(pset.revents&(POLLIN|POLLERR)))
6450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					continue;
6460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				polling = MSG_DONTWAIT;
6470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
6480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
6490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (;;) {
6510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			struct timeval *recv_timep = NULL;
6520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			struct timeval recv_time;
6530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			int not_ours = 0; /* Raw socket can receive messages
6540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					   * destined to other running pings. */
6550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			iov.iov_len = packlen;
6570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_name = addrbuf;
6580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_namelen = sizeof(addrbuf);
6590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_iov = &iov;
6600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_iovlen = 1;
6610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_control = ans_data;
6620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			msg.msg_controllen = sizeof(ans_data);
6630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			cc = recvmsg(icmp_sock, &msg, polling);
6650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			polling = MSG_DONTWAIT;
6660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (cc < 0) {
6680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (errno == EAGAIN || errno == EINTR)
6690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					break;
6700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (!receive_error_msg()) {
6710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (errno) {
6720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						perror("ping: recvmsg");
6730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						break;
6740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					}
6750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					not_ours = 1;
6760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
6770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			} else {
6780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#ifdef SO_TIMESTAMP
6800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
6810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (c->cmsg_level != SOL_SOCKET ||
6820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					    c->cmsg_type != SO_TIMESTAMP)
6830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						continue;
6840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
6850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						continue;
6860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					recv_timep = (struct timeval*)CMSG_DATA(c);
6870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
6880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif
6890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if ((options&F_LATENCY) || recv_timep == NULL) {
6910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if ((options&F_LATENCY) ||
6920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
6930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						gettimeofday(&recv_time, NULL);
6940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					recv_timep = &recv_time;
6950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
6960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
6970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
6980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
6990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* See? ... someone runs another ping on this host. */
7010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (not_ours)
7020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				install_filter();
7030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* If nothing is in flight, "break" returns us to pinger. */
7050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (in_flight() == 0)
7060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				break;
7070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* Otherwise, try to recvmsg() again. recvmsg()
7090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * is nonblocking after the first iteration, so that
7100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * if nothing is queued, it will receive EAGAIN
7110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 * and return to pinger. */
7120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
7130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
7140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	finish();
7150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
7160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint gather_statistics(__u8 *ptr, int cc, __u16 seq, int hops,
7180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		      int csfailed, struct timeval *tv, char *from)
7190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
7200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int dupflag = 0;
7210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	long triptime = 0;
7220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	++nreceived;
7240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!csfailed)
7250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		acknowledge(seq);
7260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (timing && cc >= 8+sizeof(struct timeval)) {
7280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct timeval tmp_tv;
7290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
7300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectrestamp:
7320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tvsub(tv, &tmp_tv);
7330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		triptime = tv->tv_sec * 1000000 + tv->tv_usec;
7340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (triptime < 0) {
7350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
7360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			triptime = 0;
7370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (!(options & F_LATENCY)) {
7380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				gettimeofday(tv, NULL);
7390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				options |= F_LATENCY;
7400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				goto restamp;
7410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
7420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
7430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!csfailed) {
7440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			tsum += triptime;
7450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			tsum2 += (long long)triptime * (long long)triptime;
7460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (triptime < tmin)
7470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				tmin = triptime;
7480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (triptime > tmax)
7490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				tmax = triptime;
7500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (!rtt)
7510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				rtt = triptime*8;
7520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else
7530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				rtt += triptime-rtt/8;
7540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (options&F_ADAPTIVE)
7550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				update_interval();
7560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
7570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
7580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (csfailed) {
7600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		++nchecksum;
7610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		--nreceived;
7620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else if (TST(seq % mx_dup_ck)) {
7630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		++nrepeats;
7640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		--nreceived;
7650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		dupflag = 1;
7660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else {
7670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		SET(seq % mx_dup_ck);
7680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		dupflag = 0;
7690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
7700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	confirm = confirm_flag;
7710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_QUIET)
7730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return 1;
7740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_FLOOD) {
7760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!csfailed)
7770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			write(STDOUT_FILENO, "\b \b", 3);
7780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		else
7790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			write(STDOUT_FILENO, "\bC", 1);
7800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else {
7810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int i;
7820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		__u8 *cp, *dp;
7830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("%d bytes from %s: icmp_seq=%u", cc, from, seq);
7840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (hops >= 0)
7860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf(" ttl=%d", hops);
7870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
7880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (cc < datalen+8) {
7890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf(" (truncated)\n");
7900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 1;
7910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
7920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (timing) {
7930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (triptime >= 100000)
7940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf(" time=%ld ms", triptime/1000);
7950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (triptime >= 10000)
7960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf(" time=%ld.%01ld ms", triptime/1000,
7970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       (triptime%1000)/100);
7980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (triptime >= 1000)
7990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf(" time=%ld.%02ld ms", triptime/1000,
8000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       (triptime%1000)/10);
8010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else
8020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf(" time=%ld.%03ld ms", triptime/1000,
8030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       triptime%1000);
8040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
8050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (dupflag)
8060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf(" (DUP!)");
8070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (csfailed)
8080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf(" (BAD CHECKSUM!)");
8090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* check the data */
8110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cp = ((u_char*)ptr) + sizeof(struct timeval);
8120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		dp = &outpack[8 + sizeof(struct timeval)];
8130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
8140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (*cp != *dp) {
8150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
8160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       i, *dp, *cp);
8170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				cp = (u_char*)ptr + sizeof(struct timeval);
8180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
8190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if ((i % 32) == sizeof(struct timeval))
8200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\n#%d\t", i);
8210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					printf("%x ", *cp);
8220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
8230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				break;
8240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
8250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
8260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
8270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return 0;
8280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
8290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic long llsqrt(long long a)
8310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
8320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	long long prev = ~((long long)1 << 63);
8330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	long long x = a;
8340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (x > 0) {
8360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		while (x < prev) {
8370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			prev = x;
8380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			x = (x+(a/x))/2;
8390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
8400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
8410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return (long)x;
8430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
8440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
8460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * finish --
8470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Print out statistics, and give up.
8480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
8490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid finish(void)
8500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
8510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct timeval tv = cur_time;
8520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	tvsub(&tv, &start_time);
8540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	putchar('\n');
8560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	fflush(stdout);
8570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("--- %s ping statistics ---\n", hostname);
8580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("%ld packets transmitted, ", ntransmitted);
8590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("%ld received", nreceived);
8600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nrepeats)
8610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", +%ld duplicates", nrepeats);
8620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nchecksum)
8630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", +%ld corrupted", nchecksum);
8640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nerrors)
8650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", +%ld errors", nerrors);
8660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (ntransmitted) {
8670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", %d%% packet loss",
8680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       (int) ((((long long)(ntransmitted - nreceived)) * 100) /
8690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      ntransmitted));
8700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000);
8710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
8720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	putchar('\n');
8730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nreceived && timing) {
8750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		long tmdev;
8760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tsum /= nreceived + nrepeats;
8780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tsum2 /= nreceived + nrepeats;
8790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tmdev = llsqrt(tsum2 - tsum * tsum);
8800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
8820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tmin/1000, tmin%1000,
8830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       (unsigned long)(tsum/1000), (long)(tsum%1000),
8840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tmax/1000, tmax%1000,
8850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tmdev/1000, tmdev%1000
8860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       );
8870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
8880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (pipesize > 1)
8890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", pipe %d", pipesize);
8900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) {
8910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
8920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf(", ipg/ewma %d.%03d/%d.%03d ms",
8930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
8940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
8950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	putchar('\n');
8960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	exit(!nreceived || (deadline && nreceived < npackets));
8970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
8980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
8990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid status(void)
9010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
9020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int loss = 0;
9030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	long tavg = 0;
9040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	status_snapshot = 0;
9060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (ntransmitted)
9080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
9090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss);
9110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nreceived && timing) {
9130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tavg = tsum / (nreceived + nrepeats);
9140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
9160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tmin/1000, tmin%1000,
9170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tavg/1000, tavg%1000,
9180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       rtt/8000, (rtt/8)%1000,
9190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       tmax/1000, tmax%1000
9200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		       );
9210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
9220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	fprintf(stderr, "\n");
9230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
9240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* PING COMMON */
9260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#define	MAXIPLEN	60
9280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#define	MAXICMPLEN	76
9290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#define	NROUTES		9		/* number of record route slots */
9300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#define TOS_MAX		255		/* 8-bit TOS field */
9310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic int ts_type;
9340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic int nroute = 0;
9350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic __u32 route[10];
9360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstruct sockaddr_in whereto;	/* who to ping */
9400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint optlen = 0;
9410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint settos = 0;			/* Set TOS, Precendence or other QOS options */
9420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint icmp_sock;			/* socket file descriptor */
9430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectu_char outpack[0x10000];
9440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint maxpacket = sizeof(outpack);
9450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic int broadcast_pings = 0;
9470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic char *pr_addr(__u32);
9490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void pr_options(unsigned char * cp, int hlen);
9500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void pr_iph(struct iphdr *ip);
9510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void usage(void) __attribute__((noreturn));
9520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic u_short in_cksum(const u_short *addr, int len, u_short salt);
9530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp);
9540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic int parsetos(char *str);
9550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstatic struct {
9570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct cmsghdr cm;
9580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct in_pktinfo ipi;
9590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project} cmsg = { {sizeof(struct cmsghdr) + sizeof(struct in_pktinfo), SOL_IP, IP_PKTINFO},
9600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	   {0, }};
9610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint cmsg_len;
9620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectstruct sockaddr_in source;
9640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar *device;
9650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint pmtudisc = -1;
9660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint receive_error_msg()
9680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
9690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int res;
9700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char cbuf[512];
9710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct iovec  iov;
9720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct msghdr msg;
9730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct cmsghdr *cmsg;
9740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct sock_extended_err *e;
9750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct icmphdr icmph;
9760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct sockaddr_in target;
9770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int net_errors = 0;
9780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int local_errors = 0;
9790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int saved_errno = errno;
9800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	iov.iov_base = &icmph;
9820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	iov.iov_len = sizeof(icmph);
9830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_name = (void*)&target;
9840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_namelen = sizeof(target);
9850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_iov = &iov;
9860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_iovlen = 1;
9870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_flags = 0;
9880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_control = cbuf;
9890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	msg.msg_controllen = sizeof(cbuf);
9900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	res = recvmsg(icmp_sock, &msg, MSG_ERRQUEUE|MSG_DONTWAIT);
9920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (res < 0)
9930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		goto out;
9940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
9950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	e = NULL;
9960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
9970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (cmsg->cmsg_level == SOL_IP) {
9980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (cmsg->cmsg_type == IP_RECVERR)
9990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				e = (struct sock_extended_err *)CMSG_DATA(cmsg);
10000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
10010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
10020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (e == NULL)
10030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		abort();
10040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (e->ee_origin == SO_EE_ORIGIN_LOCAL) {
10060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		local_errors++;
10070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_QUIET)
10080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			goto out;
10090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_FLOOD)
10100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			write(STDOUT_FILENO, "E", 1);
10110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		else if (e->ee_errno != EMSGSIZE)
10120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: local error: %s\n", strerror(e->ee_errno));
10130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		else
10140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: local error: Message too long, mtu=%u\n", e->ee_info);
10150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		nerrors++;
10160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
10170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);
10180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (res < sizeof(icmph) ||
10200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		    target.sin_addr.s_addr != whereto.sin_addr.s_addr ||
10210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		    icmph.type != ICMP_ECHO ||
10220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		    icmph.un.echo.id != ident) {
10230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* Not our error, not an error at all. Clear. */
10240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			saved_errno = 0;
10250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			goto out;
10260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
10270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		acknowledge(ntohs(icmph.un.echo.sequence));
10290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!working_recverr) {
10310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			struct icmp_filter filt;
10320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			working_recverr = 1;
10330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* OK, it works. Add stronger filter. */
10340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
10350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				      (1<<ICMP_REDIRECT)|
10360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				      (1<<ICMP_ECHOREPLY));
10370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1)
10380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				perror("\rWARNING: setsockopt(ICMP_FILTER)");
10390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
10400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		net_errors++;
10420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		nerrors++;
10430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_QUIET)
10440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			goto out;
10450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_FLOOD) {
10460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			write(STDOUT_FILENO, "\bE", 2);
10470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else {
10480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("From %s icmp_seq=%u ", pr_addr(sin->sin_addr.s_addr), ntohs(icmph.un.echo.sequence));
10490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_icmph(e->ee_type, e->ee_code, e->ee_info, NULL);
10500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fflush(stdout);
10510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
10520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
10530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectout:
10550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	errno = saved_errno;
10560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return net_errors ? : -local_errors;
10570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
10580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
10600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * pinger --
10610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * 	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
10620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * will be added on by the kernel.  The ID field is our UNIX process ID,
10630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * and the sequence number is an ascending integer.  The first 8 bytes
10640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * of the data portion are used to hold a UNIX "timeval" struct in VAX
10650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * byte-order, to compute the round-trip time.
10660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
10670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint send_probe()
10680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
10690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct icmphdr *icp;
10700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int cc;
10710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int i;
10720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp = (struct icmphdr *)outpack;
10740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->type = ICMP_ECHO;
10750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->code = 0;
10760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->checksum = 0;
10770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->un.echo.sequence = htons(ntransmitted+1);
10780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->un.echo.id = ident;			/* ID */
10790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	CLR((ntransmitted+1) % mx_dup_ck);
10810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (timing) {
10830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options&F_LATENCY) {
10840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			static volatile int fake_fucked_egcs = sizeof(struct timeval);
10850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			struct timeval tmp_tv;
10860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			gettimeofday(&tmp_tv, NULL);
10870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* egcs is crap or glibc is crap, but memcpy
10880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			   does not copy anything, if len is constant! */
10890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			memcpy(icp+1, &tmp_tv, fake_fucked_egcs);
10900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else {
10910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			memset(icp+1, 0, sizeof(struct timeval));
10920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
10930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
10940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	cc = datalen + 8;			/* skips ICMP portion */
10960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
10970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* compute ICMP checksum here */
10980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp->checksum = in_cksum((u_short *)icp, cc, 0);
10990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (timing && !(options&F_LATENCY)) {
11010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		static volatile int fake_fucked_egcs = sizeof(struct timeval);
11020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        struct timeval tmp_tv;
11030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		gettimeofday(&tmp_tv, NULL);
11040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* egcs is crap or glibc is crap, but memcpy
11050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		   does not copy anything, if len is constant! */
11060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		memcpy(icp+1, &tmp_tv, fake_fucked_egcs);
11070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		icp->checksum = in_cksum((u_short *)(icp+1), fake_fucked_egcs, ~icp->checksum);
11080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
11090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        do {
11110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		static struct iovec iov = {outpack, 0};
11120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		static struct msghdr m = { &whereto, sizeof(whereto),
11130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						   &iov, 1, &cmsg, 0, 0 };
11140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		m.msg_controllen = cmsg_len;
11150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		iov.iov_len = cc;
11160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		i = sendmsg(icmp_sock, &m, confirm);
11180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		confirm = 0;
11190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} while (0);
11200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return (cc == i ? 0 : i);
11220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
11230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
11250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * parse_reply --
11260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Print out the packet, if it came from us.  This logic is necessary
11270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
11280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * which arrive ('tis only fair).  This permits multiple copies of this
11290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * program to be run without having intermingled output (or statistics!).
11300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
11310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint
11320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectparse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv)
11330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
11340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct sockaddr_in *from = addr;
11350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	__u8 *buf = msg->msg_iov->iov_base;
11360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct icmphdr *icp;
11370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct iphdr *ip;
11380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int hlen;
11390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int csfailed;
11400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Check the IP header */
11420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	ip = (struct iphdr *)buf;
11430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hlen = ip->ihl*4;
11440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (cc < hlen + 8 || ip->ihl < 5) {
11450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_VERBOSE)
11460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: packet too short (%d bytes) from %s\n", cc,
11470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pr_addr(from->sin_addr.s_addr));
11480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return 1;
11490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
11500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Now the ICMP part */
11520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	cc -= hlen;
11530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icp = (struct icmphdr *)(buf + hlen);
11540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	csfailed = in_cksum((u_short *)icp, cc, 0);
11550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (icp->type == ICMP_ECHOREPLY) {
11570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp->un.echo.id != ident)
11580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 1;			/* 'Twas not our ECHO */
11590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (gather_statistics((__u8*)(icp+1), cc,
11600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				      ntohs(icp->un.echo.sequence),
11610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				      ip->ttl, 0, tv, pr_addr(from->sin_addr.s_addr)))
11620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 0;
11630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} else {
11640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* We fall here when a redirect or source quench arrived.
11650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * Also this branch processes icmp errors, when IP_RECVERR
11660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		 * is broken. */
11670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
11680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        switch (icp->type) {
11690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_ECHO:
11700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* MUST NOT */
11710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 1;
11720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_SOURCE_QUENCH:
11730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_REDIRECT:
11740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_DEST_UNREACH:
11750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_TIME_EXCEEDED:
11760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_PARAMETERPROB:
11770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			{
11780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				struct iphdr * iph = (struct  iphdr *)(&icp[1]);
11790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				struct icmphdr *icp1 = (struct icmphdr*)((unsigned char *)iph + iph->ihl*4);
11800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				int error_pkt;
11810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (cc < 8+sizeof(struct iphdr)+8 ||
11820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				    cc < 8+iph->ihl*4+8)
11830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					return 1;
11840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (icp1->type != ICMP_ECHO ||
11850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				    iph->daddr != whereto.sin_addr.s_addr ||
11860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				    icp1->un.echo.id != ident)
11870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					return 1;
11880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				error_pkt = (icp->type != ICMP_REDIRECT &&
11890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					     icp->type != ICMP_SOURCE_QUENCH);
11900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (error_pkt) {
11910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					acknowledge(ntohs(icp1->un.echo.sequence));
11920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (working_recverr) {
11930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						return 0;
11940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					} else {
11950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						static int once;
11960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						/* Sigh, IP_RECVERR for raw socket
11970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						 * was broken until 2.4.9. So, we ignore
11980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						 * the first error and warn on the second.
11990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						 */
12000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						if (once++ == 1)
12010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project							fprintf(stderr, "\rWARNING: kernel is not very fresh, upgrade is recommended.\n");
12020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						if (once == 1)
12030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project							return 0;
12040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					}
12050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
12060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				nerrors+=error_pkt;
12070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (options&F_QUIET)
12080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					return !error_pkt;
12090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (options & F_FLOOD) {
12100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (error_pkt)
12110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						write(STDOUT_FILENO, "\bE", 2);
12120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					return !error_pkt;
12130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
12140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf("From %s: icmp_seq=%u ",
12150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       pr_addr(from->sin_addr.s_addr),
12160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				       ntohs(icp1->un.echo.sequence));
12170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (csfailed)
12180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					printf("(BAD CHECKSUM)");
12190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
12200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				return !error_pkt;
12210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
12220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        default:
12230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			/* MUST NOT */
12240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
12250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
12260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if ((options & F_FLOOD) && !(options & (F_VERBOSE|F_QUIET))) {
12270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (!csfailed)
12280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				write(STDOUT_FILENO, "!E", 2);
12290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else
12300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				write(STDOUT_FILENO, "!EC", 3);
12310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 0;
12320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
12330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (!(options & F_VERBOSE) || uid)
12340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 0;
12350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("From %s: ", pr_addr(from->sin_addr.s_addr));
12360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (csfailed) {
12370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("(BAD CHECKSUM)\n");
12380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			return 0;
12390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
12400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		pr_icmph(icp->type, icp->code, ntohl(icp->un.gateway), icp);
12410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return 0;
12420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
12430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!(options & F_FLOOD)) {
12450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		pr_options(buf + sizeof(struct iphdr), hlen);
12460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_AUDIBLE)
12480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			putchar('\a');
12490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		putchar('\n');
12500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fflush(stdout);
12510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
12520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return 0;
12530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
12540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectu_short
12560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectin_cksum(const u_short *addr, register int len, u_short csum)
12570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
12580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	register int nleft = len;
12590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	const u_short *w = addr;
12600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	register u_short answer;
12610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	register int sum = csum;
12620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/*
12640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
12650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 *  we add sequential 16 bit words to it, and at the end, fold
12660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 *  back all the carry bits from the top 16 bits into the lower
12670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 *  16 bits.
12680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 */
12690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	while (nleft > 1)  {
12700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sum += *w++;
12710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		nleft -= 2;
12720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
12730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* mop up an odd byte, if necessary */
12750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (nleft == 1)
12760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sum += htons(*(u_char *)w << 8);
12770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/*
12790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 * add back carry outs from top 16 bits to low 16 bits
12800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 */
12810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
12820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	sum += (sum >> 16);			/* add carry */
12830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	answer = ~sum;				/* truncate to 16 bits */
12840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return (answer);
12850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
12860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
12870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
12880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * pr_icmph --
12890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Print a descriptive string about an ICMP header.
12900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
12910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp)
12920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
12930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	switch(type) {
12940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_ECHOREPLY:
12950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Echo Reply\n");
12960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq + Data */
12970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
12980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_DEST_UNREACH:
12990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		switch(code) {
13000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_NET_UNREACH:
13010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Destination Net Unreachable\n");
13020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_HOST_UNREACH:
13040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Destination Host Unreachable\n");
13050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_PROT_UNREACH:
13070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Destination Protocol Unreachable\n");
13080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_PORT_UNREACH:
13100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Destination Port Unreachable\n");
13110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_FRAG_NEEDED:
13130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Frag needed and DF set (mtu = %u)\n", info);
13140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_SR_FAILED:
13160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Source Route Failed\n");
13170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_PKT_FILTERED:
13190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Packet filtered\n");
13200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		default:
13220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Dest Unreachable, Bad Code: %d\n", code);
13230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
13250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp && (options & F_VERBOSE))
13260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_iph((struct iphdr*)(icp + 1));
13270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_SOURCE_QUENCH:
13290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Source Quench\n");
13300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp && (options & F_VERBOSE))
13310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_iph((struct iphdr*)(icp + 1));
13320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_REDIRECT:
13340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		switch(code) {
13350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_REDIR_NET:
13360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Redirect Network");
13370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_REDIR_HOST:
13390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Redirect Host");
13400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_REDIR_NETTOS:
13420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Redirect Type of Service and Network");
13430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_REDIR_HOSTTOS:
13450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Redirect Type of Service and Host");
13460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		default:
13480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Redirect, Bad Code: %d", code);
13490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
13510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp)
13520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("(New nexthop: %s)\n", pr_addr(icp->un.gateway));
13530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp && (options & F_VERBOSE))
13540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_iph((struct iphdr*)(icp + 1));
13550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_ECHO:
13570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Echo Request\n");
13580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq + Data */
13590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_TIME_EXCEEDED:
13610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		switch(code) {
13620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_EXC_TTL:
13630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Time to live exceeded\n");
13640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case ICMP_EXC_FRAGTIME:
13660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Frag reassembly time exceeded\n");
13670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		default:
13690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("Time exceeded, Bad Code: %d\n", code);
13700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
13710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
13720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp && (options & F_VERBOSE))
13730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_iph((struct iphdr*)(icp + 1));
13740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_PARAMETERPROB:
13760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Parameter problem: pointer = %u\n", icp ? (ntohl(icp->un.gateway)>>24) : info);
13770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (icp && (options & F_VERBOSE))
13780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pr_iph((struct iphdr*)(icp + 1));
13790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_TIMESTAMP:
13810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Timestamp\n");
13820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq + 3 timestamps */
13830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_TIMESTAMPREPLY:
13850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Timestamp Reply\n");
13860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq + 3 timestamps */
13870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_INFO_REQUEST:
13890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Information Request\n");
13900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq */
13910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_INFO_REPLY:
13930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Information Reply\n");
13940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* XXX ID + Seq */
13950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
13960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#ifdef ICMP_MASKREQ
13970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_MASKREQ:
13980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Address Mask Request\n");
13990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
14000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif
14010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#ifdef ICMP_MASKREPLY
14020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	case ICMP_MASKREPLY:
14030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Address Mask Reply\n");
14040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		break;
14050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#endif
14060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	default:
14070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("Bad ICMP type: %d\n", type);
14080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
14090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
14100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
14110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid pr_options(unsigned char * cp, int hlen)
14120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
14130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int i, j;
14140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int optlen, totlen;
14150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	unsigned char * optptr;
14160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static int old_rrlen;
14170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static char old_rr[MAX_IPOPTLEN];
14180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
14190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	totlen = hlen-sizeof(struct iphdr);
14200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	optptr = cp;
14210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
14220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	while (totlen > 0) {
14230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (*optptr == IPOPT_EOL)
14240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
14250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (*optptr == IPOPT_NOP) {
14260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			totlen--;
14270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			optptr++;
14280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("\nNOP");
14290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			continue;
14300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
14310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cp = optptr;
14320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		optlen = optptr[1];
14330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (optlen < 2 || optlen > totlen)
14340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
14350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
14360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		switch (*cp) {
14370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case IPOPT_SSRR:
14380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case IPOPT_LSRR:
14390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("\n%cSRR: ", *cp==IPOPT_SSRR ? 'S' : 'L');
14400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			j = *++cp;
14410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i = *++cp;
14420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i -= 4;
14430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			cp++;
14440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (j > IPOPT_MINOFF) {
14450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				for (;;) {
14460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					__u32 address;
14470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					memcpy(&address, cp, 4);
14480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					cp += 4;
14490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (address == 0)
14500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t0.0.0.0");
14510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					else
14520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%s", pr_addr(address));
14530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					j -= 4;
14540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					putchar('\n');
14550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (j <= IPOPT_MINOFF)
14560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						break;
14570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
14580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
14590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
14600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case IPOPT_RR:
14610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			j = *++cp;		/* get length */
14620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i = *++cp;		/* and pointer */
14630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (i > j)
14640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				i = j;
14650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i -= IPOPT_MINOFF;
14660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (i <= 0)
14670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				continue;
14680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (i == old_rrlen
14690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			    && !memcmp((char *)cp, old_rr, i)
14700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			    && !(options & F_FLOOD)) {
14710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf("\t(same route)");
14720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				i = ((i + 3) / 4) * 4;
14730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				cp += i;
14740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				break;
14750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
14760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			old_rrlen = i;
14770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			memcpy((char *)cp, old_rr, i);
14780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("\nRR: ");
14790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			cp++;
14800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			for (;;) {
14810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				__u32 address;
14820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				memcpy(&address, cp, 4);
14830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				cp += 4;
14840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (address == 0)
14850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					printf("\t0.0.0.0");
14860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				else
14870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					printf("\t%s", pr_addr(address));
14880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				i -= 4;
14890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				putchar('\n');
14900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (i <= 0)
14910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					break;
14920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
14930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
14940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case IPOPT_TS:
14950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		{
14960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			int stdtime = 0, nonstdtime = 0;
14970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			__u8 flags;
14980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			j = *++cp;		/* get length */
14990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i = *++cp;		/* and pointer */
15000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (i > j)
15010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				i = j;
15020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			i -= 5;
15030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (i <= 0)
15040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				continue;
15050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			flags = *++cp;
15060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("\nTS: ");
15070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			cp++;
15080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			for (;;) {
15090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				long l;
15100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if ((flags&0xF) != IPOPT_TS_TSONLY) {
15120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					__u32 address;
15130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					memcpy(&address, cp, 4);
15140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					cp += 4;
15150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (address == 0)
15160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t0.0.0.0");
15170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					else
15180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%s", pr_addr(address));
15190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					i -= 4;
15200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (i <= 0)
15210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						break;
15220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
15230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				l = *cp++;
15240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				l = (l<<8) + *cp++;
15250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				l = (l<<8) + *cp++;
15260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				l = (l<<8) + *cp++;
15270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if  (l & 0x80000000) {
15290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (nonstdtime==0)
15300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%ld absolute not-standard", l&0x7fffffff);
15310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					else
15320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%ld not-standard", (l&0x7fffffff) - nonstdtime);
15330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					nonstdtime = l&0x7fffffff;
15340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				} else {
15350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (stdtime==0)
15360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%ld absolute", l);
15370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					else
15380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						printf("\t%ld", l - stdtime);
15390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					stdtime = l;
15400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
15410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				i -= 4;
15420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				putchar('\n');
15430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (i <= 0)
15440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					break;
15450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
15460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (flags>>4)
15470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				printf("Unrecorded hops: %d\n", flags>>4);
15480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
15490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
15500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		default:
15510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("\nunknown option %x", *cp);
15520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
15530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
15540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		totlen -= optlen;
15550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		optptr += optlen;
15560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
15570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
15580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
15610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * pr_iph --
15620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Print an IP header with options.
15630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
15640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid pr_iph(struct iphdr *ip)
15650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
15660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int hlen;
15670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	u_char *cp;
15680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hlen = ip->ihl << 2;
15700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	cp = (u_char *)ip + 20;		/* point to options */
15710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
15730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf(" %1x  %1x  %02x %04x %04x",
15740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	       ip->version, ip->ihl, ip->tos, ip->tot_len, ip->id);
15750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("   %1x %04x", ((ip->frag_off) & 0xe000) >> 13,
15760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	       (ip->frag_off) & 0x1fff);
15770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("  %02x  %02x %04x", ip->ttl, ip->protocol, ip->check);
15780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->saddr));
15790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->daddr));
15800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("\n");
15810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	pr_options(cp, hlen);
15820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
15830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/*
15850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * pr_addr --
15860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project *	Return an ascii host address as a dotted quad and optionally with
15870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project * a hostname.
15880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project */
15890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar *
15900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectpr_addr(__u32 addr)
15910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
15920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct hostent *hp;
15930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static char buf[4096];
15940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
15950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if ((options & F_NUMERIC) ||
15960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    !(hp = gethostbyaddr((char *)&addr, 4, AF_INET)))
15970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&addr));
15980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	else
15990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name,
16000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			 inet_ntoa(*(struct in_addr *)&addr));
16010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return(buf);
16020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
16030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project/* Set Type of Service (TOS) and other Quality of Service relating bits */
16060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint parsetos(char *str)
16070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
16080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        const char *cp;
16090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        int tos;
16100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        char *ep;
16110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        /* handle both hex and decimal values */
16130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
16140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cp = str + 2;
16150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		tos = (int)strtol(cp, &ep, 16);
16160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        } else
16170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project                tos = (int)strtol(str, &ep, 10);
16180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        /* doesn't look like decimal or hex, eh? */
16200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        if (*ep != '\0') {
16210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        	fprintf(stderr, "ping: \"%s\" bad value for TOS\n", str);
16220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        	exit(2);
16230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        }
16240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        if (tos > TOS_MAX) {
16260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        	fprintf(stderr, "ping: the decimal value of TOS bits must be 0-254 (or zero)\n");
16270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        	exit(2);
16280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        }
16290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return(tos);
16300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
16310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project#include <linux/filter.h>
16330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid install_filter(void)
16350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
16360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static int once;
16370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static struct sock_filter insns[] = {
16380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* Skip IP header. F..g BSD... Look into ping6. */
16390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_LD|BPF_H|BPF_IND, 4), /* Load icmp echo ident */
16400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xAAAA, 0, 1), /* Ours? */
16410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_RET|BPF_K, ~0U), /* Yes, it passes. */
16420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_LD|BPF_B|BPF_IND, 0), /* Load icmp type */
16430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ICMP_ECHOREPLY, 1, 0), /* Echo? */
16440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_RET|BPF_K, 0xFFFFFFF), /* No. It passes. */
16450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		BPF_STMT(BPF_RET|BPF_K, 0) /* Echo with wrong ident. Reject. */
16460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	};
16470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	static struct sock_fprog filter = {
16480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		sizeof insns / sizeof(insns[0]),
16490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		insns
16500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	};
16510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (once)
16530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		return;
16540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	once = 1;
16550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Patch bpflet for current identifier. */
16570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1);
16580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
16600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		perror("WARNING: failed to install socket filter\n");
16610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
16620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid usage(void)
16650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
16660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	fprintf(stderr,
16670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project"Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]\n"
16680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project"            [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]\n"
16690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project"            [-M mtu discovery hint] [-S sndbuf]\n"
16700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project"            [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination\n");
16710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	exit(2);
16720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
16730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
16741fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevichint isInSupplementaryGroup(gid_t group) {
16751fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	long ngroups_max;
16762b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	gid_t empty[0];
16771fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	gid_t *groups;
16781fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	int ngroups;
16791fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	int i;
16801fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
16811fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	if (getuid() == 0) {
16821fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		// root is presumed to be in every group
16831fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		return 1;
16841fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	}
16851fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
16862b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	ngroups = getgroups(0, empty);
16872b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	if (ngroups < 0) {
16882b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville		perror("ping: call to getgroups for sizing failed");
16892b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville		exit(2);
16902b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	}
16912b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	groups = (gid_t *) malloc((ngroups * sizeof(gid_t)));
16921fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	if (groups == NULL) {
16932b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville		fprintf(stderr, "ping: unable to allocate memory for %d groups.  Aborting\n", ngroups);
16941fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		exit(2);
16951fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	}
16962b77a5377db63d95d777a7d5aa14380dd0e71e72Wink Saville	ngroups = getgroups(ngroups, groups);
16971fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	if (ngroups < 0) {
16981fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		perror("ping: getgroups failed");
16991fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		exit(2);
17001fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	}
17011fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
17021fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	for (i = 0; i < ngroups; i++) {
17031fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		if (group == groups[i]) {
17041fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich			free(groups);
17051fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich			return 1;
17061fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		}
17071fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	}
17081fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
17091fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	free(groups);
17101fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	return 0;
17111fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich}
17121fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
17130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint main(int argc, char *argv[])
17140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project{
17150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	struct hostent *hp;
17160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int ch, hold, packlen;
17170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	int socket_errno;
17180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	u_char *packet;
17190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char *target, hnamebuf[MAXHOSTNAMELEN];
17200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	char rspace[3 + 4 * NROUTES + 1];	/* record route space */
17210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
17220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
17230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	socket_errno = errno;
17240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
17250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* if we were setuid root, undo that */
17260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (setuid(getuid())) return -1;
17270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
17281fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	if (!isInSupplementaryGroup(AID_INET)) {
17291fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		fprintf(stderr, "You must have internet permissions to use ping.  Aborting.\n");
17301fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich		exit(2);
17311fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich	}
17321fddfb0177911d1a1f9e13904434a6f30f9cecb0Nick Kralevich
17330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	source.sin_family = AF_INET;
17340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
17350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	preload = 1;
17360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	while ((ch = getopt(argc, argv, COMMON_OPTSTR "bRT:")) != EOF) {
17370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		switch(ch) {
17380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'b':
17390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		        broadcast_pings = 1;
17400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
17410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'Q':
17420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			settos = parsetos(optarg);
17430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (settos &&
17440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			    (setsockopt(icmp_sock, IPPROTO_IP, IP_TOS,
17450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					(char *)&settos, sizeof(int)) < 0)) {
17460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				perror("ping: error setting QOS sockopts");
17470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
17480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
17490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
17500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'R':
17510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (options & F_TIMESTAMP) {
17520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "Only one of -T or -R may be used\n");
17530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
17540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
17550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			options |= F_RROUTE;
17560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
17570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'T':
17580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (options & F_RROUTE) {
17590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "Only one of -T or -R may be used\n");
17600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
17610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
17620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			options |= F_TIMESTAMP;
17630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (strcmp(optarg, "tsonly") == 0)
17640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ts_type = IPOPT_TS_TSONLY;
17650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (strcmp(optarg, "tsandaddr") == 0)
17660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ts_type = IPOPT_TS_TSANDADDR;
17670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (strcmp(optarg, "tsprespec") == 0)
17680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ts_type = IPOPT_TS_PRESPEC;
17690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else {
17700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "Invalid timestamp type\n");
17710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
17720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
17730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
17740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'I':
17750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		{
17760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			char dummy;
17770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			int i1, i2, i3, i4;
17780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
17790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (sscanf(optarg, "%u.%u.%u.%u%c",
17800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				   &i1, &i2, &i3, &i4, &dummy) == 4) {
17810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				__u8 *ptr;
17820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ptr = (__u8*)&source.sin_addr;
17830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ptr[0] = i1;
17840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ptr[1] = i2;
17850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ptr[2] = i3;
17860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				ptr[3] = i4;
17870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				options |= F_STRICTSOURCE;
17880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			} else {
17890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				device = optarg;
17900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
17910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
17920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
17930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'M':
17940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (strcmp(optarg, "do") == 0)
17950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pmtudisc = IP_PMTUDISC_DO;
17960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (strcmp(optarg, "dont") == 0)
17970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pmtudisc = IP_PMTUDISC_DONT;
17980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else if (strcmp(optarg, "want") == 0)
17990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				pmtudisc = IP_PMTUDISC_WANT;
18000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			else {
18010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "ping: wrong value for -M: do, dont, want are valid ones.\n");
18020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
18030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
18040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
18050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		case 'V':
18060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			printf("ping utility, iputils-ss\n");
18070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(0);
18080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		COMMON_OPTIONS
18090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			common_options(ch);
18100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			break;
18110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		default:
18120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			usage();
18130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
18140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
18150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	argc -= optind;
18160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	argv += optind;
18170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (argc == 0)
18190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		usage();
18200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (argc > 1) {
18210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (options & F_RROUTE)
18220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			usage();
18230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		else if (options & F_TIMESTAMP) {
18240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (ts_type != IPOPT_TS_PRESPEC)
18250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				usage();
18260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (argc > 5)
18270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				usage();
18280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else {
18290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (argc > 10)
18300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				usage();
18310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			options |= F_SOURCEROUTE;
18320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
18330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
18340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	while (argc > 0) {
18350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		target = *argv;
18360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		bzero((char *)&whereto, sizeof(whereto));
18380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		whereto.sin_family = AF_INET;
18390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (inet_aton(target, &whereto.sin_addr) == 1) {
18400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hostname = target;
18410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (argc == 1)
18420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				options |= F_NUMERIC;
18430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		} else {
18440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hp = gethostbyname(target);
18450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hp = gethostbyname(target);
18460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hp = gethostbyname(target);
18470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (!hp) {
18480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "ping: unknown host %s\n", target);
18490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
18500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
18510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			memcpy(&whereto.sin_addr, hp->h_addr, 4);
18520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
18530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hnamebuf[sizeof(hnamebuf) - 1] = 0;
18540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			hostname = hnamebuf;
18550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
18560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (argc > 1)
18570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			route[nroute++] = whereto.sin_addr.s_addr;
18580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		argc--;
18590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		argv++;
18600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
18610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (source.sin_addr.s_addr == 0) {
18630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int alen;
18640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct sockaddr_in dst = whereto;
18650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
18660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (probe_fd < 0) {
18680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("socket");
18690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
18700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
18710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (device) {
18720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			struct ifreq ifr;
18730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			memset(&ifr, 0, sizeof(ifr));
18740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
18750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) {
18760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
18770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					struct ip_mreqn imr;
18780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) {
18790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						fprintf(stderr, "ping: unknown iface %s\n", device);
18800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						exit(2);
18810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					}
18820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					memset(&imr, 0, sizeof(imr));
18830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					imr.imr_ifindex = ifr.ifr_ifindex;
18840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					if (setsockopt(probe_fd, SOL_IP, IP_MULTICAST_IF, &imr, sizeof(imr)) == -1) {
18850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						perror("ping: IP_MULTICAST_IF");
18860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project						exit(2);
18870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					}
18880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
18890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
18900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
18910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (settos &&
18930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		    setsockopt(probe_fd, IPPROTO_IP, IP_TOS, (char *)&settos, sizeof(int)) < 0)
18940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("Warning: error setting QOS sockopts");
18950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
18960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		dst.sin_port = htons(1025);
18970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (nroute)
18980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			dst.sin_addr.s_addr = route[0];
18990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
19000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (errno == EACCES) {
19010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (broadcast_pings == 0) {
19020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					fprintf(stderr, "Do you want to ping broadcast? Then -b\n");
19030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					exit(2);
19040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
19050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "WARNING: pinging broadcast address\n");
19060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (setsockopt(probe_fd, SOL_SOCKET, SO_BROADCAST,
19070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					       &broadcast_pings, sizeof(broadcast_pings)) < 0) {
19080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					perror ("can't set broadcasting");
19090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					exit(2);
19100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
19110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				if (connect(probe_fd, (struct sockaddr*)&dst, sizeof(dst)) == -1) {
19120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					perror("connect");
19130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project					exit(2);
19140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				}
19150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			} else {
19160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				perror("connect");
19170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
19180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
19190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
19200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		alen = sizeof(source);
19210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) {
19220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("getsockname");
19230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
19240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
19250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		source.sin_port = 0;
19260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		close(probe_fd);
19270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	} while (0);
19280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (whereto.sin_addr.s_addr == 0)
19300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		whereto.sin_addr.s_addr = source.sin_addr.s_addr;
19310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (icmp_sock < 0) {
19330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		errno = socket_errno;
19340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		perror("ping: icmp open socket");
19350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(2);
19360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (device) {
19390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct ifreq ifr;
19400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		memset(&ifr, 0, sizeof(ifr));
19420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
19430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ioctl(icmp_sock, SIOCGIFINDEX, &ifr) < 0) {
19440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "ping: unknown iface %s\n", device);
19450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
19460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
19470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cmsg.ipi.ipi_ifindex = ifr.ifr_ifindex;
19480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		cmsg_len = sizeof(cmsg);
19490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (broadcast_pings || IN_MULTICAST(ntohl(whereto.sin_addr.s_addr))) {
19520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (uid) {
19530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (interval < 1000) {
19540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "ping: broadcast ping with too short interval.\n");
19550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
19560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
19570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (pmtudisc >= 0 && pmtudisc != IP_PMTUDISC_DO) {
19580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				fprintf(stderr, "ping: broadcast ping does not fragment.\n");
19590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
19600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
19610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
19620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (pmtudisc < 0)
19630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			pmtudisc = IP_PMTUDISC_DO;
19640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (pmtudisc >= 0) {
19670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, SOL_IP, IP_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc)) == -1) {
19680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("ping: IP_MTU_DISCOVER");
19690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
19700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
19710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if ((options&F_STRICTSOURCE) &&
19740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	    bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) {
19750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		perror("bind");
19760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(2);
19770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (1) {
19800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		struct icmp_filter filt;
19810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		filt.data = ~((1<<ICMP_SOURCE_QUENCH)|
19820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      (1<<ICMP_DEST_UNREACH)|
19830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      (1<<ICMP_TIME_EXCEEDED)|
19840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      (1<<ICMP_PARAMETERPROB)|
19850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      (1<<ICMP_REDIRECT)|
19860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			      (1<<ICMP_ECHOREPLY));
19870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1)
19880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("WARNING: setsockopt(ICMP_FILTER)");
19890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
19900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hold = 1;
19920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (setsockopt(icmp_sock, SOL_IP, IP_RECVERR, (char *)&hold, sizeof(hold)))
19930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n");
19940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
19950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* record route option */
19960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_RROUTE) {
19970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        bzero(rspace, sizeof(rspace));
19980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[0] = IPOPT_NOP;
19990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OPTVAL] = IPOPT_RR;
20000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OLEN] = sizeof(rspace)-1;
20010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF;
20020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		optlen = 40;
20030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0) {
20040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("ping: record route");
20050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_TIMESTAMP) {
20090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        bzero(rspace, sizeof(rspace));
20100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[0] = IPOPT_TIMESTAMP;
20110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1] = (ts_type==IPOPT_TS_TSONLY ? 40 : 36);
20120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[2] = 5;
20130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[3] = ts_type;
20140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (ts_type == IPOPT_TS_PRESPEC) {
20150baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			int i;
20160baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			rspace[1] = 4+nroute*8;
20170baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			for (i=0; i<nroute; i++)
20180baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				*(__u32*)&rspace[4+i*8] = route[i];
20190baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20200baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) {
20210baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			rspace[3] = 2;
20220baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, rspace[1]) < 0) {
20230baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				perror("ping: ts option");
20240baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project				exit(2);
20250baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			}
20260baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20270baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		optlen = 40;
20280baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20290baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_SOURCEROUTE) {
20300baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        int i;
20310baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	        bzero(rspace, sizeof(rspace));
20320baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[0] = IPOPT_NOOP;
20330baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OPTVAL] = (options & F_SO_DONTROUTE) ? IPOPT_SSRR
20340baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			: IPOPT_LSRR;
20350baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OLEN] = 3 + nroute*4;
20360baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		rspace[1+IPOPT_OFFSET] = IPOPT_MINOFF;
20370baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		for (i=0; i<nroute; i++)
20380baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			*(__u32*)&rspace[4+i*4] = route[i];
20390baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20400baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_OPTIONS, rspace, 4 + nroute*4) < 0) {
20410baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror("ping: record route");
20420baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20430baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20440baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		optlen = 40;
20450baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20460baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20470baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	/* Estimate memory eaten by single packet. It is rough estimate.
20480baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	 * Actually, for small datalen's it depends on kernel side a lot. */
20490baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hold = datalen + 8;
20500baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	hold += ((hold+511)/512)*(optlen + 20 + 16 + 64 + 160);
20510baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	sock_setbufs(icmp_sock, hold);
20520baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20530baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (broadcast_pings) {
20540baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, SOL_SOCKET, SO_BROADCAST,
20550baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			       &broadcast_pings, sizeof(broadcast_pings)) < 0) {
20560baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror ("ping: can't set broadcasting");
20570baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20580baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20590baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project        }
20600baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20610baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_NOLOOP) {
20620baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int loop = 0;
20630baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_LOOP,
20640baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project							&loop, 1) == -1) {
20650baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror ("ping: can't disable multicast loopback");
20660baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20670baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20680baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20690baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (options & F_TTL) {
20700baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		int ittl = ttl;
20710baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_MULTICAST_TTL,
20720baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project							&ttl, 1) == -1) {
20730baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror ("ping: can't set multicast time-to-live");
20740baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20750baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20760baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (setsockopt(icmp_sock, IPPROTO_IP, IP_TTL,
20770baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project							&ittl, sizeof(ittl)) == -1) {
20780baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			perror ("ping: can't set unicast time-to-live");
20790baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20800baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20810baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20820baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20830baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (datalen > 0xFFFF - 8 - optlen - 20) {
20840baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		if (uid || datalen > sizeof(outpack)-8) {
20850baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			fprintf(stderr, "Error: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen);
20860baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project			exit(2);
20870baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		}
20880baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		/* Allow small oversize to root yet. It will cause EMSGSIZE. */
20890baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, "WARNING: packet size %d is too large. Maximum is %d\n", datalen, 0xFFFF-8-20-optlen);
20900baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20910baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
20920baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (datalen >= sizeof(struct timeval))	/* can we time transfer */
20930baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		timing = 1;
20940baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	packlen = datalen + MAXIPLEN + MAXICMPLEN;
20950baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (!(packet = (u_char *)malloc((u_int)packlen))) {
20960baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		fprintf(stderr, "ping: out of memory.\n");
20970baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		exit(2);
20980baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	}
20990baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
21000baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("PING %s (%s) ", hostname, inet_ntoa(whereto.sin_addr));
21010baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	if (device || (options&F_STRICTSOURCE))
21020baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project		printf("from %s %s: ", inet_ntoa(source.sin_addr), device ?: "");
21030baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	printf("%d(%d) bytes of data.\n", datalen, datalen+8+optlen+20);
21040baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
21050baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	setup(icmp_sock);
21060baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
21070baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	main_loop(icmp_sock, packet, packlen);
21080baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project	return 0;
21090baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project}
21100baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Project
21110baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid *dlopen(const char *filename, int flag) { return 0; }
21120baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectchar *dlerror(void) { return 0; }
21130baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectvoid *dlsym(void *handle, const char *symbol) { return 0; }
21140baa1aef81c61170e9078704b28264d9e8864b69The Android Open Source Projectint dlclose(void *handle) { return 0; }
2115