1ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#include "ping_common.h" 2ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#include <ctype.h> 3ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#include <sched.h> 4ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 5ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint options; 6ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 7ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint sndbuf; 8ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint ttl; 9ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint rtt; 10ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint rtt_addend; 11ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich__u16 acked; 12ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 13ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint mx_dup_ck = MAX_DUP_CHK; 14ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichchar rcvd_tbl[MAX_DUP_CHK / 8]; 15ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 16ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 17ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* counters */ 18ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong npackets; /* max packets to transmit */ 19ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong nreceived; /* # of packets we got back */ 20ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong nrepeats; /* number of duplicates */ 21ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong ntransmitted; /* sequence # for outbound packets = #sent */ 22ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong nchecksum; /* replies with bad checksum */ 23ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong nerrors; /* icmp errors */ 24ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint interval = 1000; /* interval between packets (msec) */ 25ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint preload; 26ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint deadline = 0; /* time to die */ 27ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint lingertime = MAXWAIT*1000; 28ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstruct timeval start_time, cur_time; 29ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvolatile int exiting; 30ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvolatile int status_snapshot; 31ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint confirm = 0; 32ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 33ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* Stupid workarounds for bugs/missing functionality in older linuces. 34ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * confirm_flag fixes refusing service of kernels without MSG_CONFIRM. 35ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * i.e. for linux-2.2 */ 36ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint confirm_flag = MSG_CONFIRM; 37ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* And this is workaround for bug in IP_RECVERR on raw sockets which is present 38ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * in linux-2.2.[0-19], linux-2.4.[0-7] */ 39ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint working_recverr; 40ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 41ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* timing */ 42ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint timing; /* flag to do timing */ 43ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong tmin = LONG_MAX; /* minimum round trip time */ 44ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong tmax; /* maximum round trip time */ 45ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* Message for rpm maintainers: have _shame_. If you want 46ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * to fix something send the patch to me for sanity checking. 47ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * "sparcfix" patch is a complete non-sense, apparenly the person 48ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * prepared it was stoned. 49ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 50ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong long tsum; /* sum of all times, for doing average */ 51ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichlong long tsum2; 52ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint pipesize = -1; 53ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 54ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint datalen = DEFDATALEN; 55ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 56ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichchar *hostname; 57ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint uid; 58ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint ident; /* process id to identify our packets */ 59ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 60ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic int screen_width = INT_MAX; 61ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 62ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* Fills all the outpack, excluding ICMP header, but _including_ 63ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * timestamp area with supplied pattern. 64ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 65ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic void fill(char *patp) 66ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 67ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int ii, jj, kk; 68ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int pat[16]; 69ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich char *cp; 70ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich char *bp = outpack+8; 71ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 72ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (cp = patp; *cp; cp++) { 73ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!isxdigit(*cp)) { 74ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, 75ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich "ping: patterns must be specified as hex digits.\n"); 76ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 77ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 78ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 79ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ii = sscanf(patp, 80ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 81ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], 82ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], 83ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich &pat[13], &pat[14], &pat[15]); 84ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 85ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ii > 0) { 86ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (kk = 0; kk <= maxpacket - (8 + ii); kk += ii) 87ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (jj = 0; jj < ii; ++jj) 88ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich bp[jj + kk] = pat[jj]; 89ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 90ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!(options & F_QUIET)) { 91ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("PATTERN: 0x"); 92ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (jj = 0; jj < ii; ++jj) 93ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("%02x", bp[jj] & 0xFF); 94ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("\n"); 95ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 96ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 97ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 98ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid common_options(int ch) 99ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 100ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich switch(ch) { 101ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'a': 102ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_AUDIBLE; 103ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 104ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'A': 105ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_ADAPTIVE; 106ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 107ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'c': 108ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich npackets = atoi(optarg); 109ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (npackets <= 0) { 110ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad number of packets to transmit.\n"); 111ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 112ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 113ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 114ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'd': 115ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_SO_DEBUG; 116ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 117ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'f': 118ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_FLOOD; 119ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setbuf(stdout, (char *)NULL); 120ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 121ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'i': /* wait between sending packets */ 122ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich { 123ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (strchr(optarg, '.')) { 124ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich float t; 125ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (sscanf(optarg, "%f", &t) != 1) { 126ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad timing interval.\n"); 127ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 128ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 129ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich interval = (int)(t*1000); 130ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else if (sscanf(optarg, "%d", &interval) == 1) { 131ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich interval *= 1000; 132ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 133ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad timing interval.\n"); 134ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 135ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 136ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 137ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (interval < 0) { 138ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad timing interval.\n"); 139ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 140ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 141ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_INTERVAL; 142ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 143ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 144ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'w': 145ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich deadline = atoi(optarg); 146ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (deadline < 0) { 147ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad wait time.\n"); 148ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 149ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 150ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 151ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'l': 152ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich preload = atoi(optarg); 153ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (preload <= 0) { 154ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad preload value, should be 1..%d\n", mx_dup_ck); 155ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 156ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 157ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (preload > mx_dup_ck) 158ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich preload = mx_dup_ck; 159ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (uid && preload > 3) { 160ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: cannot set preload to value > 3\n"); 161ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 162ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 163ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 164ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'S': 165ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich sndbuf = atoi(optarg); 166ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (sndbuf <= 0) { 167ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad sndbuf value.\n"); 168ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 169ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 170ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 171ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'n': 172ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_NUMERIC; 173ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 174ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'p': /* fill buffer with user pattern */ 175ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_PINGFILLED; 176ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fill(optarg); 177ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 178ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'q': 179ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_QUIET; 180ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 181ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'r': 182ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_SO_DONTROUTE; 183ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 184ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 's': /* size of packet to send */ 185ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich datalen = atoi(optarg); 186ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (datalen < 0) { 187ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen); 188ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 189ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 190ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 191ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'v': 192ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_VERBOSE; 193ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 194ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'L': 195ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_NOLOOP; 196ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 197ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 't': 198ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_TTL; 199ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ttl = atoi(optarg); 200ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ttl < 0 || ttl > 255) { 201ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: ttl %u out of range\n", ttl); 202ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 203ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 204ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 205ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'U': 206ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_LATENCY; 207ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 208ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'B': 209ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_STRICTSOURCE; 210ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 211ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'W': 212ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich lingertime = atoi(optarg); 213ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (lingertime < 0 || lingertime > INT_MAX/1000000) { 214ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: bad linger time.\n"); 215ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 216ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 217ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich lingertime *= 1000; 218ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 219ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich case 'V': 220ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("ping utility, iputils-ss%s\n", SNAPSHOT); 221ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(0); 222ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich default: 223ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich abort(); 224ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 225ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 226ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 227ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 228ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic void sigexit(int signo) 229ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 230ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exiting = 1; 231ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 232ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 233ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic void sigstatus(int signo) 234ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 235ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich status_snapshot = 1; 236ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 237ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 238ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 239ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint __schedule_exit(int next) 240ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 241ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich static unsigned long waittime; 242ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct itimerval it; 243ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 244ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (waittime) 245ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return next; 246ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 247ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nreceived) { 248ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich waittime = 2 * tmax; 249ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (waittime < 1000*interval) 250ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich waittime = 1000*interval; 251ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else 252ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich waittime = lingertime*1000; 253ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 254ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (next < 0 || next < waittime/1000) 255ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich next = waittime/1000; 256ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 257ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_interval.tv_sec = 0; 258ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_interval.tv_usec = 0; 259ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_value.tv_sec = waittime/1000000; 260ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_value.tv_usec = waittime%1000000; 261ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setitimer(ITIMER_REAL, &it, NULL); 262ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return next; 263ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 264ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 265ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic inline void update_interval(void) 266ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 267ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int est = rtt ? rtt/8 : interval*1000; 268ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 269ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich interval = (est+rtt_addend+500)/1000; 270ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (uid && interval < MINUSERINTERVAL) 271ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich interval = MINUSERINTERVAL; 272ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 273ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 274ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* 275ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * pinger -- 276ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet 277ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * will be added on by the kernel. The ID field is our UNIX process ID, 278ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * and the sequence number is an ascending integer. The first 8 bytes 279ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * of the data portion are used to hold a UNIX "timeval" struct in VAX 280ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * byte-order, to compute the round-trip time. 281ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 282ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint pinger(void) 283ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 284ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich static int oom_count; 285ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich static int tokens; 286ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int i; 287ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 288ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Have we already sent enough? If we have, return an arbitrary positive value. */ 289ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (exiting || (npackets && ntransmitted >= npackets && !deadline)) 290ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return 1000; 291ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 292ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Check that packets < rate*time + preload */ 293ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (cur_time.tv_sec == 0) { 294ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich gettimeofday(&cur_time, NULL); 295ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens = interval*(preload-1); 296ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 297ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long ntokens; 298ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval tv; 299ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 300ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich gettimeofday(&tv, NULL); 301ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 + 302ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich (tv.tv_usec-cur_time.tv_usec)/1000; 303ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!interval) { 304ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Case of unlimited flood is special; 305ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * if we see no reply, they are limited to 100pps */ 306ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntokens < MININTERVAL && in_flight() >= preload) 307ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return MININTERVAL-ntokens; 308ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 309ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ntokens += tokens; 310ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntokens > interval*preload) 311ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ntokens = interval*preload; 312ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntokens < interval) 313ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return interval - ntokens; 314ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 315ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich cur_time = tv; 316ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens = ntokens - interval; 317ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 318ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 319ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichresend: 320ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich i = send_probe(); 321ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 322ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (i == 0) { 323ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich oom_count = 0; 324ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich advance_ntransmitted(); 325ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!(options & F_QUIET) && (options & F_FLOOD)) { 326ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Very silly, but without this output with 327ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * high preload or pipe size is very confusing. */ 328ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((preload < screen_width && pipesize < screen_width) || 329ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich in_flight() < screen_width) 330ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich write(STDOUT_FILENO, ".", 1); 331ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 332ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return interval - tokens; 333ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 334ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 335ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* And handle various errors... */ 336ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (i > 0) { 337ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Apparently, it is some fatal bug. */ 338ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich abort(); 339ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else if (errno == ENOBUFS || errno == ENOMEM) { 340ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int nores_interval; 341ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 342ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Device queue overflow or OOM. Packet is not sent. */ 343ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens = 0; 344ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Slowdown. This works only in adaptive mode (option -A) */ 345ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000); 346ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options&F_ADAPTIVE) 347ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich update_interval(); 348ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich nores_interval = SCHINT(interval/2); 349ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nores_interval > 500) 350ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich nores_interval = 500; 351ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich oom_count++; 352ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (oom_count*nores_interval < lingertime) 353ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return nores_interval; 354ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich i = 0; 355ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Fall to hard error. It is to avoid complete deadlock 356ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * on stuck output device even when dealine was not requested. 357ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Expected timings are screwed up in any case, but we will 358ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * exit some day. :-) */ 359ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else if (errno == EAGAIN) { 360ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Socket buffer is full. */ 361ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens += interval; 362ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return MININTERVAL; 363ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 364ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((i=receive_error_msg()) > 0) { 365ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* An ICMP error arrived. */ 366ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens += interval; 367ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return MININTERVAL; 368ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 369ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Compatibility with old linuces. */ 370ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (i == 0 && confirm_flag && errno == EINVAL) { 371ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich confirm_flag = 0; 372ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich errno = 0; 373ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 374ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!errno) 375ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich goto resend; 376ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 377ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 378ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Hard local error. Pretend we sent packet. */ 379ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich advance_ntransmitted(); 380ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 381ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (i == 0 && !(options & F_QUIET)) { 382ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options & F_FLOOD) 383ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich write(STDOUT_FILENO, "E", 1); 384ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else 385ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich perror("ping: sendmsg"); 386ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 387ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tokens = 0; 388ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return SCHINT(interval); 389ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 390ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 391ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */ 392ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 393ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid sock_setbufs(int icmp_sock, int alloc) 394ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 395ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int rcvbuf, hold; 396ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int tmplen = sizeof(hold); 397ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 398ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!sndbuf) 399ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich sndbuf = alloc; 400ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf)); 401ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 402ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich rcvbuf = hold = alloc * preload; 403ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (hold < 65536) 404ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich hold = 65536; 405ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); 406ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (getsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) { 407ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (hold < rcvbuf) 408ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n"); 409ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 410ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 411ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 412ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* Protocol independent setup and parameter checks. */ 413ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 414ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid setup(int icmp_sock) 415ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 416ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int hold; 417ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval tv; 418ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 419ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((options & F_FLOOD) && !(options & F_INTERVAL)) 420ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich interval = 0; 421ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 422ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (uid && interval < MINUSERINTERVAL) { 423ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: cannot flood; minimal interval, allowed for user, is %dms\n", MINUSERINTERVAL); 424ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 425ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 426ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 427ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (interval >= INT_MAX/preload) { 428ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "ping: illegal preload and/or interval\n"); 429ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(2); 430ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 431ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 432ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich hold = 1; 433ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options & F_SO_DEBUG) 434ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold)); 435ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options & F_SO_DONTROUTE) 436ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold)); 437ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 438ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#ifdef SO_TIMESTAMP 439ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!(options&F_LATENCY)) { 440ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int on = 1; 441ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 442ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n"); 443ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 444ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#endif 445ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 446ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Set some SNDTIMEO to prevent blocking forever 447ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * on sends, when device is too slow or stalls. Just put limit 448ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * of one second, or "interval", if it is less. 449ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 450ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_sec = 1; 451ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_usec = 0; 452ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (interval < 1000) { 453ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_sec = 0; 454ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_usec = 1000 * SCHINT(interval); 455ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 456ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); 457ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 458ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Set RCVTIMEO to "interval". Note, it is just an optimization 459ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * allowing to avoid redundant poll(). */ 460ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_sec = SCHINT(interval)/1000; 461ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tv.tv_usec = 1000*(SCHINT(interval)%1000); 462ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (setsockopt(icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv))) 463ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_FLOOD_POLL; 464ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 465ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!(options & F_PINGFILLED)) { 466ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int i; 467ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich char *p = outpack+8; 468ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 469ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Do not forget about case of small datalen, 470ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * fill timestamp area too! 471ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 472ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (i = 0; i < datalen; ++i) 473ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich *p++ = i; 474ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 475ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 476ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!ident) 477ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ident = getpid() & 0xFFFF; 478ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 479ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich set_signal(SIGINT, sigexit); 480ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich set_signal(SIGALRM, sigexit); 481ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich set_signal(SIGQUIT, sigstatus); 482ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 483ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich gettimeofday(&start_time, NULL); 484ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 485ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (deadline) { 486ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct itimerval it; 487ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 488ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_interval.tv_sec = 0; 489ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_interval.tv_usec = 0; 490ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_value.tv_sec = deadline; 491ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich it.it_value.tv_usec = 0; 492ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich setitimer(ITIMER_REAL, &it, NULL); 493ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 494ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 495ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#ifndef ANDROID 496ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (isatty(STDOUT_FILENO)) { 497ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct winsize w; 498ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 499ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) { 500ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (w.ws_col > 0) 501ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich screen_width = w.ws_col; 502ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 503ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 504ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#endif 505ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 506ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 507ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid main_loop(int icmp_sock, __u8 *packet, int packlen) 508ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 509ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich char addrbuf[128]; 510ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich char ans_data[4096]; 511ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct iovec iov; 512ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct msghdr msg; 513ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct cmsghdr *c; 514ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int cc; 515ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int next; 516ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int polling; 517ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 518ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich iov.iov_base = (char *)packet; 519ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 520ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (;;) { 521ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Check exit conditions. */ 522ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (exiting) 523ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 524ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (npackets && nreceived + nerrors >= npackets) 525ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 526ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (deadline && nerrors) 527ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 528ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Check for and do special actions. */ 529ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (status_snapshot) 530ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich status(); 531ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 532ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Send probes scheduled to this time. */ 533ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich do { 534ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich next = pinger(); 535ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich next = schedule_exit(next); 536ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } while (next <= 0); 537ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 538ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* "next" is time to send next probe, if positive. 539ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * If next<=0 send now or as soon as possible. */ 540ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 541ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Technical part. Looks wicked. Could be dropped, 542ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * if everyone used the newest kernel. :-) 543ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Its purpose is: 544ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * 1. Provide intervals less than resolution of scheduler. 545ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Solution: spinning. 546ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * 2. Avoid use of poll(), when recvmsg() can provide 547ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * timed waiting (SO_RCVTIMEO). */ 548ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich polling = 0; 549ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) { 550ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int recv_expected = in_flight(); 551ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 552ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* If we are here, recvmsg() is unable to wait for 553ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * required timeout. */ 554ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (1000*next <= 1000000/(int)HZ) { 555ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Very short timeout... So, if we wait for 556ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * something, we sleep for MININTERVAL. 557ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Otherwise, spin! */ 558ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (recv_expected) { 559ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich next = MININTERVAL; 560ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 561ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich next = 0; 562ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* When spinning, no reasons to poll. 563ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Use nonblocking recvmsg() instead. */ 564ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich polling = MSG_DONTWAIT; 565ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* But yield yet. */ 566ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich sched_yield(); 567ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 568ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 569ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 570ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!polling && 571ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) { 572ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct pollfd pset; 573ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich pset.fd = icmp_sock; 574ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich pset.events = POLLIN|POLLERR; 575ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich pset.revents = 0; 576ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (poll(&pset, 1, next) < 1 || 577ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich !(pset.revents&(POLLIN|POLLERR))) 578ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich continue; 579ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich polling = MSG_DONTWAIT; 580ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 581ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 582ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 583ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (;;) { 584ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval *recv_timep = NULL; 585ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval recv_time; 586ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int not_ours = 0; /* Raw socket can receive messages 587ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * destined to other running pings. */ 588ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 589ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich iov.iov_len = packlen; 590ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_name = addrbuf; 591ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_namelen = sizeof(addrbuf); 592ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_iov = &iov; 593ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_iovlen = 1; 594ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_control = ans_data; 595ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich msg.msg_controllen = sizeof(ans_data); 596ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 597ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich cc = recvmsg(icmp_sock, &msg, polling); 598ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich polling = MSG_DONTWAIT; 599ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 600ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (cc < 0) { 601ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (errno == EAGAIN || errno == EINTR) 602ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 603ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!receive_error_msg()) { 604ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (errno) { 605ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich perror("ping: recvmsg"); 606ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 607ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 608ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich not_ours = 1; 609ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 610ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 611ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 612ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#ifdef SO_TIMESTAMP 613ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { 614ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (c->cmsg_level != SOL_SOCKET || 615ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich c->cmsg_type != SO_TIMESTAMP) 616ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich continue; 617ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) 618ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich continue; 619ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich recv_timep = (struct timeval*)CMSG_DATA(c); 620ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 621ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich#endif 622ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 623ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((options&F_LATENCY) || recv_timep == NULL) { 624ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((options&F_LATENCY) || 625ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ioctl(icmp_sock, SIOCGSTAMP, &recv_time)) 626ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich gettimeofday(&recv_time, NULL); 627ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich recv_timep = &recv_time; 628ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 629ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 630ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich not_ours = parse_reply(&msg, cc, addrbuf, recv_timep); 631ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 632ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 633ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* See? ... someone runs another ping on this host. */ 634ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (not_ours) 635ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich install_filter(); 636ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 637ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* If nothing is in flight, "break" returns us to pinger. */ 638ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (in_flight() == 0) 639ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 640ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 641ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* Otherwise, try to recvmsg() again. recvmsg() 642ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * is nonblocking after the first iteration, so that 643ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * if nothing is queued, it will receive EAGAIN 644ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * and return to pinger. */ 645ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 646ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 647ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich finish(); 648ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 649ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 650ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichint gather_statistics(__u8 *ptr, int cc, __u16 seq, int hops, 651ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int csfailed, struct timeval *tv, char *from) 652ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 653ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int dupflag = 0; 654ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long triptime = 0; 655ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 656ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ++nreceived; 657ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!csfailed) 658ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich acknowledge(seq); 659ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 660ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (timing && cc >= 8+sizeof(struct timeval)) { 661ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval tmp_tv; 662ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich memcpy(&tmp_tv, ptr, sizeof(tmp_tv)); 663ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 664ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichrestamp: 665ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tvsub(tv, &tmp_tv); 666ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich triptime = tv->tv_sec * 1000000 + tv->tv_usec; 667ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (triptime < 0) { 668ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime); 669ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich triptime = 0; 670ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!(options & F_LATENCY)) { 671ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich gettimeofday(tv, NULL); 672ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich options |= F_LATENCY; 673ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich goto restamp; 674ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 675ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 676ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!csfailed) { 677ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tsum += triptime; 678ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tsum2 += (long long)triptime * (long long)triptime; 679ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (triptime < tmin) 680ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmin = triptime; 681ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (triptime > tmax) 682ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmax = triptime; 683ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!rtt) 684ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich rtt = triptime*8; 685ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else 686ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich rtt += triptime-rtt/8; 687ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options&F_ADAPTIVE) 688ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich update_interval(); 689ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 690ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 691ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 692ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (csfailed) { 693ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ++nchecksum; 694ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich --nreceived; 695ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else if (TST(seq % mx_dup_ck)) { 696ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ++nrepeats; 697ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich --nreceived; 698ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich dupflag = 1; 699ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 700ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich SET(seq % mx_dup_ck); 701ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich dupflag = 0; 702ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 703ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich confirm = confirm_flag; 704ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 705ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options & F_QUIET) 706ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return 1; 707ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 708ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (options & F_FLOOD) { 709ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (!csfailed) 710ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich write(STDOUT_FILENO, "\b \b", 3); 711ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else 712ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich write(STDOUT_FILENO, "\bC", 1); 713ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } else { 714ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int i; 715ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich __u8 *cp, *dp; 716ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("%d bytes from %s: icmp_seq=%u", cc, from, seq); 717ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 718ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (hops >= 0) 719ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" ttl=%d", hops); 720ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 721ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (cc < datalen+8) { 722ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" (truncated)\n"); 723ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return 1; 724ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 725ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (timing) { 726ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (triptime >= 100000) 727ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" time=%ld ms", triptime/1000); 728ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else if (triptime >= 10000) 729ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" time=%ld.%01ld ms", triptime/1000, 730ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich (triptime%1000)/100); 731ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else if (triptime >= 1000) 732ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" time=%ld.%02ld ms", triptime/1000, 733ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich (triptime%1000)/10); 734ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich else 735ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" time=%ld.%03ld ms", triptime/1000, 736ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich triptime%1000); 737ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 738ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (dupflag) 739ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" (DUP!)"); 740ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (csfailed) 741ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(" (BAD CHECKSUM!)"); 742ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 743ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich /* check the data */ 744ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich cp = ((u_char*)ptr) + sizeof(struct timeval); 745ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich dp = &outpack[8 + sizeof(struct timeval)]; 746ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { 747ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (*cp != *dp) { 748ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("\nwrong data byte #%d should be 0x%x but was 0x%x", 749ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich i, *dp, *cp); 750ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich cp = (u_char*)ptr + sizeof(struct timeval); 751ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { 752ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if ((i % 32) == sizeof(struct timeval)) 753ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("\n#%d\t", i); 754ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("%x ", *cp); 755ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 756ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich break; 757ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 758ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 759ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 760ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return 0; 761ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 762ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 763ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichstatic long llsqrt(long long a) 764ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 765ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long long prev = ~((long long)1 << 63); 766ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long long x = a; 767ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 768ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (x > 0) { 769ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich while (x < prev) { 770ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich prev = x; 771ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich x = (x+(a/x))/2; 772ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 773ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 774ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 775ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich return (long)x; 776ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 777ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 778ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich/* 779ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * finish -- 780ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich * Print out statistics, and give up. 781ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich */ 782ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid finish(void) 783ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 784ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich struct timeval tv = cur_time; 785ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 786ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tvsub(&tv, &start_time); 787ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 788ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich putchar('\n'); 789ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fflush(stdout); 790ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("--- %s ping statistics ---\n", hostname); 791ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("%ld packets transmitted, ", ntransmitted); 792ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("%ld received", nreceived); 793ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nrepeats) 794ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", +%ld duplicates", nrepeats); 795ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nchecksum) 796ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", +%ld corrupted", nchecksum); 797ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nerrors) 798ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", +%ld errors", nerrors); 799ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntransmitted) { 800ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", %d%% packet loss", 801ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich (int) ((((long long)(ntransmitted - nreceived)) * 100) / 802ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ntransmitted)); 803ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", time %ldms", 1000*tv.tv_sec+tv.tv_usec/1000); 804ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 805ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich putchar('\n'); 806ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 807ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nreceived && timing) { 808ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long tmdev; 809ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 810ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tsum /= nreceived + nrepeats; 811ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tsum2 /= nreceived + nrepeats; 812ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmdev = llsqrt(tsum2 - tsum * tsum); 813ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 814ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms", 815ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmin/1000, tmin%1000, 816ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich (unsigned long)(tsum/1000), (long)(tsum%1000), 817ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmax/1000, tmax%1000, 818ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmdev/1000, tmdev%1000 819ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ); 820ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 821ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (pipesize > 1) 822ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", pipe %d", pipesize); 823ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntransmitted > 1 && (!interval || (options&(F_FLOOD|F_ADAPTIVE)))) { 824ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1); 825ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich printf(", ipg/ewma %d.%03d/%d.%03d ms", 826ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000); 827ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 828ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich putchar('\n'); 829ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich exit(!nreceived || (deadline && nreceived < npackets)); 830ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 831ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 832ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 833ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevichvoid status(void) 834ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich{ 835ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich int loss = 0; 836ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich long tavg = 0; 837ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 838ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich status_snapshot = 0; 839ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 840ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (ntransmitted) 841ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted; 842ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 843ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "\r%ld/%ld packets, %d%% loss", ntransmitted, nreceived, loss); 844ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 845ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich if (nreceived && timing) { 846ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tavg = tsum / (nreceived + nrepeats); 847ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 848ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms", 849ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmin/1000, tmin%1000, 850ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tavg/1000, tavg%1000, 851ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich rtt/8000, (rtt/8)%1000, 852ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich tmax/1000, tmax%1000 853ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich ); 854ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich } 855ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich fprintf(stderr, "\n"); 856ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich} 857ef37d714c2d9bbc7ee483bd1e1092c65c74ab92aNick Kralevich 858