* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)measure.c 2.7 (Berkeley) 6/1/90";
#include <protocols/timed.h>
#include <netinet/in_systm.h>
#include <netinet/ip_icmp.h>
#define PROCESSING_TIME 5 /* ms. to reduce error in measurement */
static n_short seqno
= 0;
* Measures the differences between machines' clocks using
* ICMP timestamp messages.
struct sockaddr_in
*addr
;
long sendtime
, recvtime
, histime
;
register long delta1
, delta2
;
struct timeval tv1
, tout
;
u_char packet
[PACKET_IN
], opacket
[64];
register struct icmp
*icp
= (struct icmp
*) packet
;
register struct icmp
*oicp
= (struct icmp
*) opacket
;
struct ip
*ip
= (struct ip
*) packet
;
min1
= min2
= 0x7fffffff;
measure_delta
= HOSTDOWN
;
/* empties the icmp input queue */
tout
.tv_sec
= tout
.tv_usec
= 0;
FD_SET(sock_raw
, &ready
);
if (select(FD_SETSIZE
, &ready
, (fd_set
*)0, (fd_set
*)0, &tout
)) {
length
= sizeof(struct sockaddr_in
);
cc
= recvfrom(sock_raw
, (char *)packet
, PACKET_IN
, 0,
(struct sockaddr_in
*)NULL
, &length
);
* To measure the difference, select MSGS messages whose round-trip
* time is smaller than RANGE if ckrange is 1, otherwise simply
* select MSGS messages regardless of round-trip transmission time.
* Choose the smallest transmission time in each of the two directions.
* Use these two latter quantities to compute the delta between
length
= sizeof(struct sockaddr_in
);
oicp
->icmp_type
= ICMP_TSTAMP
;
for (trials
= 0; msgcount
< MSGS
&& trials
< TRIALS
; ++trials
) {
oicp
->icmp_seq
= ++seqno
;
tout
.tv_sec
= wait
->tv_sec
;
tout
.tv_usec
= wait
->tv_usec
;
(void)gettimeofday (&tv1
, (struct timezone
*)0);
sendtime
= oicp
->icmp_otime
= (tv1
.tv_sec
% (24*60*60)) * 1000
oicp
->icmp_cksum
= in_cksum((u_short
*)oicp
, sizeof(*oicp
));
count
= sendto(sock_raw
, (char *)opacket
, sizeof(*oicp
), 0,
addr
, sizeof(struct sockaddr_in
));
FD_SET(sock_raw
, &ready
);
if ((count
= select(FD_SETSIZE
, &ready
, (fd_set
*)0,
(fd_set
*)0, &tout
)) <= 0)
cc
= recvfrom(sock_raw
, (char *)packet
, PACKET_IN
, 0,
(struct sockaddr_in
*)NULL
, &length
);
(void)gettimeofday(&tv1
, (struct timezone
*)0);
icp
= (struct icmp
*)(packet
+ (ip
->ip_hl
<< 2));
if((icp
->icmp_type
== ICMP_TSTAMPREPLY
) &&
icp
->icmp_id
== id
&& icp
->icmp_seq
== seqno
)
recvtime
= (tv1
.tv_sec
% (24*60*60)) * 1000 +
diff
= recvtime
- sendtime
;
* diff can be less than 0 aroud midnight
histime
= ntohl((u_long
)icp
->icmp_rtime
);
* a hosts using a time format different from
* ms. since midnight UT (as per RFC792) should
* set the high order bit of the 32-bit time
if ((histime
& 0x80000000) != 0) {
delta1
= histime
- sendtime
;
* Handles wrap-around to avoid that around
* midnight small time differences appear
* enormous. However, the two machine's clocks
* must be within 12 hours from each other.
delta2
= recvtime
- histime
;
* If no answer is received for TRIALS consecutive times,
* the machine is assumed to be down
measure_delta
= (min1
- min2
)/2 + PROCESSING_TIME
;