|
Packit Service |
6f2e62 |
/*-
|
|
Packit Service |
6f2e62 |
* Copyright (c) 1985, 1993
|
|
Packit Service |
6f2e62 |
* The Regents of the University of California. All rights reserved.
|
|
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 <time.h>
|
|
Packit Service |
6f2e62 |
#include <sys/types.h>
|
|
Packit Service |
6f2e62 |
#include <sys/param.h>
|
|
Packit Service |
6f2e62 |
#include <stdio.h>
|
|
Packit Service |
6f2e62 |
#include <unistd.h>
|
|
Packit Service |
6f2e62 |
#include <stdlib.h>
|
|
Packit Service |
6f2e62 |
#include <math.h>
|
|
Packit Service |
6f2e62 |
#include <string.h>
|
|
Packit Service |
6f2e62 |
#include <sys/time.h>
|
|
Packit Service |
6f2e62 |
#include <sys/timex.h>
|
|
Packit Service |
6f2e62 |
#include <errno.h>
|
|
Packit Service |
6f2e62 |
#include <sys/socket.h>
|
|
Packit Service |
6f2e62 |
#include <netinet/in.h>
|
|
Packit Service |
6f2e62 |
#include <netinet/ip.h>
|
|
Packit Service |
6f2e62 |
#include <netinet/ip_icmp.h>
|
|
Packit Service |
6f2e62 |
#define TSPTYPES
|
|
Packit Service |
6f2e62 |
#include <fcntl.h>
|
|
Packit Service |
6f2e62 |
#include <netdb.h>
|
|
Packit Service |
6f2e62 |
#include <arpa/inet.h>
|
|
Packit Service |
6f2e62 |
#include <errno.h>
|
|
Packit Service |
6f2e62 |
#include <linux/types.h>
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
#include <sys/capability.h>
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void usage(void) __attribute__((noreturn));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define MAX_HOSTNAMELEN NI_MAXHOST
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Checksum routine for Internet Protocol family headers.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* This routine is very heavily used in the network
|
|
Packit Service |
6f2e62 |
* code and should be modified for each CPU to be as fast as possible.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* This implementation is TAHOE version.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#undef ADDCARRY
|
|
Packit Service |
6f2e62 |
#define ADDCARRY(sum) { \
|
|
Packit Service |
6f2e62 |
if (sum & 0xffff0000) { \
|
|
Packit Service |
6f2e62 |
sum &= 0xffff; \
|
|
Packit Service |
6f2e62 |
sum++; \
|
|
Packit Service |
6f2e62 |
} \
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int in_cksum(unsigned short *addr, int len)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
union word {
|
|
Packit Service |
6f2e62 |
char c[2];
|
|
Packit Service |
6f2e62 |
unsigned short s;
|
|
Packit Service |
6f2e62 |
} u;
|
|
Packit Service |
6f2e62 |
int sum = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
while (len > 0) {
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* add by words.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
while ((len -= 2) >= 0) {
|
|
Packit Service |
6f2e62 |
if ((unsigned long)addr & 0x1) {
|
|
Packit Service |
6f2e62 |
/* word is not aligned */
|
|
Packit Service |
6f2e62 |
u.c[0] = *(char *)addr;
|
|
Packit Service |
6f2e62 |
u.c[1] = *((char *)addr+1);
|
|
Packit Service |
6f2e62 |
sum += u.s;
|
|
Packit Service |
6f2e62 |
addr++;
|
|
Packit Service |
6f2e62 |
} else
|
|
Packit Service |
6f2e62 |
sum += *addr++;
|
|
Packit Service |
6f2e62 |
ADDCARRY(sum);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (len == -1)
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Odd number of bytes.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
u.c[0] = *(unsigned char *)addr;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (len == -1) {
|
|
Packit Service |
6f2e62 |
/* The last mbuf has odd # of bytes. Follow the
|
|
Packit Service |
6f2e62 |
standard (the odd byte is shifted left by 8 bits) */
|
|
Packit Service |
6f2e62 |
u.c[1] = 0;
|
|
Packit Service |
6f2e62 |
sum += u.s;
|
|
Packit Service |
6f2e62 |
ADDCARRY(sum);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
return (~sum & 0xffff);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define ON 1
|
|
Packit Service |
6f2e62 |
#define OFF 0
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define RANGE 1 /* best expected round-trip time, ms */
|
|
Packit Service |
6f2e62 |
#define MSGS 50
|
|
Packit Service |
6f2e62 |
#define TRIALS 10
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define GOOD 0
|
|
Packit Service |
6f2e62 |
#define UNREACHABLE 2
|
|
Packit Service |
6f2e62 |
#define NONSTDTIME 3
|
|
Packit Service |
6f2e62 |
#define HOSTDOWN 0x7fffffff
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int interactive = 0;
|
|
Packit Service |
6f2e62 |
uint16_t id;
|
|
Packit Service |
6f2e62 |
int sock;
|
|
Packit Service |
6f2e62 |
int sock_raw;
|
|
Packit Service |
6f2e62 |
struct sockaddr_in server;
|
|
Packit Service |
6f2e62 |
int ip_opt_len = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define BIASP 43199999
|
|
Packit Service |
6f2e62 |
#define BIASN -43200000
|
|
Packit Service |
6f2e62 |
#define MODULO 86400000
|
|
Packit Service |
6f2e62 |
#define PROCESSING_TIME 0 /* ms. to reduce error in measurement */
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
#define PACKET_IN 1024
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int measure_delta;
|
|
Packit Service |
6f2e62 |
int measure_delta1;
|
|
Packit Service |
6f2e62 |
static unsigned short seqno, seqno0, acked;
|
|
Packit Service |
6f2e62 |
long rtt = 1000;
|
|
Packit Service |
6f2e62 |
long min_rtt;
|
|
Packit Service |
6f2e62 |
long rtt_sigma = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Measures the differences between machines' clocks using
|
|
Packit Service |
6f2e62 |
* ICMP timestamp messages.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
int
|
|
Packit Service |
6f2e62 |
measure(struct sockaddr_in * addr)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
socklen_t length;
|
|
Packit Service |
6f2e62 |
int msgcount;
|
|
Packit Service |
6f2e62 |
int cc, count;
|
|
Packit Service |
6f2e62 |
fd_set ready;
|
|
Packit Service |
6f2e62 |
long sendtime, recvtime, histime;
|
|
Packit Service |
6f2e62 |
long min1, min2, diff;
|
|
Packit Service |
6f2e62 |
long delta1, delta2;
|
|
Packit Service |
6f2e62 |
struct timeval tv1, tout;
|
|
Packit Service |
6f2e62 |
unsigned char packet[PACKET_IN], opacket[64];
|
|
Packit Service |
6f2e62 |
struct icmphdr *icp;
|
|
Packit Service |
6f2e62 |
struct icmphdr *oicp = (struct icmphdr *) opacket;
|
|
Packit Service |
6f2e62 |
struct iphdr *ip = (struct iphdr *) packet;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
min1 = min2 = 0x7fffffff;
|
|
Packit Service |
6f2e62 |
min_rtt = 0x7fffffff;
|
|
Packit Service |
6f2e62 |
measure_delta = HOSTDOWN;
|
|
Packit Service |
6f2e62 |
measure_delta1 = HOSTDOWN;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* empties the icmp input queue */
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
empty:
|
|
Packit Service |
6f2e62 |
tout.tv_sec = tout.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
FD_SET(sock_raw, &ready);
|
|
Packit Service |
6f2e62 |
if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
|
|
Packit Service |
6f2e62 |
length = sizeof(struct sockaddr_in);
|
|
Packit Service |
6f2e62 |
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)NULL, &length);
|
|
Packit Service |
6f2e62 |
if (cc < 0)
|
|
Packit Service |
6f2e62 |
return -1;
|
|
Packit Service |
6f2e62 |
goto empty;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* To measure the difference, select MSGS messages whose round-trip
|
|
Packit Service |
6f2e62 |
* time is smaller than RANGE if ckrange is 1, otherwise simply
|
|
Packit Service |
6f2e62 |
* select MSGS messages regardless of round-trip transmission time.
|
|
Packit Service |
6f2e62 |
* Choose the smallest transmission time in each of the two directions.
|
|
Packit Service |
6f2e62 |
* Use these two latter quantities to compute the delta between
|
|
Packit Service |
6f2e62 |
* the two clocks.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
length = sizeof(struct sockaddr_in);
|
|
Packit Service |
6f2e62 |
oicp->type = ICMP_TIMESTAMP;
|
|
Packit Service |
6f2e62 |
oicp->code = 0;
|
|
Packit Service |
6f2e62 |
oicp->checksum = 0;
|
|
Packit Service |
6f2e62 |
oicp->un.echo.id = id;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[0] = 0;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[1] = 0;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[2] = 0;
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
acked = seqno = seqno0 = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (msgcount = 0; msgcount < MSGS; ) {
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* If no answer is received for TRIALS consecutive times,
|
|
Packit Service |
6f2e62 |
* the machine is assumed to be down
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if (seqno - acked > TRIALS)
|
|
Packit Service |
6f2e62 |
return HOSTDOWN;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
oicp->un.echo.sequence = ++seqno;
|
|
Packit Service |
6f2e62 |
oicp->checksum = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
(void)gettimeofday (&tv1, (struct timezone *)0);
|
|
Packit Service |
6f2e62 |
*(__u32*)(oicp+1) = htonl((tv1.tv_sec % (24*60*60)) * 1000
|
|
Packit Service |
6f2e62 |
+ tv1.tv_usec / 1000);
|
|
Packit Service |
6f2e62 |
oicp->checksum = in_cksum((unsigned short *)oicp, sizeof(*oicp) + 12);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
count = sendto(sock_raw, (char *)opacket, sizeof(*oicp)+12, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (count < 0)
|
|
Packit Service |
6f2e62 |
return UNREACHABLE;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (;;) {
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
FD_SET(sock_raw, &ready);
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
long tmo = rtt + rtt_sigma;
|
|
Packit Service |
6f2e62 |
tout.tv_sec = tmo/1000;
|
|
Packit Service |
6f2e62 |
tout.tv_usec = (tmo - (tmo/1000)*1000)*1000;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
|
|
Packit Service |
6f2e62 |
(fd_set *)0, &tout)) <= 0)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
(void)gettimeofday(&tv1, (struct timezone *)0);
|
|
Packit Service |
6f2e62 |
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)NULL, &length);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cc < 0)
|
|
Packit Service |
6f2e62 |
return(-1);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
icp = (struct icmphdr *)(packet + (ip->ihl << 2));
|
|
Packit Service |
6f2e62 |
if( icp->type == ICMP_TIMESTAMPREPLY &&
|
|
Packit Service |
6f2e62 |
icp->un.echo.id == id && icp->un.echo.sequence >= seqno0 &&
|
|
Packit Service |
6f2e62 |
icp->un.echo.sequence <= seqno) {
|
|
Packit Service |
6f2e62 |
if (acked < icp->un.echo.sequence)
|
|
Packit Service |
6f2e62 |
acked = icp->un.echo.sequence;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
recvtime = (tv1.tv_sec % (24*60*60)) * 1000 +
|
|
Packit Service |
6f2e62 |
tv1.tv_usec / 1000;
|
|
Packit Service |
6f2e62 |
sendtime = ntohl(*(__u32*)(icp+1));
|
|
Packit Service |
6f2e62 |
diff = recvtime - sendtime;
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* diff can be less than 0 aroud midnight
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if (diff < 0)
|
|
Packit Service |
6f2e62 |
continue;
|
|
Packit Service |
6f2e62 |
rtt = (rtt * 3 + diff)/4;
|
|
Packit Service |
6f2e62 |
rtt_sigma = (rtt_sigma *3 + abs(diff-rtt))/4;
|
|
Packit Service |
6f2e62 |
msgcount++;
|
|
Packit Service |
6f2e62 |
histime = ntohl(((__u32*)(icp+1))[1]);
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* a hosts using a time format different from
|
|
Packit Service |
6f2e62 |
* ms. since midnight UT (as per RFC792) should
|
|
Packit Service |
6f2e62 |
* set the high order bit of the 32-bit time
|
|
Packit Service |
6f2e62 |
* value it transmits.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if ((histime & 0x80000000) != 0)
|
|
Packit Service |
6f2e62 |
return NONSTDTIME;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (interactive) {
|
|
Packit Service |
6f2e62 |
printf(".");
|
|
Packit Service |
6f2e62 |
fflush(stdout);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
delta1 = histime - sendtime;
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Handles wrap-around to avoid that around
|
|
Packit Service |
6f2e62 |
* midnight small time differences appear
|
|
Packit Service |
6f2e62 |
* enormous. However, the two machine's clocks
|
|
Packit Service |
6f2e62 |
* must be within 12 hours from each other.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if (delta1 < BIASN)
|
|
Packit Service |
6f2e62 |
delta1 += MODULO;
|
|
Packit Service |
6f2e62 |
else if (delta1 > BIASP)
|
|
Packit Service |
6f2e62 |
delta1 -= MODULO;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
delta2 = recvtime - histime;
|
|
Packit Service |
6f2e62 |
if (delta2 < BIASN)
|
|
Packit Service |
6f2e62 |
delta2 += MODULO;
|
|
Packit Service |
6f2e62 |
else if (delta2 > BIASP)
|
|
Packit Service |
6f2e62 |
delta2 -= MODULO;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (delta1 < min1)
|
|
Packit Service |
6f2e62 |
min1 = delta1;
|
|
Packit Service |
6f2e62 |
if (delta2 < min2)
|
|
Packit Service |
6f2e62 |
min2 = delta2;
|
|
Packit Service |
6f2e62 |
if (delta1 + delta2 < min_rtt) {
|
|
Packit Service |
6f2e62 |
min_rtt = delta1 + delta2;
|
|
Packit Service |
6f2e62 |
measure_delta1 = (delta1 - delta2)/2 + PROCESSING_TIME;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (diff < RANGE) {
|
|
Packit Service |
6f2e62 |
min1 = delta1;
|
|
Packit Service |
6f2e62 |
min2 = delta2;
|
|
Packit Service |
6f2e62 |
goto good_exit;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
good_exit:
|
|
Packit Service |
6f2e62 |
measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
|
|
Packit Service |
6f2e62 |
return GOOD;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
char *myname, *hisname;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int
|
|
Packit Service |
6f2e62 |
measure_opt(struct sockaddr_in * addr)
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
socklen_t length;
|
|
Packit Service |
6f2e62 |
int msgcount;
|
|
Packit Service |
6f2e62 |
int cc, count;
|
|
Packit Service |
6f2e62 |
fd_set ready;
|
|
Packit Service |
6f2e62 |
long sendtime, recvtime, histime, histime1;
|
|
Packit Service |
6f2e62 |
long min1, min2, diff;
|
|
Packit Service |
6f2e62 |
long delta1, delta2;
|
|
Packit Service |
6f2e62 |
struct timeval tv1, tout;
|
|
Packit Service |
6f2e62 |
unsigned char packet[PACKET_IN], opacket[64];
|
|
Packit Service |
6f2e62 |
struct icmphdr *icp;
|
|
Packit Service |
6f2e62 |
struct icmphdr *oicp = (struct icmphdr *) opacket;
|
|
Packit Service |
6f2e62 |
struct iphdr *ip = (struct iphdr *) packet;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
min1 = min2 = 0x7fffffff;
|
|
Packit Service |
6f2e62 |
min_rtt = 0x7fffffff;
|
|
Packit Service |
6f2e62 |
measure_delta = HOSTDOWN;
|
|
Packit Service |
6f2e62 |
measure_delta1 = HOSTDOWN;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/* empties the icmp input queue */
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
empty:
|
|
Packit Service |
6f2e62 |
tout.tv_sec = tout.tv_usec = 0;
|
|
Packit Service |
6f2e62 |
FD_SET(sock_raw, &ready);
|
|
Packit Service |
6f2e62 |
if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
|
|
Packit Service |
6f2e62 |
length = sizeof(struct sockaddr_in);
|
|
Packit Service |
6f2e62 |
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)NULL, &length);
|
|
Packit Service |
6f2e62 |
if (cc < 0)
|
|
Packit Service |
6f2e62 |
return -1;
|
|
Packit Service |
6f2e62 |
goto empty;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* To measure the difference, select MSGS messages whose round-trip
|
|
Packit Service |
6f2e62 |
* time is smaller than RANGE if ckrange is 1, otherwise simply
|
|
Packit Service |
6f2e62 |
* select MSGS messages regardless of round-trip transmission time.
|
|
Packit Service |
6f2e62 |
* Choose the smallest transmission time in each of the two directions.
|
|
Packit Service |
6f2e62 |
* Use these two latter quantities to compute the delta between
|
|
Packit Service |
6f2e62 |
* the two clocks.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
length = sizeof(struct sockaddr_in);
|
|
Packit Service |
6f2e62 |
oicp->type = ICMP_ECHO;
|
|
Packit Service |
6f2e62 |
oicp->code = 0;
|
|
Packit Service |
6f2e62 |
oicp->checksum = 0;
|
|
Packit Service |
6f2e62 |
oicp->un.echo.id = id;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[0] = 0;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[1] = 0;
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[2] = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
acked = seqno = seqno0 = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (msgcount = 0; msgcount < MSGS; ) {
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* If no answer is received for TRIALS consecutive times,
|
|
Packit Service |
6f2e62 |
* the machine is assumed to be down
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if ( seqno - acked > TRIALS) {
|
|
Packit Service |
6f2e62 |
errno = EHOSTDOWN;
|
|
Packit Service |
6f2e62 |
return HOSTDOWN;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
oicp->un.echo.sequence = ++seqno;
|
|
Packit Service |
6f2e62 |
oicp->checksum = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
gettimeofday (&tv1, NULL);
|
|
Packit Service |
6f2e62 |
((__u32*)(oicp+1))[0] = htonl((tv1.tv_sec % (24*60*60)) * 1000
|
|
Packit Service |
6f2e62 |
+ tv1.tv_usec / 1000);
|
|
Packit Service |
6f2e62 |
oicp->checksum = in_cksum((unsigned short *)oicp, sizeof(*oicp)+12);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
count = sendto(sock_raw, (char *)opacket, sizeof(*oicp)+12, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (count < 0) {
|
|
Packit Service |
6f2e62 |
errno = EHOSTUNREACH;
|
|
Packit Service |
6f2e62 |
return UNREACHABLE;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
for (;;) {
|
|
Packit Service |
6f2e62 |
FD_ZERO(&ready);
|
|
Packit Service |
6f2e62 |
FD_SET(sock_raw, &ready);
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
long tmo = rtt + rtt_sigma;
|
|
Packit Service |
6f2e62 |
tout.tv_sec = tmo/1000;
|
|
Packit Service |
6f2e62 |
tout.tv_usec = (tmo - (tmo/1000)*1000)*1000;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
|
|
Packit Service |
6f2e62 |
(fd_set *)0, &tout)) <= 0)
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
(void)gettimeofday(&tv1, (struct timezone *)0);
|
|
Packit Service |
6f2e62 |
cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
|
|
Packit Service |
6f2e62 |
(struct sockaddr *)NULL, &length);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (cc < 0)
|
|
Packit Service |
6f2e62 |
return(-1);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
icp = (struct icmphdr *)(packet + (ip->ihl << 2));
|
|
Packit Service |
6f2e62 |
if (icp->type == ICMP_ECHOREPLY &&
|
|
Packit Service |
6f2e62 |
packet[20] == IPOPT_TIMESTAMP &&
|
|
Packit Service |
6f2e62 |
icp->un.echo.id == id &&
|
|
Packit Service |
6f2e62 |
icp->un.echo.sequence >= seqno0 &&
|
|
Packit Service |
6f2e62 |
icp->un.echo.sequence <= seqno) {
|
|
Packit Service |
6f2e62 |
int i;
|
|
Packit Service |
6f2e62 |
__u8 *opt = packet+20;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (acked < icp->un.echo.sequence)
|
|
Packit Service |
6f2e62 |
acked = icp->un.echo.sequence;
|
|
Packit Service |
6f2e62 |
if ((opt[3]&0xF) != IPOPT_TS_PRESPEC) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Wrong timestamp %d\n", opt[3]&0xF);
|
|
Packit Service |
6f2e62 |
return NONSTDTIME;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (opt[3]>>4) {
|
|
Packit Service |
6f2e62 |
if ((opt[3]>>4) != 1 || ip_opt_len != 4+3*8)
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Overflow %d hops\n", opt[3]>>4);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
sendtime = recvtime = histime = histime1 = 0;
|
|
Packit Service |
6f2e62 |
for (i=0; i < (opt[2]-5)/8; i++) {
|
|
Packit Service |
6f2e62 |
__u32 *timep = (__u32*)(opt+4+i*8+4);
|
|
Packit Service |
6f2e62 |
__u32 t = ntohl(*timep);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (t & 0x80000000)
|
|
Packit Service |
6f2e62 |
return NONSTDTIME;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (i == 0)
|
|
Packit Service |
6f2e62 |
sendtime = t;
|
|
Packit Service |
6f2e62 |
if (i == 1)
|
|
Packit Service |
6f2e62 |
histime = histime1 = t;
|
|
Packit Service |
6f2e62 |
if (i == 2) {
|
|
Packit Service |
6f2e62 |
if (ip_opt_len == 4+4*8)
|
|
Packit Service |
6f2e62 |
histime1 = t;
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
recvtime = t;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (i == 3)
|
|
Packit Service |
6f2e62 |
recvtime = t;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (!(sendtime&histime&histime1&recvtime)) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "wrong timestamps\n");
|
|
Packit Service |
6f2e62 |
return -1;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
diff = recvtime - sendtime;
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* diff can be less than 0 aroud midnight
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if (diff < 0)
|
|
Packit Service |
6f2e62 |
continue;
|
|
Packit Service |
6f2e62 |
rtt = (rtt * 3 + diff)/4;
|
|
Packit Service |
6f2e62 |
rtt_sigma = (rtt_sigma *3 + abs(diff-rtt))/4;
|
|
Packit Service |
6f2e62 |
msgcount++;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (interactive) {
|
|
Packit Service |
6f2e62 |
printf(".");
|
|
Packit Service |
6f2e62 |
fflush(stdout);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
delta1 = histime - sendtime;
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Handles wrap-around to avoid that around
|
|
Packit Service |
6f2e62 |
* midnight small time differences appear
|
|
Packit Service |
6f2e62 |
* enormous. However, the two machine's clocks
|
|
Packit Service |
6f2e62 |
* must be within 12 hours from each other.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
if (delta1 < BIASN)
|
|
Packit Service |
6f2e62 |
delta1 += MODULO;
|
|
Packit Service |
6f2e62 |
else if (delta1 > BIASP)
|
|
Packit Service |
6f2e62 |
delta1 -= MODULO;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
delta2 = recvtime - histime1;
|
|
Packit Service |
6f2e62 |
if (delta2 < BIASN)
|
|
Packit Service |
6f2e62 |
delta2 += MODULO;
|
|
Packit Service |
6f2e62 |
else if (delta2 > BIASP)
|
|
Packit Service |
6f2e62 |
delta2 -= MODULO;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (delta1 < min1)
|
|
Packit Service |
6f2e62 |
min1 = delta1;
|
|
Packit Service |
6f2e62 |
if (delta2 < min2)
|
|
Packit Service |
6f2e62 |
min2 = delta2;
|
|
Packit Service |
6f2e62 |
if (delta1 + delta2 < min_rtt) {
|
|
Packit Service |
6f2e62 |
min_rtt = delta1 + delta2;
|
|
Packit Service |
6f2e62 |
measure_delta1 = (delta1 - delta2)/2 + PROCESSING_TIME;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (diff < RANGE) {
|
|
Packit Service |
6f2e62 |
min1 = delta1;
|
|
Packit Service |
6f2e62 |
min2 = delta2;
|
|
Packit Service |
6f2e62 |
goto good_exit;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
good_exit:
|
|
Packit Service |
6f2e62 |
measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
|
|
Packit Service |
6f2e62 |
return GOOD;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
/*
|
|
Packit Service |
6f2e62 |
* Clockdiff computes the difference between the time of the machine on
|
|
Packit Service |
6f2e62 |
* which it is called and the time of the machines given as argument.
|
|
Packit Service |
6f2e62 |
* The time differences measured by clockdiff are obtained using a sequence
|
|
Packit Service |
6f2e62 |
* of ICMP TSTAMP messages which are returned to the sender by the IP module
|
|
Packit Service |
6f2e62 |
* in the remote machine.
|
|
Packit Service |
6f2e62 |
* In order to compare clocks of machines in different time zones, the time
|
|
Packit Service |
6f2e62 |
* is transmitted (as a 32-bit value) in milliseconds since midnight UT.
|
|
Packit Service |
6f2e62 |
* If a hosts uses a different time format, it should set the high order
|
|
Packit Service |
6f2e62 |
* bit of the 32-bit quantity it transmits.
|
|
Packit Service |
6f2e62 |
* However, VMS apparently transmits the time in milliseconds since midnight
|
|
Packit Service |
6f2e62 |
* local time (rather than GMT) without setting the high order bit.
|
|
Packit Service |
6f2e62 |
* Furthermore, it does not understand daylight-saving time. This makes
|
|
Packit Service |
6f2e62 |
* clockdiff behaving inconsistently with hosts running VMS.
|
|
Packit Service |
6f2e62 |
*
|
|
Packit Service |
6f2e62 |
* In order to reduce the sensitivity to the variance of message transmission
|
|
Packit Service |
6f2e62 |
* time, clockdiff sends a sequence of messages. Yet, measures between
|
|
Packit Service |
6f2e62 |
* two `distant' hosts can be affected by a small error. The error can, however,
|
|
Packit Service |
6f2e62 |
* be reduced by increasing the number of messages sent in each measurement.
|
|
Packit Service |
6f2e62 |
*/
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void
|
|
Packit Service |
6f2e62 |
usage() {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "Usage: clockdiff [-o] <host>\n");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
void drop_rights(void) {
|
|
Packit Service |
6f2e62 |
#ifdef CAPABILITIES
|
|
Packit Service |
6f2e62 |
cap_t caps = cap_init();
|
|
Packit Service |
6f2e62 |
if (cap_set_proc(caps)) {
|
|
Packit Service |
6f2e62 |
perror("clockdiff: cap_set_proc");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
cap_free(caps);
|
|
Packit Service |
6f2e62 |
#endif
|
|
Packit Service |
6f2e62 |
if (setuid(getuid())) {
|
|
Packit Service |
6f2e62 |
perror("clockdiff: setuid");
|
|
Packit Service |
6f2e62 |
exit(-1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
int
|
|
Packit Service |
6f2e62 |
main(int argc, char *argv[])
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
int measure_status;
|
|
Packit Service |
6f2e62 |
struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_RAW, .ai_flags = AI_CANONNAME };
|
|
Packit Service |
6f2e62 |
struct addrinfo *result;
|
|
Packit Service |
6f2e62 |
int status;
|
|
Packit Service |
6f2e62 |
char hostname[MAX_HOSTNAMELEN];
|
|
Packit Service |
6f2e62 |
int s_errno = 0;
|
|
Packit Service |
6f2e62 |
int n_errno = 0;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (argc < 2) {
|
|
Packit Service |
6f2e62 |
drop_rights();
|
|
Packit Service |
6f2e62 |
usage();
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
|
Packit Service |
6f2e62 |
s_errno = errno;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
errno = 0;
|
|
Packit Service |
6f2e62 |
if (nice(-16) == -1)
|
|
Packit Service |
6f2e62 |
n_errno = errno;
|
|
Packit Service |
6f2e62 |
drop_rights();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (argc == 3) {
|
|
Packit Service |
6f2e62 |
if (strcmp(argv[1], "-o") == 0) {
|
|
Packit Service |
6f2e62 |
ip_opt_len = 4 + 4*8;
|
|
Packit Service |
6f2e62 |
argv++;
|
|
Packit Service |
6f2e62 |
} else if (strcmp(argv[1], "-o1") == 0) {
|
|
Packit Service |
6f2e62 |
ip_opt_len = 4 + 3*8;
|
|
Packit Service |
6f2e62 |
argv++;
|
|
Packit Service |
6f2e62 |
} else
|
|
Packit Service |
6f2e62 |
usage();
|
|
Packit Service |
6f2e62 |
} else if (argc != 2)
|
|
Packit Service |
6f2e62 |
usage();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (sock_raw < 0) {
|
|
Packit Service |
6f2e62 |
errno = s_errno;
|
|
Packit Service |
6f2e62 |
perror("clockdiff: socket");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (n_errno < 0) {
|
|
Packit Service |
6f2e62 |
errno = n_errno;
|
|
Packit Service |
6f2e62 |
perror("clockdiff: nice");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (isatty(fileno(stdin)) && isatty(fileno(stdout)))
|
|
Packit Service |
6f2e62 |
interactive = 1;
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
id = getpid();
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
(void)gethostname(hostname,sizeof(hostname));
|
|
Packit Service |
6f2e62 |
status = getaddrinfo(hostname, NULL, &hints, &result);
|
|
Packit Service |
6f2e62 |
if (status) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "clockdiff: %s: %s\n", hostname, gai_strerror(status));
|
|
Packit Service |
6f2e62 |
exit(2);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
myname = strdup(result->ai_canonname);
|
|
Packit Service |
6f2e62 |
freeaddrinfo(result);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
status = getaddrinfo(argv[1], NULL, &hints, &result);
|
|
Packit Service |
6f2e62 |
if (status) {
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "clockdiff: %s: %s\n", argv[1], gai_strerror(status));
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
hisname = strdup(result->ai_canonname);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
memcpy(&server, result->ai_addr, sizeof server);
|
|
Packit Service |
6f2e62 |
freeaddrinfo(result);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (connect(sock_raw, (struct sockaddr*)&server, sizeof(server)) == -1) {
|
|
Packit Service |
6f2e62 |
perror("connect");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
if (ip_opt_len) {
|
|
Packit Service |
6f2e62 |
struct sockaddr_in myaddr;
|
|
Packit Service |
6f2e62 |
socklen_t addrlen = sizeof(myaddr);
|
|
Packit Service |
6f2e62 |
unsigned char rspace[ip_opt_len];
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
memset(rspace, 0, sizeof(rspace));
|
|
Packit Service |
6f2e62 |
rspace[0] = IPOPT_TIMESTAMP;
|
|
Packit Service |
6f2e62 |
rspace[1] = ip_opt_len;
|
|
Packit Service |
6f2e62 |
rspace[2] = 5;
|
|
Packit Service |
6f2e62 |
rspace[3] = IPOPT_TS_PRESPEC;
|
|
Packit Service |
6f2e62 |
if (getsockname(sock_raw, (struct sockaddr*)&myaddr, &addrlen) == -1) {
|
|
Packit Service |
6f2e62 |
perror("getsockname");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
((__u32*)(rspace+4))[0*2] = myaddr.sin_addr.s_addr;
|
|
Packit Service |
6f2e62 |
((__u32*)(rspace+4))[1*2] = server.sin_addr.s_addr;
|
|
Packit Service |
6f2e62 |
((__u32*)(rspace+4))[2*2] = myaddr.sin_addr.s_addr;
|
|
Packit Service |
6f2e62 |
if (ip_opt_len == 4+4*8) {
|
|
Packit Service |
6f2e62 |
((__u32*)(rspace+4))[2*2] = server.sin_addr.s_addr;
|
|
Packit Service |
6f2e62 |
((__u32*)(rspace+4))[3*2] = myaddr.sin_addr.s_addr;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (setsockopt(sock_raw, IPPROTO_IP, IP_OPTIONS, rspace, ip_opt_len) < 0) {
|
|
Packit Service |
6f2e62 |
perror("ping: IP_OPTIONS (fallback to icmp tstamps)");
|
|
Packit Service |
6f2e62 |
ip_opt_len = 0;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if ((measure_status = (ip_opt_len ? measure_opt : measure)(&server)) < 0) {
|
|
Packit Service |
6f2e62 |
if (errno)
|
|
Packit Service |
6f2e62 |
perror("measure");
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "measure: unknown failure\n");
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
switch (measure_status) {
|
|
Packit Service |
6f2e62 |
case HOSTDOWN:
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "%s is down\n", hisname);
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
case NONSTDTIME:
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "%s time transmitted in a non-standard format\n", hisname);
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
case UNREACHABLE:
|
|
Packit Service |
6f2e62 |
fprintf(stderr, "%s is unreachable\n", hisname);
|
|
Packit Service |
6f2e62 |
exit(1);
|
|
Packit Service |
6f2e62 |
default:
|
|
Packit Service |
6f2e62 |
break;
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
{
|
|
Packit Service |
6f2e62 |
time_t now = time(NULL);
|
|
Packit Service |
6f2e62 |
|
|
Packit Service |
6f2e62 |
if (interactive)
|
|
Packit Service |
6f2e62 |
printf("\nhost=%s rtt=%ld(%ld)ms/%ldms delta=%dms/%dms %s", hisname,
|
|
Packit Service |
6f2e62 |
rtt, rtt_sigma, min_rtt,
|
|
Packit Service |
6f2e62 |
measure_delta, measure_delta1,
|
|
Packit Service |
6f2e62 |
ctime(&now));
|
|
Packit Service |
6f2e62 |
else
|
|
Packit Service |
6f2e62 |
printf("%ld %d %d\n", now, measure_delta, measure_delta1);
|
|
Packit Service |
6f2e62 |
}
|
|
Packit Service |
6f2e62 |
exit(0);
|
|
Packit Service |
6f2e62 |
}
|