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*)⌖ 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