|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)measure.c 2.4 (Berkeley) 5/28/86";
9: #endif not lint
10:
11: #include "globals.h"
12: #include <protocols/timed.h>
13: #include <netinet/in_systm.h>
14: #include <netinet/ip.h>
15: #include <netinet/ip_icmp.h>
16:
17: #define BIASP 43199999
18: #define BIASN -43200000
19: #define MODULO 86400000
20: #define PROCESSING_TIME 5 /* ms. to reduce error in measurement */
21:
22: #define PACKET_IN 1024
23:
24: extern int id;
25: int measure_delta;
26: extern int sock_raw;
27: static n_short seqno = 0;
28:
29: /*
30: * Measures the differences between machines' clocks using
31: * ICMP timestamp messages.
32: */
33:
34: measure(wait, addr)
35: struct timeval *wait;
36: struct sockaddr_in *addr;
37: {
38: int length;
39: int status;
40: int msgcount, trials;
41: int cc, count;
42: fd_set ready;
43: long sendtime, recvtime, histime;
44: long min1, min2, diff;
45: register long delta1, delta2;
46: struct timeval tv1, tout;
47: u_char packet[PACKET_IN], opacket[64];
48: register struct icmp *icp = (struct icmp *) packet;
49: register struct icmp *oicp = (struct icmp *) opacket;
50: struct ip *ip = (struct ip *) packet;
51:
52: min1 = min2 = 0x7fffffff;
53: status = HOSTDOWN;
54: measure_delta = HOSTDOWN;
55:
56: /* empties the icmp input queue */
57: FD_ZERO(&ready);
58: empty:
59: tout.tv_sec = tout.tv_usec = 0;
60: FD_SET(sock_raw, &ready);
61: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
62: length = sizeof(struct sockaddr_in);
63: cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
64: (struct sockaddr_in *)NULL, &length);
65: if (cc < 0)
66: return(-1);
67: goto empty;
68: }
69:
70: /*
71: * To measure the difference, select MSGS messages whose round-trip
72: * time is smaller than RANGE if ckrange is 1, otherwise simply
73: * select MSGS messages regardless of round-trip transmission time.
74: * Choose the smallest transmission time in each of the two directions.
75: * Use these two latter quantities to compute the delta between
76: * the two clocks.
77: */
78:
79: length = sizeof(struct sockaddr_in);
80: oicp->icmp_type = ICMP_TSTAMP;
81: oicp->icmp_code = 0;
82: oicp->icmp_cksum = 0;
83: oicp->icmp_id = id;
84: oicp->icmp_rtime = 0;
85: oicp->icmp_ttime = 0;
86: FD_ZERO(&ready);
87: msgcount = 0;
88: for (trials = 0; msgcount < MSGS && trials < TRIALS; ++trials) {
89: oicp->icmp_seq = ++seqno;
90: oicp->icmp_cksum = 0;
91:
92: tout.tv_sec = wait->tv_sec;
93: tout.tv_usec = wait->tv_usec;
94:
95: (void)gettimeofday (&tv1, (struct timezone *)0);
96: sendtime = oicp->icmp_otime = (tv1.tv_sec % (24*60*60)) * 1000
97: + tv1.tv_usec / 1000;
98: oicp->icmp_cksum = in_cksum((u_short *)oicp, sizeof(*oicp));
99:
100: count = sendto(sock_raw, (char *)opacket, sizeof(*oicp), 0,
101: addr, sizeof(struct sockaddr_in));
102: if (count < 0) {
103: status = UNREACHABLE;
104: return(-1);
105: }
106: for (;;) {
107: FD_SET(sock_raw, &ready);
108: if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
109: (fd_set *)0, &tout)) <= 0)
110: break;
111: cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
112: (struct sockaddr_in *)NULL, &length);
113: (void)gettimeofday(&tv1, (struct timezone *)0);
114: if (cc < 0)
115: return(-1);
116: icp = (struct icmp *)(packet + (ip->ip_hl << 2));
117: if((icp->icmp_type == ICMP_TSTAMPREPLY) &&
118: icp->icmp_id == id && icp->icmp_seq == seqno)
119: break;
120: }
121: if (count <= 0)
122: continue; /* resend */
123: recvtime = (tv1.tv_sec % (24*60*60)) * 1000 +
124: tv1.tv_usec / 1000;
125: diff = recvtime - sendtime;
126: /*
127: * diff can be less than 0 aroud midnight
128: */
129: if (diff < 0)
130: continue;
131: msgcount++;
132: histime = ntohl((u_long)icp->icmp_rtime);
133: /*
134: * a hosts using a time format different from
135: * ms. since midnight UT (as per RFC792) should
136: * set the high order bit of the 32-bit time
137: * value it transmits.
138: */
139: if ((histime & 0x80000000) != 0) {
140: status = NONSTDTIME;
141: break;
142: }
143: status = GOOD;
144: delta1 = histime - sendtime;
145: /*
146: * Handles wrap-around to avoid that around
147: * midnight small time differences appear
148: * enormous. However, the two machine's clocks
149: * must be within 12 hours from each other.
150: */
151: if (delta1 < BIASN)
152: delta1 += MODULO;
153: else if (delta1 > BIASP)
154: delta1 -= MODULO;
155: delta2 = recvtime - histime;
156: if (delta2 < BIASN)
157: delta2 += MODULO;
158: else if (delta2 > BIASP)
159: delta2 -= MODULO;
160: if (delta1 < min1)
161: min1 = delta1;
162: if (delta2 < min2)
163: min2 = delta2;
164: if (diff < RANGE) {
165: min1 = delta1;
166: min2 = delta2;
167: break;
168: }
169: }
170:
171: /*
172: * If no answer is received for TRIALS consecutive times,
173: * the machine is assumed to be down
174: */
175: if (status == GOOD) {
176: measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
177: }
178: return(status);
179: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.