1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ping_common.h" 2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <ctype.h> 3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sched.h> 4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <math.h> 5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint options; 7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint mark; 9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint sndbuf; 10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ttl; 11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint rtt; 12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint rtt_addend; 13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti__u16 acked; 14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct rcvd_table rcvd_tbl; 167618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colittiint using_ping_socket = 1; 17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* counters */ 20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong npackets; /* max packets to transmit */ 21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nreceived; /* # of packets we got back */ 22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nrepeats; /* number of duplicates */ 23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong ntransmitted; /* sequence # for outbound packets = #sent */ 24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nchecksum; /* replies with bad checksum */ 25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong nerrors; /* icmp errors */ 26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint interval = 1000; /* interval between packets (msec) */ 27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint preload; 28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint deadline = 0; /* time to die */ 29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint lingertime = MAXWAIT*1000; 30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct timeval start_time, cur_time; 31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int exiting; 32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int status_snapshot; 33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint confirm = 0; 34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivolatile int in_pr_addr = 0; /* pr_addr() is executing */ 35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittijmp_buf pr_addr_jmp; 36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Stupid workarounds for bugs/missing functionality in older linuces. 38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * confirm_flag fixes refusing service of kernels without MSG_CONFIRM. 39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * i.e. for linux-2.2 */ 40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint confirm_flag = MSG_CONFIRM; 41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* And this is workaround for bug in IP_RECVERR on raw sockets which is present 42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * in linux-2.2.[0-19], linux-2.4.[0-7] */ 43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint working_recverr; 44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* timing */ 46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint timing; /* flag to do timing */ 47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong tmin = LONG_MAX; /* minimum round trip time */ 48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong tmax; /* maximum round trip time */ 49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Message for rpm maintainers: have _shame_. If you want 50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * to fix something send the patch to me for sanity checking. 51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * "sparcfix" patch is a complete non-sense, apparenly the person 52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * prepared it was stoned. 53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong long tsum; /* sum of all times, for doing average */ 55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilong long tsum2; 56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pipesize = -1; 57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint datalen = DEFDATALEN; 59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *hostname; 61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint uid; 62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiuid_t euid; 637618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colittiint ident = 0; /* process id to identify our packets */ 64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int screen_width = INT_MAX; 66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_value_t cap_raw = CAP_NET_RAW; 71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic cap_value_t cap_admin = CAP_NET_ADMIN; 72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid limit_capabilities(void) 75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_cur_p; 78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_p; 79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_flag_value_t cap_ok; 80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_cur_p = cap_get_proc(); 82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_cur_p) { 83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_get_proc"); 84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_p = cap_init(); 88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_p) { 89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_init"); 90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_ok = CAP_CLEAR; 94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok); 95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_ok != CAP_CLEAR) 97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET); 98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_ok = CAP_CLEAR; 100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok); 101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_ok != CAP_CLEAR) 103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET); 104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap_p) < 0) { 106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_set_proc"); 107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (prctl(PR_SET_KEEPCAPS, 1) < 0) { 111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: prctl"); 112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setuid(getuid()) < 0) { 116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("setuid"); 117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (prctl(PR_SET_KEEPCAPS, 0) < 0) { 121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: prctl"); 122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_cur_p); 127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti uid = getuid(); 129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti euid = geteuid(); 130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef CAPABILITIES 131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (seteuid(uid)) { 132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: setuid"); 133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint modify_capability(cap_value_t cap, cap_flag_value_t on) 140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap_p = cap_get_proc(); 142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_flag_value_t cap_ok; 143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rc = -1; 144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!cap_p) { 146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_get_proc"); 147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_ok = CAP_CLEAR; 151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok); 152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_ok == CAP_CLEAR) { 153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = on ? -1 : 0; 154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on); 158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap_p) < 0) { 160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_set_proc"); 161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto out; 162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rc = 0; 167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout: 168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_p) 169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap_p); 170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return rc; 171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint modify_capability(int on) 174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (seteuid(on ? euid : getuid())) { 176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("seteuid"); 177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return -1; 178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid drop_capabilities(void) 185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef CAPABILITIES 187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_t cap = cap_init(); 188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cap_set_proc(cap) < 0) { 189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: cap_set_proc"); 190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cap_free(cap); 193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setuid(getuid())) { 195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: setuid"); 196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(-1); 197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 201924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colittivoid android_check_security(void) 202924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti{ 203924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti if (getauxval(AT_SECURE) != 0) { 204924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti fprintf(stderr, "This version of ping should NOT run with privileges. Aborting\n"); 205924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti exit(1); 206924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti } 207924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti} 208924a10d5d9645d4e82fa4b9781f2d85b41ec74f1Lorenzo Colitti 209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Fills all the outpack, excluding ICMP header, but _including_ 210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * timestamp area with supplied pattern. 211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void fill(char *patp) 213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ii, jj, kk; 215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int pat[16]; 216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *cp; 217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char *bp = outpack+8; 218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setlocale(LC_ALL, "C"); 221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (cp = patp; *cp; cp++) { 224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!isxdigit(*cp)) { 225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, 226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "ping: patterns must be specified as hex digits.\n"); 227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ii = sscanf(patp, 231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti &pat[13], &pat[14], &pat[15]); 235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ii > 0) { 237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii) 238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (jj = 0; jj < ii; ++jj) 239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti bp[jj + kk] = pat[jj]; 240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(options & F_QUIET)) { 242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("PATTERN: 0x"); 243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (jj = 0; jj < ii; ++jj) 244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%02x", bp[jj] & 0xFF); 245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("\n"); 246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef USE_IDN 249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setlocale(LC_ALL, ""); 250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid common_options(int ch) 254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch(ch) { 256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'a': 257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_AUDIBLE; 258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'A': 260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_ADAPTIVE; 261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'c': 263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti npackets = atoi(optarg); 264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (npackets <= 0) { 265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad number of packets to transmit.\n"); 266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'd': 270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_SO_DEBUG; 271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'D': 273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_PTIMEOFDAY; 274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'i': /* wait between sending packets */ 276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti { 277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti double dbl; 278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *ep; 279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = 0; 281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dbl = strtod(optarg, &ep); 282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno || *ep != '\0' || 284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) { 285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad timing interval\n"); 286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interval = (int)(dbl * 1000); 290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_INTERVAL; 292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'm': 295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti { 296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *endp; 297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mark = (int)strtoul(optarg, &endp, 10); 298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (mark < 0 || *endp != '\0') { 299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "mark cannot be negative\n"); 300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_MARK; 303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'w': 306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti deadline = atoi(optarg); 307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (deadline < 0) { 308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad wait time.\n"); 309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'l': 313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti preload = atoi(optarg); 314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (preload <= 0) { 315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad preload value, should be 1..%d\n", MAX_DUP_CHK); 316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (preload > MAX_DUP_CHK) 319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti preload = MAX_DUP_CHK; 320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (uid && preload > 3) { 321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: cannot set preload to value > 3\n"); 322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'O': 326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_OUTSTANDING; 327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'S': 329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sndbuf = atoi(optarg); 330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sndbuf <= 0) { 331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad sndbuf value.\n"); 332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'f': 336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_FLOOD; 337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setbuf(stdout, (char *)NULL); 338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* fallthrough to numeric - avoid gethostbyaddr during flood */ 339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'n': 340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_NUMERIC; 341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'p': /* fill buffer with user pattern */ 343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_PINGFILLED; 344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fill(optarg); 345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'q': 347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_QUIET; 348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'r': 350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_SO_DONTROUTE; 351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 's': /* size of packet to send */ 353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti datalen = atoi(optarg); 354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (datalen < 0) { 355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen); 356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (datalen > maxpacket - 8) { 359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: packet size too large: %d\n", 360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti datalen); 361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'v': 365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_VERBOSE; 366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'L': 368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_NOLOOP; 369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 't': 371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_TTL; 372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ttl = atoi(optarg); 373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ttl < 0 || ttl > 255) { 374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: ttl %u out of range\n", ttl); 375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'U': 379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_LATENCY; 380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'B': 382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_STRICTSOURCE; 383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'W': 385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti lingertime = atoi(optarg); 386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (lingertime < 0 || lingertime > INT_MAX/1000000) { 387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: bad linger time.\n"); 388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti lingertime *= 1000; 391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'V': 393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("ping utility, iputils-%s\n", SNAPSHOT); 394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti default: 396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti abort(); 397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sigexit(int signo) 402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exiting = 1; 404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (in_pr_addr) 405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti longjmp(pr_addr_jmp, 0); 406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void sigstatus(int signo) 409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status_snapshot = 1; 411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint __schedule_exit(int next) 415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static unsigned long waittime; 417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct itimerval it; 418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (waittime) 420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return next; 421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nreceived) { 423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti waittime = 2 * tmax; 424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (waittime < 1000*interval) 425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti waittime = 1000*interval; 426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else 427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti waittime = lingertime*1000; 428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (next < 0 || next < waittime/1000) 430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti next = waittime/1000; 431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_interval.tv_sec = 0; 433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_interval.tv_usec = 0; 434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_value.tv_sec = waittime/1000000; 435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_value.tv_usec = waittime%1000000; 436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setitimer(ITIMER_REAL, &it, NULL); 437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return next; 438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic inline void update_interval(void) 441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int est = rtt ? rtt/8 : interval*1000; 443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interval = (est+rtt_addend+500)/1000; 445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (uid && interval < MINUSERINTERVAL) 446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interval = MINUSERINTERVAL; 447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Print timestamp 451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid print_timestamp(void) 453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_PTIMEOFDAY) { 455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv; 456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&tv, NULL); 457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("[%lu.%06lu] ", 458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec); 459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * pinger -- 464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * will be added on by the kernel. The ID field is our UNIX process ID, 466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * and the sequence number is an ascending integer. The first 8 bytes 467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * of the data portion are used to hold a UNIX "timeval" struct in VAX 468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * byte-order, to compute the round-trip time. 469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pinger(void) 471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static int oom_count; 473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static int tokens; 474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Have we already sent enough? If we have, return an arbitrary positive value. */ 477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (exiting || (npackets && ntransmitted >= npackets && !deadline)) 478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1000; 479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check that packets < rate*time + preload */ 481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cur_time.tv_sec == 0) { 482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&cur_time, NULL); 483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens = interval*(preload-1); 484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long ntokens; 486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv; 487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&tv, NULL); 489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + 490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (tv.tv_usec-cur_time.tv_usec)/1000; 491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!interval) { 492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Case of unlimited flood is special; 493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * if we see no reply, they are limited to 100pps */ 494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntokens < MININTERVAL && in_flight() >= preload) 495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return MININTERVAL-ntokens; 496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntokens += tokens; 498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntokens > interval*preload) 499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntokens = interval*preload; 500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntokens < interval) 501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return interval - ntokens; 502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cur_time = tv; 504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens = ntokens - interval; 505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_OUTSTANDING) { 508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntransmitted > 0 && !rcvd_test(ntransmitted)) { 509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti print_timestamp(); 510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK)); 511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fflush(stdout); 512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiresend: 516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i = send_probe(); 517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i == 0) { 519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti oom_count = 0; 520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advance_ntransmitted(); 521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(options & F_QUIET) && (options & F_FLOOD)) { 522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Very silly, but without this output with 523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * high preload or pipe size is very confusing. */ 524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((preload < screen_width && pipesize < screen_width) || 525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti in_flight() < screen_width) 526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti write_stdout(".", 1); 527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return interval - tokens; 529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* And handle various errors... */ 532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i > 0) { 533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Apparently, it is some fatal bug. */ 534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti abort(); 535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else if (errno == ENOBUFS || errno == ENOMEM) { 536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int nores_interval; 537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Device queue overflow or OOM. Packet is not sent. */ 539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens = 0; 540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Slowdown. This works only in adaptive mode (option -A) */ 541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); 542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options&F_ADAPTIVE) 543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti update_interval(); 544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nores_interval = SCHINT(interval/2); 545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nores_interval > 500) 546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nores_interval = 500; 547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti oom_count++; 548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (oom_count*nores_interval < lingertime) 549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return nores_interval; 550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i = 0; 551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Fall to hard error. It is to avoid complete deadlock 552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * on stuck output device even when dealine was not requested. 553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Expected timings are screwed up in any case, but we will 554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * exit some day. :-) */ 555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else if (errno == EAGAIN) { 556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Socket buffer is full. */ 557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens += interval; 558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return MININTERVAL; 559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((i=receive_error_msg()) > 0) { 561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* An ICMP error arrived. */ 562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens += interval; 563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return MININTERVAL; 564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Compatibility with old linuces. */ 566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i == 0 && confirm_flag && errno == EINVAL) { 567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti confirm_flag = 0; 568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti errno = 0; 569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!errno) 571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto resend; 572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Hard local error. Pretend we sent packet. */ 575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advance_ntransmitted(); 576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (i == 0 && !(options & F_QUIET)) { 578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_FLOOD) 579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti write_stdout("E", 1); 580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: sendmsg"); 582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tokens = 0; 584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return SCHINT(interval); 585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */ 588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid sock_setbufs(int icmp_sock, int alloc) 590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int rcvbuf, hold; 592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t tmplen = sizeof(hold); 593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!sndbuf) 595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sndbuf = alloc; 596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf)); 597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rcvbuf = hold = alloc * preload; 599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (hold < 65536) 600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti hold = 65536; 601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); 602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) { 603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (hold < rcvbuf) 604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n"); 605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Protocol independent setup and parameter checks. */ 609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid setup(int icmp_sock) 611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int hold; 613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv; 614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigset_t sset; 615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((options & F_FLOOD) && !(options & F_INTERVAL)) 617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interval = 0; 618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (uid && interval < MINUSERINTERVAL) { 620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL); 621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (interval >= INT_MAX/preload) { 625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "ping: illegal preload and/or interval\n"); 626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(2); 627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti hold = 1; 630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_SO_DEBUG) 631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); 632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_SO_DONTROUTE) 633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); 634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SO_TIMESTAMP 636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(options&F_LATENCY)) { 637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int on = 1; 638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n"); 640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 642eadaaeadfa3d5fcf49f433896e9244f0a10a5f63Lorenzo Colitti#ifdef SO_MARK 643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_MARK) { 644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ret; 645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti enable_capability_admin(); 647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ret = setsockopt(icmp_sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); 648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti disable_capability_admin(); 649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ret == -1) { 651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* we probably dont wanna exit since old kernels 652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * dont support mark .. 653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "Warning: Failed to set mark %d\n", mark); 655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 657eadaaeadfa3d5fcf49f433896e9244f0a10a5f63Lorenzo Colitti#endif 658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Set some SNDTIMEO to prevent blocking forever 660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * on sends, when device is too slow or stalls. Just put limit 661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * of one second, or "interval", if it is less. 662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_sec = 1; 664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_usec = 0; 665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (interval < 1000) { 666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_sec = 0; 667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_usec = 1000 * SCHINT(interval); 668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Set RCVTIMEO to "interval". Note, it is just an optimization 672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * allowing to avoid redundant poll(). */ 673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_sec = SCHINT(interval)/1000; 674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tv.tv_usec = 1000*(SCHINT(interval)%1000); 675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv))) 676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_FLOOD_POLL; 677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(options & F_PINGFILLED)) { 679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char *p = outpack+8; 681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Do not forget about case of small datalen, 683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * fill timestamp area too! 684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < datalen; ++i) 686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *p++ = i; 687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 6897618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti if (!using_ping_socket) 6905df1daf326001b8d7d91a8b726ded17e09309952Lorenzo Colitti ident = htons(getpid() & 0xFFFF); 691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_signal(SIGINT, sigexit); 693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_signal(SIGALRM, sigexit); 694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti set_signal(SIGQUIT, sigstatus); 695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigemptyset(&sset); 697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigprocmask(SIG_SETMASK, &sset, NULL); 698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&start_time, NULL); 700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (deadline) { 702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct itimerval it; 703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_interval.tv_sec = 0; 705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_interval.tv_usec = 0; 706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_value.tv_sec = deadline; 707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti it.it_value.tv_usec = 0; 708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setitimer(ITIMER_REAL, &it, NULL); 709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (isatty(STDOUT_FILENO)) { 712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct winsize w; 713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { 715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (w.ws_col > 0) 716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti screen_width = w.ws_col; 717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid main_loop(int icmp_sock, __u8 *packet, int packlen) 722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char addrbuf[128]; 724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char ans_data[4096]; 725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct iovec iov; 726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct msghdr msg; 727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct cmsghdr *c; 728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc; 729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int next; 730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int polling; 731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti iov.iov_base = (char *)packet; 733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (;;) { 735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check exit conditions. */ 736313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (exiting) 737313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 738313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (npackets && nreceived + nerrors >= npackets) 739313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 740313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (deadline && nerrors) 741313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 742313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check for and do special actions. */ 743313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (status_snapshot) 744313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status(); 745313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 746313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Send probes scheduled to this time. */ 747313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti do { 748313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti next = pinger(); 749313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti next = schedule_exit(next); 750313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } while (next <= 0); 751313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 752313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* "next" is time to send next probe, if positive. 753313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * If next<=0 send now or as soon as possible. */ 754313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 755313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Technical part. Looks wicked. Could be dropped, 756313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * if everyone used the newest kernel. :-) 757313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Its purpose is: 758313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 1. Provide intervals less than resolution of scheduler. 759313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Solution: spinning. 760313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2. Avoid use of poll(), when recvmsg() can provide 761313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * timed waiting (SO_RCVTIMEO). */ 762313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti polling = 0; 763313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { 764313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int recv_expected = in_flight(); 765313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 766313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* If we are here, recvmsg() is unable to wait for 767313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * required timeout. */ 768313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) { 769313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Very short timeout... So, if we wait for 770313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * something, we sleep for MININTERVAL. 771313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Otherwise, spin! */ 772313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (recv_expected) { 773313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti next = MININTERVAL; 774313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 775313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti next = 0; 776313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* When spinning, no reasons to poll. 777313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Use nonblocking recvmsg() instead. */ 778313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti polling = MSG_DONTWAIT; 779313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* But yield yet. */ 780313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sched_yield(); 781313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 782313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 783313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 784313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!polling && 785313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { 786313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct pollfd pset; 787313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pset.fd = icmp_sock; 788313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pset.events = POLLIN|POLLERR; 789313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pset.revents = 0; 790313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (poll(&pset, 1, next) < 1 || 791313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti !(pset.revents&(POLLIN|POLLERR))) 792313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 793313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti polling = MSG_DONTWAIT; 794313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 795313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 796313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 797313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (;;) { 798313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval *recv_timep = NULL; 799313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval recv_time; 800313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int not_ours = 0; /* Raw socket can receive messages 801313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * destined to other running pings. */ 802313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 803313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti iov.iov_len = packlen; 804313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&msg, 0, sizeof(msg)); 805313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_name = addrbuf; 806313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_namelen = sizeof(addrbuf); 807313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_iov = &iov; 808313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_iovlen = 1; 809313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_control = ans_data; 810313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti msg.msg_controllen = sizeof(ans_data); 811313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 812313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = recvmsg(icmp_sock, &msg, polling); 813313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti polling = MSG_DONTWAIT; 814313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 815313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc < 0) { 816313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno == EAGAIN || errno == EINTR) 817313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 818313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!receive_error_msg()) { 819313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno) { 820313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti perror("ping: recvmsg"); 821313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 822313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 823313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti not_ours = 1; 824313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 825313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 826313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 827313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SO_TIMESTAMP 828313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { 829313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (c->cmsg_level != SOL_SOCKET || 830313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti c->cmsg_type != SO_TIMESTAMP) 831313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 832313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) 833313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 834313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recv_timep = (struct timeval*)CMSG_DATA(c); 835313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 836313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 837313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 838313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((options&F_LATENCY) || recv_timep == NULL) { 839313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((options&F_LATENCY) || 840313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) 841313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(&recv_time, NULL); 842313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recv_timep = &recv_time; 843313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 844313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 845313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); 846313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 847313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 848313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* See? ... someone runs another ping on this host. */ 8497618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti if (not_ours && !using_ping_socket) 850313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti install_filter(); 851313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 852313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* If nothing is in flight, "break" returns us to pinger. */ 853313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (in_flight() == 0) 854313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 855313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 856313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Otherwise, try to recvmsg() again. recvmsg() 857313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * is nonblocking after the first iteration, so that 858313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * if nothing is queued, it will receive EAGAIN 859313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * and return to pinger. */ 860313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 861313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 862313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti finish(); 863313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 864313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 865313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint gather_statistics(__u8 *icmph, int icmplen, 866313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc, __u16 seq, int hops, 867313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int csfailed, struct timeval *tv, char *from, 868313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti void (*pr_reply)(__u8 *icmph, int cc)) 869313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 870313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int dupflag = 0; 871313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long triptime = 0; 872313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti __u8 *ptr = icmph + icmplen; 873313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 874313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ++nreceived; 875313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!csfailed) 876313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti acknowledge(seq); 877313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 878313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (timing && cc >= 8+sizeof(struct timeval)) { 879313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tmp_tv; 880313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memcpy(&tmp_tv, ptr, sizeof(tmp_tv)); 881313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 882313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittirestamp: 883313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tvsub(tv, &tmp_tv); 884313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti triptime = tv->tv_sec * 1000000 + tv->tv_usec; 885313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (triptime < 0) { 886313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime); 887313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti triptime = 0; 888313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(options & F_LATENCY)) { 889313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti gettimeofday(tv, NULL); 890313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti options |= F_LATENCY; 891313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto restamp; 892313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 893313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 894313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!csfailed) { 895313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tsum += triptime; 896313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tsum2 += (long long)triptime * (long long)triptime; 897313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (triptime < tmin) 898313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tmin = triptime; 899313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (triptime > tmax) 900313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tmax = triptime; 901313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!rtt) 902313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtt = triptime*8; 903313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 904313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtt += triptime-rtt/8; 905313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options&F_ADAPTIVE) 906313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti update_interval(); 907313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 908313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 909313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 910313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (csfailed) { 911313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ++nchecksum; 912313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti --nreceived; 913313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else if (rcvd_test(seq)) { 914313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ++nrepeats; 915313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti --nreceived; 916313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dupflag = 1; 917313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 918313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rcvd_set(seq); 919313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dupflag = 0; 920313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 921313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti confirm = confirm_flag; 922313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 923313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_QUIET) 924313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1; 925313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 926313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (options & F_FLOOD) { 927313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!csfailed) 928313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti write_stdout("\b \b", 3); 929313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 930313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti write_stdout("\bC", 2); 931313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 932313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 933313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti __u8 *cp, *dp; 934313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 935313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti print_timestamp(); 936313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%d bytes from %s:", cc, from); 937313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 938313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (pr_reply) 939313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_reply(icmph, cc); 940313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 941313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (hops >= 0) 942313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" ttl=%d", hops); 943313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 944313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc < datalen+8) { 945313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" (truncated)\n"); 946313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 1; 947313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 948313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (timing) { 949313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (triptime >= 100000) 950313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" time=%ld ms", triptime/1000); 951313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else if (triptime >= 10000) 952313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" time=%ld.%01ld ms", triptime/1000, 953313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (triptime%1000)/100); 954313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else if (triptime >= 1000) 955313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" time=%ld.%02ld ms", triptime/1000, 956313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (triptime%1000)/10); 957313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 958313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" time=%ld.%03ld ms", triptime/1000, 959313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti triptime%1000); 960313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 961313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (dupflag) 962313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" (DUP!)"); 963313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (csfailed) 964313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(" (BAD CHECKSUM!)"); 965313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 966313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* check the data */ 967313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cp = ((u_char*)ptr) + sizeof(struct timeval); 968313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti dp = &outpack[8 + sizeof(struct timeval)]; 969313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { 970313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (*cp != *dp) { 971313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 972313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i, *dp, *cp); 973313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cp = (u_char*)ptr + sizeof(struct timeval); 974313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { 975313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((i % 32) == sizeof(struct timeval)) 976313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("\n#%d\t", i); 977313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%x ", *cp); 978313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 979313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 980313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 981313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 982313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 983313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return 0; 984313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 985313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 986313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic long llsqrt(long long a) 987313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 988313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long long prev = ~((long long)1 << 63); 989313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long long x = a; 990313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 991313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (x > 0) { 992313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (x < prev) { 993313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prev = x; 994313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti x = (x+(a/x))/2; 995313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 996313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 997313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 998313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (long)x; 999313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1000313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1001313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 1002313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * finish -- 1003313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Print out statistics, and give up. 1004313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 1005313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid finish(void) 1006313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1007313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct timeval tv = cur_time; 1008313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *comma = ""; 1009313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1010313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tvsub(&tv, &start_time); 1011313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1012313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti putchar('\n'); 1013313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fflush(stdout); 1014313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("--- %s ping statistics ---\n", hostname); 1015313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%ld packets transmitted, ", ntransmitted); 1016313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%ld received", nreceived); 1017313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nrepeats) 1018313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(", +%ld duplicates", nrepeats); 1019313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nchecksum) 1020313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(", +%ld corrupted", nchecksum); 1021313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nerrors) 1022313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(", +%ld errors", nerrors); 1023313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntransmitted) { 1024313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(", %d%% packet loss", 1025313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (int) ((((long long)(ntransmitted - nreceived)) * 100) / 1026313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntransmitted)); 1027313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000); 1028313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1029313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti putchar('\n'); 1030313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1031313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nreceived && timing) { 1032313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long tmdev; 1033313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1034313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tsum /= nreceived + nrepeats; 1035313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tsum2 /= nreceived + nrepeats; 1036313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tmdev = llsqrt(tsum2 - tsum * tsum); 1037313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1038313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms", 1039313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (long)tmin/1000, (long)tmin%1000, 1040313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (unsigned long)(tsum/1000), (long)(tsum%1000), 1041313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (long)tmax/1000, (long)tmax%1000, 1042313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (long)tmdev/1000, (long)tmdev%1000 1043313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ); 1044313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti comma = ", "; 1045313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1046313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (pipesize > 1) { 1047313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%spipe %d", comma, pipesize); 1048313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti comma = ", "; 1049313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1050313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) { 1051313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1); 1052313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("%sipg/ewma %d.%03d/%d.%03d ms", 1053313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000); 1054313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1055313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti putchar('\n'); 1056313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(!nreceived || (deadline && nreceived < npackets)); 1057313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1058313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1059313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1060313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid status(void) 1061313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1062313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int loss = 0; 1063313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long tavg = 0; 1064313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1065313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti status_snapshot = 0; 1066313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1067313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntransmitted) 1068313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted; 1069313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1070313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss); 1071313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1072313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (nreceived && timing) { 1073313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tavg = tsum / (nreceived + nrepeats); 1074313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1075313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms", 1076313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (long)tmin/1000, (long)tmin%1000, 1077313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tavg/1000, tavg%1000, 1078313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtt/8000, (rtt/8)%1000, 1079313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (long)tmax/1000, (long)tmax%1000 1080313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ); 1081313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1082313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fprintf(stderr, "\n"); 1083313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1084313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1085ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colittiinline int is_ours(uint16_t id) { 10867618e8104cac3bcc0ba509f4ba40644b665a3ac1Lorenzo Colitti return using_ping_socket || id == ident; 1087ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colitti} 1088ce2d2d04ca21aedab67bd41dd9f89063454ed463Lorenzo Colitti 1089