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