|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Copyright (c) 1989 The Regents of the University of California.
|
|
Packit Service |
6f2e62 |
* All rights reserved.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* This code is derived from software contributed to Berkeley by
|
|
Packit Service |
6f2e62 |
* Mike Muuss.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
6f2e62 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
6f2e62 |
* are met:
|
|
Packit Service |
6f2e62 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit Service |
6f2e62 |
* notice, this list of conditions and the following disclaimer.
|
|
Packit Service |
6f2e62 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit Service |
6f2e62 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit Service |
6f2e62 |
* documentation and/or other materials provided with the distribution.
|
|
Packit Service |
6f2e62 |
* 3. Neither the name of the University nor the names of its contributors
|
|
Packit Service |
6f2e62 |
* may be used to endorse or promote products derived from this software
|
|
Packit Service |
6f2e62 |
* without specific prior written permission.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit Service |
6f2e62 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit Service |
6f2e62 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
6f2e62 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
Packit Service |
6f2e62 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit Service |
6f2e62 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit Service |
6f2e62 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit Service |
6f2e62 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit Service |
6f2e62 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit Service |
6f2e62 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit Service |
6f2e62 |
* SUCH DAMAGE.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#include "ping.h"
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifndef HZ
|
|
Packit Service |
6f2e62 |
#define HZ sysconf(_SC_CLK_TCK)
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int options;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int mark;
|
|
Packit Service |
6f2e62 |
int sndbuf;
|
|
Packit Service |
6f2e62 |
int ttl;
|
|
Packit Service |
6f2e62 |
int rtt;
|
|
Packit Service |
6f2e62 |
int rtt_addend;
|
|
Packit Service |
6f2e62 |
__u16 acked;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
unsigned char outpack[MAXPACKET];
|
|
Packit Service |
6f2e62 |
struct rcvd_table rcvd_tbl;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* counters */
|
|
Packit Service |
6f2e62 |
long npackets; /* max packets to transmit */
|
|
Packit Service |
6f2e62 |
long nreceived; /* # of packets we got back */
|
|
Packit Service |
6f2e62 |
long nrepeats; /* number of duplicates */
|
|
Packit Service |
6f2e62 |
long ntransmitted; /* sequence # for outbound packets = #sent */
|
|
Packit Service |
6f2e62 |
long nchecksum; /* replies with bad checksum */
|
|
Packit Service |
6f2e62 |
long nerrors; /* icmp errors */
|
|
Packit Service |
6f2e62 |
int interval = 1000; /* interval between packets (msec) */
|
|
Packit Service |
6f2e62 |
int preload = 1;
|
|
Packit Service |
6f2e62 |
int deadline = 0; /* time to die */
|
|
Packit Service |
6f2e62 |
int lingertime = MAXWAIT*1000;
|
|
Packit Service |
6f2e62 |
struct timeval start_time, cur_time;
|
|
Packit Service |
6f2e62 |
volatile int exiting;
|
|
Packit Service |
6f2e62 |
volatile int status_snapshot;
|
|
Packit Service |
6f2e62 |
int confirm = 0;
|
|
Packit Service |
6f2e62 |
volatile int in_pr_addr = 0; /* pr_addr() is executing */
|
|
Packit Service |
6f2e62 |
jmp_buf pr_addr_jmp;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Stupid workarounds for bugs/missing functionality in older linuces.
|
|
Packit Service |
6f2e62 |
* confirm_flag fixes refusing service of kernels without MSG_CONFIRM.
|
|
Packit Service |
6f2e62 |
* i.e. for linux-2.2 */
|
|
Packit Service |
6f2e62 |
int confirm_flag = MSG_CONFIRM;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* timing */
|
|
Packit Service |
6f2e62 |
int timing; /* flag to do timing */
|
|
Packit Service |
6f2e62 |
long tmin = LONG_MAX; /* minimum round trip time */
|
|
Packit Service |
6f2e62 |
long tmax; /* maximum round trip time */
|
|
Packit Service |
6f2e62 |
/* Message for rpm maintainers: have _shame_. If you want
|
|
Packit Service |
6f2e62 |
* to fix something send the patch to me for sanity checking.
|
|
Packit Service |
6f2e62 |
* "sparcfix" patch is a complete non-sense, apparenly the person
|
|
Packit Service |
6f2e62 |
* prepared it was stoned.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
long long tsum; /* sum of all times, for doing average */
|
|
Packit Service |
6f2e62 |
long long tsum2;
|
|
Packit Service |
6f2e62 |
int pipesize = -1;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int datalen = DEFDATALEN;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
char *hostname;
|
|
Packit Service |
6f2e62 |
int uid;
|
|
Packit Service |
6f2e62 |
uid_t euid;
|
|
Packit Service |
6f2e62 |
int ident; /* process id to identify our packets */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
static int screen_width = INT_MAX;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
static cap_value_t cap_raw = CAP_NET_RAW;
|
|
Packit Service |
6f2e62 |
static cap_value_t cap_admin = CAP_NET_ADMIN;
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void limit_capabilities(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
cap_t cap_cur_p;
|
|
Packit Service |
6f2e62 |
cap_t cap_p;
|
|
Packit Service |
6f2e62 |
cap_flag_value_t cap_ok;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_cur_p = cap_get_proc();
|
|
Packit Service |
6f2e62 |
if (!cap_cur_p) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_get_proc");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_p = cap_init();
|
|
Packit Service |
6f2e62 |
if (!cap_p) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_init");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_ok = CAP_CLEAR;
|
|
Packit Service |
6f2e62 |
cap_get_flag(cap_cur_p, CAP_NET_ADMIN, CAP_PERMITTED, &cap_ok);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cap_ok != CAP_CLEAR)
|
|
Packit Service |
6f2e62 |
cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_admin, CAP_SET);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_ok = CAP_CLEAR;
|
|
Packit Service |
6f2e62 |
cap_get_flag(cap_cur_p, CAP_NET_RAW, CAP_PERMITTED, &cap_ok);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cap_ok != CAP_CLEAR)
|
|
Packit Service |
6f2e62 |
cap_set_flag(cap_p, CAP_PERMITTED, 1, &cap_raw, CAP_SET);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cap_set_proc(cap_p) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_set_proc");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: prctl");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (setuid(getuid()) < 0) {
|
|
Packit Service |
6f2e62 |
perror("setuid");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: prctl");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_free(cap_p);
|
|
Packit Service |
6f2e62 |
cap_free(cap_cur_p);
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
uid = getuid();
|
|
Packit Service |
6f2e62 |
euid = geteuid();
|
|
Packit Service |
6f2e62 |
#ifndef CAPABILITIES
|
|
Packit Service |
6f2e62 |
if (seteuid(uid)) {
|
|
Packit Service |
6f2e62 |
perror("ping: setuid");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
int modify_capability(cap_value_t cap, cap_flag_value_t on)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
cap_t cap_p = cap_get_proc();
|
|
Packit Service |
6f2e62 |
cap_flag_value_t cap_ok;
|
|
Packit Service |
6f2e62 |
int rc = -1;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (!cap_p) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_get_proc");
|
|
Packit Service |
6f2e62 |
goto out;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_ok = CAP_CLEAR;
|
|
Packit Service |
6f2e62 |
cap_get_flag(cap_p, cap, CAP_PERMITTED, &cap_ok);
|
|
Packit Service |
6f2e62 |
if (cap_ok == CAP_CLEAR) {
|
|
Packit Service |
6f2e62 |
rc = on ? -1 : 0;
|
|
Packit Service |
6f2e62 |
goto out;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cap_set_proc(cap_p) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_set_proc");
|
|
Packit Service |
6f2e62 |
goto out;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cap_free(cap_p);
|
|
Packit Service |
6f2e62 |
cap_p = NULL;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
rc = 0;
|
|
Packit Service |
6f2e62 |
out:
|
|
Packit Service |
6f2e62 |
if (cap_p)
|
|
Packit Service |
6f2e62 |
cap_free(cap_p);
|
|
Packit Service |
6f2e62 |
return rc;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#else
|
|
Packit Service |
6f2e62 |
int modify_capability(int on)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
if (seteuid(on ? euid : getuid())) {
|
|
Packit Service |
6f2e62 |
perror("seteuid");
|
|
Packit Service |
6f2e62 |
return -1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
return 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void drop_capabilities(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
cap_t cap = cap_init();
|
|
Packit Service |
6f2e62 |
if (cap_set_proc(cap) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: cap_set_proc");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
cap_free(cap);
|
|
Packit Service |
6f2e62 |
#else
|
|
Packit Service |
6f2e62 |
if (setuid(getuid())) {
|
|
Packit Service |
6f2e62 |
perror("ping: setuid");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Fills all the outpack, excluding ICMP header, but _including_
|
|
Packit Service |
6f2e62 |
* timestamp area with supplied pattern.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
void fill(char *patp, void *packet, unsigned packet_size)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int ii, jj, kk;
|
|
Packit Service |
6f2e62 |
int pat[16];
|
|
Packit Service |
6f2e62 |
char *cp;
|
|
Packit Service |
6f2e62 |
unsigned char *bp = packet+8;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef USE_IDN
|
|
Packit Service |
6f2e62 |
setlocale(LC_ALL, "C");
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (cp = patp; *cp; cp++) {
|
|
Packit Service |
6f2e62 |
if (!isxdigit(*cp)) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr,
|
|
Packit Service |
6f2e62 |
"ping: patterns must be specified as hex digits.\n");
|
|
Packit Service |
6f2e62 |
exit(2);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
ii = sscanf(patp,
|
|
Packit Service |
6f2e62 |
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
|
|
Packit Service |
6f2e62 |
&pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
|
|
Packit Service |
6f2e62 |
&pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
|
|
Packit Service |
6f2e62 |
&pat[13], &pat[14], &pat[15]);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (ii > 0) {
|
|
Packit Service |
6f2e62 |
for (kk = 0; kk <= packet_size - (8 + ii); kk += ii)
|
|
Packit Service |
6f2e62 |
for (jj = 0; jj < ii; ++jj)
|
|
Packit Service |
6f2e62 |
bp[jj + kk] = pat[jj];
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (!(options & F_QUIET)) {
|
|
Packit Service |
6f2e62 |
printf("PATTERN: 0x");
|
|
Packit Service |
6f2e62 |
for (jj = 0; jj < ii; ++jj)
|
|
Packit Service |
6f2e62 |
printf("%02x", bp[jj] & 0xFF);
|
|
Packit Service |
6f2e62 |
printf("\n");
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef USE_IDN
|
|
Packit Service |
6f2e62 |
setlocale(LC_ALL, "");
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
static void sigexit(int signo)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
exiting = 1;
|
|
Packit Service |
6f2e62 |
if (in_pr_addr)
|
|
Packit Service |
6f2e62 |
longjmp(pr_addr_jmp, 0);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
static void sigstatus(int signo)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
status_snapshot = 1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int __schedule_exit(int next)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
static unsigned long waittime;
|
|
Packit Service |
6f2e62 |
struct itimerval it;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (waittime)
|
|
Packit Service |
6f2e62 |
return next;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (nreceived) {
|
|
Packit Service |
6f2e62 |
waittime = 2 * tmax;
|
|
Packit Service |
6f2e62 |
if (waittime < 1000*interval)
|
|
Packit Service |
6f2e62 |
waittime = 1000*interval;
|
|
Packit Service |
6f2e62 |
} else
|
|
Packit Service |
6f2e62 |
waittime = lingertime*1000;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (next < 0 || next < waittime/1000)
|
|
Packit Service |
6f2e62 |
next = waittime/1000;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
it.it_interval.tv_sec = 0;
|
|
Packit Service |
6f2e62 |
it.it_interval.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
it.it_value.tv_sec = waittime/1000000;
|
|
Packit Service |
6f2e62 |
it.it_value.tv_usec = waittime%1000000;
|
|
Packit Service |
6f2e62 |
setitimer(ITIMER_REAL, &it, NULL);
|
|
Packit Service |
6f2e62 |
return next;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
static inline void update_interval(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int est = rtt ? rtt/8 : interval*1000;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
interval = (est+rtt_addend+500)/1000;
|
|
Packit Service |
6f2e62 |
if (uid && interval < MINUSERINTERVAL)
|
|
Packit Service |
6f2e62 |
interval = MINUSERINTERVAL;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Print timestamp
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
void print_timestamp(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
if (options & F_PTIMEOFDAY) {
|
|
Packit Service |
6f2e62 |
struct timeval tv;
|
|
Packit Service |
6f2e62 |
gettimeofday(&tv, NULL);
|
|
Packit Service |
6f2e62 |
printf("[%lu.%06lu] ",
|
|
Packit Service |
6f2e62 |
(unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* pinger --
|
|
Packit Service |
6f2e62 |
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
|
|
Packit Service |
6f2e62 |
* will be added on by the kernel. The ID field is our UNIX process ID,
|
|
Packit Service |
6f2e62 |
* and the sequence number is an ascending integer. The first 8 bytes
|
|
Packit Service |
6f2e62 |
* of the data portion are used to hold a UNIX "timeval" struct in VAX
|
|
Packit Service |
6f2e62 |
* byte-order, to compute the round-trip time.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
int pinger(ping_func_set_st *fset, socket_st *sock)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
static int oom_count;
|
|
Packit Service |
6f2e62 |
static int tokens;
|
|
Packit Service |
6f2e62 |
int i;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Have we already sent enough? If we have, return an arbitrary positive value. */
|
|
Packit Service |
6f2e62 |
if (exiting || (npackets && ntransmitted >= npackets && !deadline))
|
|
Packit Service |
6f2e62 |
return 1000;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Check that packets < rate*time + preload */
|
|
Packit Service |
6f2e62 |
if (cur_time.tv_sec == 0) {
|
|
Packit Service |
6f2e62 |
gettimeofday(&cur_time, NULL);
|
|
Packit Service |
6f2e62 |
tokens = interval*(preload-1);
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
long ntokens;
|
|
Packit Service |
6f2e62 |
struct timeval tv;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
gettimeofday(&tv, NULL);
|
|
Packit Service |
6f2e62 |
ntokens = (tv.tv_sec - cur_time.tv_sec)*1000 +
|
|
Packit Service |
6f2e62 |
(tv.tv_usec-cur_time.tv_usec)/1000;
|
|
Packit Service |
6f2e62 |
if (!interval) {
|
|
Packit Service |
6f2e62 |
/* Case of unlimited flood is special;
|
|
Packit Service |
6f2e62 |
* if we see no reply, they are limited to 100pps */
|
|
Packit Service |
6f2e62 |
if (ntokens < MININTERVAL && in_flight() >= preload)
|
|
Packit Service |
6f2e62 |
return MININTERVAL-ntokens;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
ntokens += tokens;
|
|
Packit Service |
6f2e62 |
if (ntokens > interval*preload)
|
|
Packit Service |
6f2e62 |
ntokens = interval*preload;
|
|
Packit Service |
6f2e62 |
if (ntokens < interval)
|
|
Packit Service |
6f2e62 |
return interval - ntokens;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cur_time = tv;
|
|
Packit Service |
6f2e62 |
tokens = ntokens - interval;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (options & F_OUTSTANDING) {
|
|
Packit Service |
6f2e62 |
if (ntransmitted > 0 && !rcvd_test(ntransmitted)) {
|
|
Packit Service |
6f2e62 |
print_timestamp();
|
|
Packit Service |
6f2e62 |
printf("no answer yet for icmp_seq=%lu\n", (ntransmitted % MAX_DUP_CHK));
|
|
Packit Service |
6f2e62 |
fflush(stdout);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
resend:
|
|
Packit Service |
6f2e62 |
i = fset->send_probe(sock, outpack, sizeof(outpack));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (i == 0) {
|
|
Packit Service |
6f2e62 |
oom_count = 0;
|
|
Packit Service |
6f2e62 |
advance_ntransmitted();
|
|
Packit Service |
6f2e62 |
if (!(options & F_QUIET) && (options & F_FLOOD)) {
|
|
Packit Service |
6f2e62 |
/* Very silly, but without this output with
|
|
Packit Service |
6f2e62 |
* high preload or pipe size is very confusing. */
|
|
Packit Service |
6f2e62 |
if ((preload < screen_width && pipesize < screen_width) ||
|
|
Packit Service |
6f2e62 |
in_flight() < screen_width)
|
|
Packit Service |
6f2e62 |
write_stdout(".", 1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
return interval - tokens;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* And handle various errors... */
|
|
Packit Service |
6f2e62 |
if (i > 0) {
|
|
Packit Service |
6f2e62 |
/* Apparently, it is some fatal bug. */
|
|
Packit Service |
6f2e62 |
abort();
|
|
Packit Service |
6f2e62 |
} else if (errno == ENOBUFS || errno == ENOMEM) {
|
|
Packit Service |
6f2e62 |
int nores_interval;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Device queue overflow or OOM. Packet is not sent. */
|
|
Packit Service |
6f2e62 |
tokens = 0;
|
|
Packit Service |
6f2e62 |
/* Slowdown. This works only in adaptive mode (option -A) */
|
|
Packit Service |
6f2e62 |
rtt_addend += (rtt < 8*50000 ? rtt/8 : 50000);
|
|
Packit Service |
6f2e62 |
if (options&F_ADAPTIVE)
|
|
Packit Service |
6f2e62 |
update_interval();
|
|
Packit Service |
6f2e62 |
nores_interval = SCHINT(interval/2);
|
|
Packit Service |
6f2e62 |
if (nores_interval > 500)
|
|
Packit Service |
6f2e62 |
nores_interval = 500;
|
|
Packit Service |
6f2e62 |
oom_count++;
|
|
Packit Service |
6f2e62 |
if (oom_count*nores_interval < lingertime)
|
|
Packit Service |
6f2e62 |
return nores_interval;
|
|
Packit Service |
6f2e62 |
i = 0;
|
|
Packit Service |
6f2e62 |
/* Fall to hard error. It is to avoid complete deadlock
|
|
Packit Service |
6f2e62 |
* on stuck output device even when dealine was not requested.
|
|
Packit Service |
6f2e62 |
* Expected timings are screwed up in any case, but we will
|
|
Packit Service |
6f2e62 |
* exit some day. :-) */
|
|
Packit Service |
6f2e62 |
} else if (errno == EAGAIN) {
|
|
Packit Service |
6f2e62 |
/* Socket buffer is full. */
|
|
Packit Service |
6f2e62 |
tokens += interval;
|
|
Packit Service |
6f2e62 |
return MININTERVAL;
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
if ((i=fset->receive_error_msg(sock)) > 0) {
|
|
Packit Service |
6f2e62 |
/* An ICMP error arrived. In this case, we've received
|
|
Packit Service |
6f2e62 |
* an error from sendto(), but we've also received an
|
|
Packit Service |
6f2e62 |
* ICMP message, which means the packet did in fact
|
|
Packit Service |
6f2e62 |
* send in some capacity. So, in this odd case, report
|
|
Packit Service |
6f2e62 |
* the more specific errno as the error, and treat this
|
|
Packit Service |
6f2e62 |
* as a hard local error. */
|
|
Packit Service |
6f2e62 |
i = 0;
|
|
Packit Service |
6f2e62 |
goto hard_local_error;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
/* Compatibility with old linuces. */
|
|
Packit Service |
6f2e62 |
if (i == 0 && confirm_flag && errno == EINVAL) {
|
|
Packit Service |
6f2e62 |
confirm_flag = 0;
|
|
Packit Service |
6f2e62 |
errno = 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (!errno)
|
|
Packit Service |
6f2e62 |
goto resend;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
hard_local_error:
|
|
Packit Service |
6f2e62 |
/* Hard local error. Pretend we sent packet. */
|
|
Packit Service |
6f2e62 |
advance_ntransmitted();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (i == 0 && !(options & F_QUIET)) {
|
|
Packit Service |
6f2e62 |
if (options & F_FLOOD)
|
|
Packit Service |
6f2e62 |
write_stdout("E", 1);
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
perror("ping: sendmsg");
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
tokens = 0;
|
|
Packit Service |
6f2e62 |
return SCHINT(interval);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Set socket buffers, "alloc" is an estimate of memory taken by single packet. */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void sock_setbufs(socket_st *sock, int alloc)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int rcvbuf, hold;
|
|
Packit Service |
6f2e62 |
socklen_t tmplen = sizeof(hold);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (!sndbuf)
|
|
Packit Service |
6f2e62 |
sndbuf = alloc;
|
|
Packit Service |
6f2e62 |
setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, sizeof(sndbuf));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
rcvbuf = hold = alloc * preload;
|
|
Packit Service |
6f2e62 |
if (hold < 65536)
|
|
Packit Service |
6f2e62 |
hold = 65536;
|
|
Packit Service |
6f2e62 |
setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
|
|
Packit Service |
6f2e62 |
if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, (char *)&hold, &tmplen) == 0) {
|
|
Packit Service |
6f2e62 |
if (hold < rcvbuf)
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "WARNING: probably, rcvbuf is not enough to hold preload.\n");
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Protocol independent setup and parameter checks. */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void setup(socket_st *sock)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int hold;
|
|
Packit Service |
6f2e62 |
struct timeval tv;
|
|
Packit Service |
6f2e62 |
sigset_t sset;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if ((options & F_FLOOD) && !(options & F_INTERVAL))
|
|
Packit Service |
6f2e62 |
interval = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (uid && interval < MINUSERINTERVAL) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "ping: cannot flood; minimal interval allowed for user is %dms\n", MINUSERINTERVAL);
|
|
Packit Service |
6f2e62 |
exit(2);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (interval >= INT_MAX/preload) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "ping: illegal preload and/or interval\n");
|
|
Packit Service |
6f2e62 |
exit(2);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
hold = 1;
|
|
Packit Service |
6f2e62 |
if (options & F_SO_DEBUG)
|
|
Packit Service |
6f2e62 |
setsockopt(sock->fd, SOL_SOCKET, SO_DEBUG, (char *)&hold, sizeof(hold));
|
|
Packit Service |
6f2e62 |
if (options & F_SO_DONTROUTE)
|
|
Packit Service |
6f2e62 |
setsockopt(sock->fd, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, sizeof(hold));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef SO_TIMESTAMP
|
|
Packit Service |
6f2e62 |
if (!(options&F_LATENCY)) {
|
|
Packit Service |
6f2e62 |
int on = 1;
|
|
Packit Service |
6f2e62 |
if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
#ifdef SO_MARK
|
|
Packit Service |
6f2e62 |
if (options & F_MARK) {
|
|
Packit Service |
6f2e62 |
int ret;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
enable_capability_admin();
|
|
Packit Service |
6f2e62 |
ret = setsockopt(sock->fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
|
|
Packit Service |
6f2e62 |
disable_capability_admin();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (ret == -1) {
|
|
Packit Service |
6f2e62 |
/* we probably dont wanna exit since old kernels
|
|
Packit Service |
6f2e62 |
* dont support mark ..
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Warning: Failed to set mark %d\n", mark);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Set some SNDTIMEO to prevent blocking forever
|
|
Packit Service |
6f2e62 |
* on sends, when device is too slow or stalls. Just put limit
|
|
Packit Service |
6f2e62 |
* of one second, or "interval", if it is less.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
tv.tv_sec = 1;
|
|
Packit Service |
6f2e62 |
tv.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
if (interval < 1000) {
|
|
Packit Service |
6f2e62 |
tv.tv_sec = 0;
|
|
Packit Service |
6f2e62 |
tv.tv_usec = 1000 * SCHINT(interval);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Set RCVTIMEO to "interval". Note, it is just an optimization
|
|
Packit Service |
6f2e62 |
* allowing to avoid redundant poll(). */
|
|
Packit Service |
6f2e62 |
tv.tv_sec = SCHINT(interval)/1000;
|
|
Packit Service |
6f2e62 |
tv.tv_usec = 1000*(SCHINT(interval)%1000);
|
|
Packit Service |
6f2e62 |
if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)))
|
|
Packit Service |
6f2e62 |
options |= F_FLOOD_POLL;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (!(options & F_PINGFILLED)) {
|
|
Packit Service |
6f2e62 |
int i;
|
|
Packit Service |
6f2e62 |
unsigned char *p = outpack+8;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Do not forget about case of small datalen,
|
|
Packit Service |
6f2e62 |
* fill timestamp area too!
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
for (i = 0; i < datalen; ++i)
|
|
Packit Service |
6f2e62 |
*p++ = i;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (sock->socktype == SOCK_RAW)
|
|
Packit Service |
6f2e62 |
ident = htons(getpid() & 0xFFFF);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
set_signal(SIGINT, sigexit);
|
|
Packit Service |
6f2e62 |
set_signal(SIGALRM, sigexit);
|
|
Packit Service |
6f2e62 |
set_signal(SIGQUIT, sigstatus);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
sigemptyset(&sset);
|
|
Packit Service |
6f2e62 |
sigprocmask(SIG_SETMASK, &sset, NULL);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
gettimeofday(&start_time, NULL);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (deadline) {
|
|
Packit Service |
6f2e62 |
struct itimerval it;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
it.it_interval.tv_sec = 0;
|
|
Packit Service |
6f2e62 |
it.it_interval.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
it.it_value.tv_sec = deadline;
|
|
Packit Service |
6f2e62 |
it.it_value.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
setitimer(ITIMER_REAL, &it, NULL);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (isatty(STDOUT_FILENO)) {
|
|
Packit Service |
6f2e62 |
struct winsize w;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
|
|
Packit Service |
6f2e62 |
if (w.ws_col > 0)
|
|
Packit Service |
6f2e62 |
screen_width = w.ws_col;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Return 0 if pattern in payload point to be ptr did not match the pattern that was sent
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
int contains_pattern_in_payload(__u8 *ptr)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int i;
|
|
Packit Service |
6f2e62 |
__u8 *cp, *dp;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* check the data */
|
|
Packit Service |
6f2e62 |
cp = ((u_char*)ptr) + sizeof(struct timeval);
|
|
Packit Service |
6f2e62 |
dp = &outpack[8 + sizeof(struct timeval)];
|
|
Packit Service |
6f2e62 |
for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
|
|
Packit Service |
6f2e62 |
if (*cp != *dp)
|
|
Packit Service |
6f2e62 |
return 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
return 1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void main_loop(ping_func_set_st *fset, socket_st *sock, __u8 *packet, int packlen)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
char addrbuf[128];
|
|
Packit Service |
6f2e62 |
char ans_data[4096];
|
|
Packit Service |
6f2e62 |
struct iovec iov;
|
|
Packit Service |
6f2e62 |
struct msghdr msg;
|
|
Packit Service |
6f2e62 |
struct cmsghdr *c;
|
|
Packit Service |
6f2e62 |
int cc;
|
|
Packit Service |
6f2e62 |
int next;
|
|
Packit Service |
6f2e62 |
int polling;
|
|
Packit Service |
6f2e62 |
int recv_error;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
iov.iov_base = (char *)packet;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (;;) {
|
|
Packit Service |
6f2e62 |
/* Check exit conditions. */
|
|
Packit Service |
6f2e62 |
if (exiting)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
if (npackets && nreceived + nerrors >= npackets)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
if (deadline && nerrors)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
/* Check for and do special actions. */
|
|
Packit Service |
6f2e62 |
if (status_snapshot)
|
|
Packit Service |
6f2e62 |
status();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Send probes scheduled to this time. */
|
|
Packit Service |
6f2e62 |
do {
|
|
Packit Service |
6f2e62 |
next = pinger(fset, sock);
|
|
Packit Service |
6f2e62 |
next = schedule_exit(next);
|
|
Packit Service |
6f2e62 |
} while (next <= 0);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* "next" is time to send next probe, if positive.
|
|
Packit Service |
6f2e62 |
* If next<=0 send now or as soon as possible. */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Technical part. Looks wicked. Could be dropped,
|
|
Packit Service |
6f2e62 |
* if everyone used the newest kernel. :-)
|
|
Packit Service |
6f2e62 |
* Its purpose is:
|
|
Packit Service |
6f2e62 |
* 1. Provide intervals less than resolution of scheduler.
|
|
Packit Service |
6f2e62 |
* Solution: spinning.
|
|
Packit Service |
6f2e62 |
* 2. Avoid use of poll(), when recvmsg() can provide
|
|
Packit Service |
6f2e62 |
* timed waiting (SO_RCVTIMEO). */
|
|
Packit Service |
6f2e62 |
polling = 0;
|
|
Packit Service |
6f2e62 |
recv_error = 0;
|
|
Packit Service |
6f2e62 |
if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next
|
|
Packit Service |
6f2e62 |
int recv_expected = in_flight();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* If we are here, recvmsg() is unable to wait for
|
|
Packit Service |
6f2e62 |
* required timeout. */
|
|
Packit Service |
6f2e62 |
if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
|
|
Packit Service |
6f2e62 |
/* Very short timeout... So, if we wait for
|
|
Packit Service |
6f2e62 |
* something, we sleep for MININTERVAL.
|
|
Packit Service |
6f2e62 |
* Otherwise, spin! */
|
|
Packit Service |
6f2e62 |
if (recv_expected) {
|
|
Packit Service |
6f2e62 |
next = MININTERVAL;
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
next = 0;
|
|
Packit Service |
6f2e62 |
/* When spinning, no reasons to poll.
|
|
Packit Service |
6f2e62 |
* Use nonblocking recvmsg() instead. */
|
|
Packit Service |
6f2e62 |
polling = MSG_DONTWAIT;
|
|
Packit Service |
6f2e62 |
/* But yield yet. */
|
|
Packit Service |
6f2e62 |
sched_yield();
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (!polling &&
|
|
Packit Service |
6f2e62 |
((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
|
|
Packit Service |
6f2e62 |
struct pollfd pset;
|
|
Packit Service |
6f2e62 |
pset.fd = sock->fd;
|
|
Packit Service |
6f2e62 |
pset.events = POLLIN;
|
|
Packit Service |
6f2e62 |
pset.revents = 0;
|
|
Packit Service |
6f2e62 |
if (poll(&pset, 1, next) < 1 ||
|
|
Packit Service |
6f2e62 |
!(pset.revents&(POLLIN|POLLERR)))
|
|
Packit Service |
6f2e62 |
continue;
|
|
Packit Service |
6f2e62 |
polling = MSG_DONTWAIT;
|
|
Packit Service |
6f2e62 |
recv_error = pset.revents&POLLERR;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (;;) {
|
|
Packit Service |
6f2e62 |
struct timeval *recv_timep = NULL;
|
|
Packit Service |
6f2e62 |
struct timeval recv_time;
|
|
Packit Service |
6f2e62 |
int not_ours = 0; /* Raw socket can receive messages
|
|
Packit Service |
6f2e62 |
* destined to other running pings. */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
iov.iov_len = packlen;
|
|
Packit Service |
6f2e62 |
memset(&msg, 0, sizeof(msg));
|
|
Packit Service |
6f2e62 |
msg.msg_name = addrbuf;
|
|
Packit Service |
6f2e62 |
msg.msg_namelen = sizeof(addrbuf);
|
|
Packit Service |
6f2e62 |
msg.msg_iov = &iov;
|
|
Packit Service |
6f2e62 |
msg.msg_iovlen = 1;
|
|
Packit Service |
6f2e62 |
msg.msg_control = ans_data;
|
|
Packit Service |
6f2e62 |
msg.msg_controllen = sizeof(ans_data);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
cc = recvmsg(sock->fd, &msg, polling);
|
|
Packit Service |
6f2e62 |
polling = MSG_DONTWAIT;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cc < 0) {
|
|
Packit Service |
6f2e62 |
/* If there was a POLLERR and there is no packet
|
|
Packit Service |
6f2e62 |
* on the socket, try to read the error queue.
|
|
Packit Service |
6f2e62 |
* Otherwise, give up.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if ((errno == EAGAIN && !recv_error) ||
|
|
Packit Service |
6f2e62 |
errno == EINTR)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
recv_error = 0;
|
|
Packit Service |
6f2e62 |
if (!fset->receive_error_msg(sock)) {
|
|
Packit Service |
6f2e62 |
if (errno) {
|
|
Packit Service |
6f2e62 |
perror("ping: recvmsg");
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
not_ours = 1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#ifdef SO_TIMESTAMP
|
|
Packit Service |
6f2e62 |
for (c = CMSG_FIRSTHDR(&msg;; c; c = CMSG_NXTHDR(&msg, c)) {
|
|
Packit Service |
6f2e62 |
if (c->cmsg_level != SOL_SOCKET ||
|
|
Packit Service |
6f2e62 |
c->cmsg_type != SO_TIMESTAMP)
|
|
Packit Service |
6f2e62 |
continue;
|
|
Packit Service |
6f2e62 |
if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
|
|
Packit Service |
6f2e62 |
continue;
|
|
Packit Service |
6f2e62 |
recv_timep = (struct timeval*)CMSG_DATA(c);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if ((options&F_LATENCY) || recv_timep == NULL) {
|
|
Packit Service |
6f2e62 |
if ((options&F_LATENCY) ||
|
|
Packit Service |
6f2e62 |
ioctl(sock->fd, SIOCGSTAMP, &recv_time))
|
|
Packit Service |
6f2e62 |
gettimeofday(&recv_time, NULL);
|
|
Packit Service |
6f2e62 |
recv_timep = &recv_time;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
not_ours = fset->parse_reply(sock, &msg, cc, addrbuf, recv_timep);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* See? ... someone runs another ping on this host. */
|
|
Packit Service |
6f2e62 |
if (not_ours && sock->socktype == SOCK_RAW)
|
|
Packit Service |
6f2e62 |
fset->install_filter(sock);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* If nothing is in flight, "break" returns us to pinger. */
|
|
Packit Service |
6f2e62 |
if (in_flight() == 0)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* Otherwise, try to recvmsg() again. recvmsg()
|
|
Packit Service |
6f2e62 |
* is nonblocking after the first iteration, so that
|
|
Packit Service |
6f2e62 |
* if nothing is queued, it will receive EAGAIN
|
|
Packit Service |
6f2e62 |
* and return to pinger. */
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
finish();
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int gather_statistics(__u8 *icmph, int icmplen,
|
|
Packit Service |
6f2e62 |
int cc, __u16 seq, int hops,
|
|
Packit Service |
6f2e62 |
int csfailed, struct timeval *tv, char *from,
|
|
Packit Service |
6f2e62 |
void (*pr_reply)(__u8 *icmph, int cc))
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int dupflag = 0;
|
|
Packit Service |
6f2e62 |
long triptime = 0;
|
|
Packit Service |
6f2e62 |
__u8 *ptr = icmph + icmplen;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
++nreceived;
|
|
Packit Service |
6f2e62 |
if (!csfailed)
|
|
Packit Service |
6f2e62 |
acknowledge(seq);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (timing && cc >= 8+sizeof(struct timeval)) {
|
|
Packit Service |
6f2e62 |
struct timeval tmp_tv;
|
|
Packit Service |
6f2e62 |
memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
restamp:
|
|
Packit Service |
6f2e62 |
tvsub(tv, &tmp_tv);
|
|
Packit Service |
6f2e62 |
triptime = tv->tv_sec * 1000000 + tv->tv_usec;
|
|
Packit Service |
6f2e62 |
if (triptime < 0) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Warning: time of day goes back (%ldus), taking countermeasures.\n", triptime);
|
|
Packit Service |
6f2e62 |
triptime = 0;
|
|
Packit Service |
6f2e62 |
if (!(options & F_LATENCY)) {
|
|
Packit Service |
6f2e62 |
gettimeofday(tv, NULL);
|
|
Packit Service |
6f2e62 |
options |= F_LATENCY;
|
|
Packit Service |
6f2e62 |
goto restamp;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (!csfailed) {
|
|
Packit Service |
6f2e62 |
tsum += triptime;
|
|
Packit Service |
6f2e62 |
tsum2 += (long long)triptime * (long long)triptime;
|
|
Packit Service |
6f2e62 |
if (triptime < tmin)
|
|
Packit Service |
6f2e62 |
tmin = triptime;
|
|
Packit Service |
6f2e62 |
if (triptime > tmax)
|
|
Packit Service |
6f2e62 |
tmax = triptime;
|
|
Packit Service |
6f2e62 |
if (!rtt)
|
|
Packit Service |
6f2e62 |
rtt = triptime*8;
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
rtt += triptime-rtt/8;
|
|
Packit Service |
6f2e62 |
if (options&F_ADAPTIVE)
|
|
Packit Service |
6f2e62 |
update_interval();
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (csfailed) {
|
|
Packit Service |
6f2e62 |
++nchecksum;
|
|
Packit Service |
6f2e62 |
--nreceived;
|
|
Packit Service |
6f2e62 |
} else if (rcvd_test(seq)) {
|
|
Packit Service |
6f2e62 |
++nrepeats;
|
|
Packit Service |
6f2e62 |
--nreceived;
|
|
Packit Service |
6f2e62 |
dupflag = 1;
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
rcvd_set(seq);
|
|
Packit Service |
6f2e62 |
dupflag = 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
confirm = confirm_flag;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (options & F_QUIET)
|
|
Packit Service |
6f2e62 |
return 1;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (options & F_FLOOD) {
|
|
Packit Service |
6f2e62 |
if (!csfailed)
|
|
Packit Service |
6f2e62 |
write_stdout("\b \b", 3);
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
write_stdout("\bC", 2);
|
|
Packit Service |
6f2e62 |
} else {
|
|
Packit Service |
6f2e62 |
int i;
|
|
Packit Service |
6f2e62 |
__u8 *cp, *dp;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
print_timestamp();
|
|
Packit Service |
6f2e62 |
printf("%d bytes from %s:", cc, from);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (pr_reply)
|
|
Packit Service |
6f2e62 |
pr_reply(icmph, cc);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (hops >= 0)
|
|
Packit Service |
6f2e62 |
printf(" ttl=%d", hops);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cc < datalen+8) {
|
|
Packit Service |
6f2e62 |
printf(" (truncated)\n");
|
|
Packit Service |
6f2e62 |
return 1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (timing) {
|
|
Packit Service |
6f2e62 |
if (triptime >= 100000)
|
|
Packit Service |
6f2e62 |
printf(" time=%ld ms", (triptime+500)/1000);
|
|
Packit Service |
6f2e62 |
else if (triptime >= 10000)
|
|
Packit Service |
6f2e62 |
printf(" time=%ld.%01ld ms", triptime/1000,
|
|
Packit Service |
6f2e62 |
((triptime%1000)+50)/100);
|
|
Packit Service |
6f2e62 |
else if (triptime >= 1000)
|
|
Packit Service |
6f2e62 |
printf(" time=%ld.%02ld ms", triptime/1000,
|
|
Packit Service |
6f2e62 |
((triptime%1000)+5)/10);
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
printf(" time=%ld.%03ld ms", triptime/1000,
|
|
Packit Service |
6f2e62 |
triptime%1000);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (dupflag)
|
|
Packit Service |
6f2e62 |
printf(" (DUP!)");
|
|
Packit Service |
6f2e62 |
if (csfailed)
|
|
Packit Service |
6f2e62 |
printf(" (BAD CHECKSUM!)");
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* check the data */
|
|
Packit Service |
6f2e62 |
cp = ((unsigned char*)ptr) + sizeof(struct timeval);
|
|
Packit Service |
6f2e62 |
dp = &outpack[8 + sizeof(struct timeval)];
|
|
Packit Service |
6f2e62 |
for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
|
|
Packit Service |
6f2e62 |
if (*cp != *dp) {
|
|
Packit Service |
6f2e62 |
printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
|
|
Packit Service |
6f2e62 |
i, *dp, *cp);
|
|
Packit Service |
6f2e62 |
cp = (unsigned char*)ptr + sizeof(struct timeval);
|
|
Packit Service |
6f2e62 |
for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
|
|
Packit Service |
6f2e62 |
if ((i % 32) == sizeof(struct timeval))
|
|
Packit Service |
6f2e62 |
printf("\n#%d\t", i);
|
|
Packit Service |
6f2e62 |
printf("%x ", *cp);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
return 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
static long llsqrt(long long a)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
long long prev = ~((long long)1 << 63);
|
|
Packit Service |
6f2e62 |
long long x = a;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (x > 0) {
|
|
Packit Service |
6f2e62 |
while (x < prev) {
|
|
Packit Service |
6f2e62 |
prev = x;
|
|
Packit Service |
6f2e62 |
x = (x+(a/x))/2;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
return (long)x;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* finish --
|
|
Packit Service |
6f2e62 |
* Print out statistics, and give up.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
void finish(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
struct timeval tv = cur_time;
|
|
Packit Service |
6f2e62 |
char *comma = "";
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
tvsub(&tv, &start_time);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
putchar('\n');
|
|
Packit Service |
6f2e62 |
fflush(stdout);
|
|
Packit Service |
6f2e62 |
printf("--- %s ping statistics ---\n", hostname);
|
|
Packit Service |
6f2e62 |
printf("%ld packets transmitted, ", ntransmitted);
|
|
Packit Service |
6f2e62 |
printf("%ld received", nreceived);
|
|
Packit Service |
6f2e62 |
if (nrepeats)
|
|
Packit Service |
6f2e62 |
printf(", +%ld duplicates", nrepeats);
|
|
Packit Service |
6f2e62 |
if (nchecksum)
|
|
Packit Service |
6f2e62 |
printf(", +%ld corrupted", nchecksum);
|
|
Packit Service |
6f2e62 |
if (nerrors)
|
|
Packit Service |
6f2e62 |
printf(", +%ld errors", nerrors);
|
|
Packit Service |
6f2e62 |
if (ntransmitted) {
|
|
Packit Service |
6f2e62 |
#ifdef USE_IDN
|
|
Packit Service |
6f2e62 |
setlocale(LC_ALL, "C");
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
printf(", %g%% packet loss",
|
|
Packit Service |
6f2e62 |
(float) ((((long long)(ntransmitted - nreceived)) * 100.0) /
|
|
Packit Service |
6f2e62 |
ntransmitted));
|
|
Packit Service |
f4d28a |
printf(", time %ldms", 1000*tv.tv_sec+(tv.tv_usec+500)/1000);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
putchar('\n');
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (nreceived && timing) {
|
|
Packit Service |
6f2e62 |
long tmdev;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
tsum /= nreceived + nrepeats;
|
|
Packit Service |
6f2e62 |
tsum2 /= nreceived + nrepeats;
|
|
Packit Service |
6f2e62 |
tmdev = llsqrt(tsum2 - tsum * tsum);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
printf("rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms",
|
|
Packit Service |
6f2e62 |
(long)tmin/1000, (long)tmin%1000,
|
|
Packit Service |
6f2e62 |
(unsigned long)(tsum/1000), (long)(tsum%1000),
|
|
Packit Service |
6f2e62 |
(long)tmax/1000, (long)tmax%1000,
|
|
Packit Service |
6f2e62 |
(long)tmdev/1000, (long)tmdev%1000
|
|
Packit Service |
6f2e62 |
);
|
|
Packit Service |
6f2e62 |
comma = ", ";
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (pipesize > 1) {
|
|
Packit Service |
6f2e62 |
printf("%spipe %d", comma, pipesize);
|
|
Packit Service |
6f2e62 |
comma = ", ";
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (nreceived && (!interval || (options&(F_FLOOD|F_ADAPTIVE))) && ntransmitted > 1) {
|
|
Packit Service |
6f2e62 |
int ipg = (1000000*(long long)tv.tv_sec+tv.tv_usec)/(ntransmitted-1);
|
|
Packit Service |
6f2e62 |
printf("%sipg/ewma %d.%03d/%d.%03d ms",
|
|
Packit Service |
6f2e62 |
comma, ipg/1000, ipg%1000, rtt/8000, (rtt/8)%1000);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
putchar('\n');
|
|
Packit Service |
6f2e62 |
exit(!nreceived || (deadline && nreceived < npackets));
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void status(void)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int loss = 0;
|
|
Packit Service |
6f2e62 |
long tavg = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
status_snapshot = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (ntransmitted)
|
|
Packit Service |
6f2e62 |
loss = (((long long)(ntransmitted - nreceived)) * 100) / ntransmitted;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "\r%ld/%ld packets, %d%% loss", nreceived, ntransmitted, loss);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (nreceived && timing) {
|
|
Packit Service |
6f2e62 |
tavg = tsum / (nreceived + nrepeats);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
fprintf(stderr, ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms",
|
|
Packit Service |
6f2e62 |
(long)tmin/1000, (long)tmin%1000,
|
|
Packit Service |
6f2e62 |
tavg/1000, tavg%1000,
|
|
Packit Service |
6f2e62 |
rtt/8000, (rtt/8)%1000,
|
|
Packit Service |
6f2e62 |
(long)tmax/1000, (long)tmax%1000
|
|
Packit Service |
6f2e62 |
);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "\n");
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
inline int is_ours(socket_st *sock, uint16_t id) {
|
|
Packit Service |
6f2e62 |
return sock->socktype == SOCK_DGRAM || id == ident;
|
|
Packit Service |
6f2e62 |
}
|