1*bd1f8aebSAndroid Build Coastguard Worker #include <time.h>
2*bd1f8aebSAndroid Build Coastguard Worker #include <sys/types.h>
3*bd1f8aebSAndroid Build Coastguard Worker #include <sys/param.h>
4*bd1f8aebSAndroid Build Coastguard Worker #include <stdio.h>
5*bd1f8aebSAndroid Build Coastguard Worker #include <unistd.h>
6*bd1f8aebSAndroid Build Coastguard Worker #include <stdlib.h>
7*bd1f8aebSAndroid Build Coastguard Worker #include <math.h>
8*bd1f8aebSAndroid Build Coastguard Worker #include <string.h>
9*bd1f8aebSAndroid Build Coastguard Worker #include <sys/time.h>
10*bd1f8aebSAndroid Build Coastguard Worker #include <sys/timex.h>
11*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
12*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
13*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in.h>
14*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/ip.h>
15*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/ip_icmp.h>
16*bd1f8aebSAndroid Build Coastguard Worker #define TSPTYPES
17*bd1f8aebSAndroid Build Coastguard Worker #include <protocols/timed.h>
18*bd1f8aebSAndroid Build Coastguard Worker #include <fcntl.h>
19*bd1f8aebSAndroid Build Coastguard Worker #include <netdb.h>
20*bd1f8aebSAndroid Build Coastguard Worker #include <arpa/inet.h>
21*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
22*bd1f8aebSAndroid Build Coastguard Worker #include <linux/types.h>
23*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
24*bd1f8aebSAndroid Build Coastguard Worker #include <sys/capability.h>
25*bd1f8aebSAndroid Build Coastguard Worker #endif
26*bd1f8aebSAndroid Build Coastguard Worker
27*bd1f8aebSAndroid Build Coastguard Worker void usage(void) __attribute__((noreturn));
28*bd1f8aebSAndroid Build Coastguard Worker
29*bd1f8aebSAndroid Build Coastguard Worker #define MAX_HOSTNAMELEN NI_MAXHOST
30*bd1f8aebSAndroid Build Coastguard Worker
31*bd1f8aebSAndroid Build Coastguard Worker /*
32*bd1f8aebSAndroid Build Coastguard Worker * Checksum routine for Internet Protocol family headers.
33*bd1f8aebSAndroid Build Coastguard Worker *
34*bd1f8aebSAndroid Build Coastguard Worker * This routine is very heavily used in the network
35*bd1f8aebSAndroid Build Coastguard Worker * code and should be modified for each CPU to be as fast as possible.
36*bd1f8aebSAndroid Build Coastguard Worker *
37*bd1f8aebSAndroid Build Coastguard Worker * This implementation is TAHOE version.
38*bd1f8aebSAndroid Build Coastguard Worker */
39*bd1f8aebSAndroid Build Coastguard Worker
40*bd1f8aebSAndroid Build Coastguard Worker #undef ADDCARRY
41*bd1f8aebSAndroid Build Coastguard Worker #define ADDCARRY(sum) { \
42*bd1f8aebSAndroid Build Coastguard Worker if (sum & 0xffff0000) { \
43*bd1f8aebSAndroid Build Coastguard Worker sum &= 0xffff; \
44*bd1f8aebSAndroid Build Coastguard Worker sum++; \
45*bd1f8aebSAndroid Build Coastguard Worker } \
46*bd1f8aebSAndroid Build Coastguard Worker }
47*bd1f8aebSAndroid Build Coastguard Worker
in_cksum(u_short * addr,int len)48*bd1f8aebSAndroid Build Coastguard Worker int in_cksum(u_short *addr, int len)
49*bd1f8aebSAndroid Build Coastguard Worker {
50*bd1f8aebSAndroid Build Coastguard Worker union word {
51*bd1f8aebSAndroid Build Coastguard Worker char c[2];
52*bd1f8aebSAndroid Build Coastguard Worker u_short s;
53*bd1f8aebSAndroid Build Coastguard Worker } u;
54*bd1f8aebSAndroid Build Coastguard Worker int sum = 0;
55*bd1f8aebSAndroid Build Coastguard Worker
56*bd1f8aebSAndroid Build Coastguard Worker while (len > 0) {
57*bd1f8aebSAndroid Build Coastguard Worker /*
58*bd1f8aebSAndroid Build Coastguard Worker * add by words.
59*bd1f8aebSAndroid Build Coastguard Worker */
60*bd1f8aebSAndroid Build Coastguard Worker while ((len -= 2) >= 0) {
61*bd1f8aebSAndroid Build Coastguard Worker if ((unsigned long)addr & 0x1) {
62*bd1f8aebSAndroid Build Coastguard Worker /* word is not aligned */
63*bd1f8aebSAndroid Build Coastguard Worker u.c[0] = *(char *)addr;
64*bd1f8aebSAndroid Build Coastguard Worker u.c[1] = *((char *)addr+1);
65*bd1f8aebSAndroid Build Coastguard Worker sum += u.s;
66*bd1f8aebSAndroid Build Coastguard Worker addr++;
67*bd1f8aebSAndroid Build Coastguard Worker } else
68*bd1f8aebSAndroid Build Coastguard Worker sum += *addr++;
69*bd1f8aebSAndroid Build Coastguard Worker ADDCARRY(sum);
70*bd1f8aebSAndroid Build Coastguard Worker }
71*bd1f8aebSAndroid Build Coastguard Worker if (len == -1)
72*bd1f8aebSAndroid Build Coastguard Worker /*
73*bd1f8aebSAndroid Build Coastguard Worker * Odd number of bytes.
74*bd1f8aebSAndroid Build Coastguard Worker */
75*bd1f8aebSAndroid Build Coastguard Worker u.c[0] = *(u_char *)addr;
76*bd1f8aebSAndroid Build Coastguard Worker }
77*bd1f8aebSAndroid Build Coastguard Worker if (len == -1) {
78*bd1f8aebSAndroid Build Coastguard Worker /* The last mbuf has odd # of bytes. Follow the
79*bd1f8aebSAndroid Build Coastguard Worker standard (the odd byte is shifted left by 8 bits) */
80*bd1f8aebSAndroid Build Coastguard Worker u.c[1] = 0;
81*bd1f8aebSAndroid Build Coastguard Worker sum += u.s;
82*bd1f8aebSAndroid Build Coastguard Worker ADDCARRY(sum);
83*bd1f8aebSAndroid Build Coastguard Worker }
84*bd1f8aebSAndroid Build Coastguard Worker return (~sum & 0xffff);
85*bd1f8aebSAndroid Build Coastguard Worker }
86*bd1f8aebSAndroid Build Coastguard Worker
87*bd1f8aebSAndroid Build Coastguard Worker #define ON 1
88*bd1f8aebSAndroid Build Coastguard Worker #define OFF 0
89*bd1f8aebSAndroid Build Coastguard Worker
90*bd1f8aebSAndroid Build Coastguard Worker #define RANGE 1 /* best expected round-trip time, ms */
91*bd1f8aebSAndroid Build Coastguard Worker #define MSGS 50
92*bd1f8aebSAndroid Build Coastguard Worker #define TRIALS 10
93*bd1f8aebSAndroid Build Coastguard Worker
94*bd1f8aebSAndroid Build Coastguard Worker #define GOOD 0
95*bd1f8aebSAndroid Build Coastguard Worker #define UNREACHABLE 2
96*bd1f8aebSAndroid Build Coastguard Worker #define NONSTDTIME 3
97*bd1f8aebSAndroid Build Coastguard Worker #define HOSTDOWN 0x7fffffff
98*bd1f8aebSAndroid Build Coastguard Worker
99*bd1f8aebSAndroid Build Coastguard Worker
100*bd1f8aebSAndroid Build Coastguard Worker int interactive = 0;
101*bd1f8aebSAndroid Build Coastguard Worker uint16_t id;
102*bd1f8aebSAndroid Build Coastguard Worker int sock;
103*bd1f8aebSAndroid Build Coastguard Worker int sock_raw;
104*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in server;
105*bd1f8aebSAndroid Build Coastguard Worker int ip_opt_len = 0;
106*bd1f8aebSAndroid Build Coastguard Worker
107*bd1f8aebSAndroid Build Coastguard Worker #define BIASP 43199999
108*bd1f8aebSAndroid Build Coastguard Worker #define BIASN -43200000
109*bd1f8aebSAndroid Build Coastguard Worker #define MODULO 86400000
110*bd1f8aebSAndroid Build Coastguard Worker #define PROCESSING_TIME 0 /* ms. to reduce error in measurement */
111*bd1f8aebSAndroid Build Coastguard Worker
112*bd1f8aebSAndroid Build Coastguard Worker #define PACKET_IN 1024
113*bd1f8aebSAndroid Build Coastguard Worker
114*bd1f8aebSAndroid Build Coastguard Worker int measure_delta;
115*bd1f8aebSAndroid Build Coastguard Worker int measure_delta1;
116*bd1f8aebSAndroid Build Coastguard Worker static u_short seqno, seqno0, acked;
117*bd1f8aebSAndroid Build Coastguard Worker long rtt = 1000;
118*bd1f8aebSAndroid Build Coastguard Worker long min_rtt;
119*bd1f8aebSAndroid Build Coastguard Worker long rtt_sigma = 0;
120*bd1f8aebSAndroid Build Coastguard Worker
121*bd1f8aebSAndroid Build Coastguard Worker /*
122*bd1f8aebSAndroid Build Coastguard Worker * Measures the differences between machines' clocks using
123*bd1f8aebSAndroid Build Coastguard Worker * ICMP timestamp messages.
124*bd1f8aebSAndroid Build Coastguard Worker */
125*bd1f8aebSAndroid Build Coastguard Worker int
measure(struct sockaddr_in * addr)126*bd1f8aebSAndroid Build Coastguard Worker measure(struct sockaddr_in * addr)
127*bd1f8aebSAndroid Build Coastguard Worker {
128*bd1f8aebSAndroid Build Coastguard Worker socklen_t length;
129*bd1f8aebSAndroid Build Coastguard Worker int msgcount;
130*bd1f8aebSAndroid Build Coastguard Worker int cc, count;
131*bd1f8aebSAndroid Build Coastguard Worker fd_set ready;
132*bd1f8aebSAndroid Build Coastguard Worker long sendtime, recvtime, histime;
133*bd1f8aebSAndroid Build Coastguard Worker long min1, min2, diff;
134*bd1f8aebSAndroid Build Coastguard Worker long delta1, delta2;
135*bd1f8aebSAndroid Build Coastguard Worker struct timeval tv1, tout;
136*bd1f8aebSAndroid Build Coastguard Worker u_char packet[PACKET_IN], opacket[64];
137*bd1f8aebSAndroid Build Coastguard Worker struct icmphdr *icp = (struct icmphdr *) packet;
138*bd1f8aebSAndroid Build Coastguard Worker struct icmphdr *oicp = (struct icmphdr *) opacket;
139*bd1f8aebSAndroid Build Coastguard Worker struct iphdr *ip = (struct iphdr *) packet;
140*bd1f8aebSAndroid Build Coastguard Worker
141*bd1f8aebSAndroid Build Coastguard Worker min1 = min2 = 0x7fffffff;
142*bd1f8aebSAndroid Build Coastguard Worker min_rtt = 0x7fffffff;
143*bd1f8aebSAndroid Build Coastguard Worker measure_delta = HOSTDOWN;
144*bd1f8aebSAndroid Build Coastguard Worker measure_delta1 = HOSTDOWN;
145*bd1f8aebSAndroid Build Coastguard Worker
146*bd1f8aebSAndroid Build Coastguard Worker /* empties the icmp input queue */
147*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
148*bd1f8aebSAndroid Build Coastguard Worker
149*bd1f8aebSAndroid Build Coastguard Worker empty:
150*bd1f8aebSAndroid Build Coastguard Worker tout.tv_sec = tout.tv_usec = 0;
151*bd1f8aebSAndroid Build Coastguard Worker FD_SET(sock_raw, &ready);
152*bd1f8aebSAndroid Build Coastguard Worker if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
153*bd1f8aebSAndroid Build Coastguard Worker length = sizeof(struct sockaddr_in);
154*bd1f8aebSAndroid Build Coastguard Worker cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
155*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)NULL, &length);
156*bd1f8aebSAndroid Build Coastguard Worker if (cc < 0)
157*bd1f8aebSAndroid Build Coastguard Worker return -1;
158*bd1f8aebSAndroid Build Coastguard Worker goto empty;
159*bd1f8aebSAndroid Build Coastguard Worker }
160*bd1f8aebSAndroid Build Coastguard Worker
161*bd1f8aebSAndroid Build Coastguard Worker /*
162*bd1f8aebSAndroid Build Coastguard Worker * To measure the difference, select MSGS messages whose round-trip
163*bd1f8aebSAndroid Build Coastguard Worker * time is smaller than RANGE if ckrange is 1, otherwise simply
164*bd1f8aebSAndroid Build Coastguard Worker * select MSGS messages regardless of round-trip transmission time.
165*bd1f8aebSAndroid Build Coastguard Worker * Choose the smallest transmission time in each of the two directions.
166*bd1f8aebSAndroid Build Coastguard Worker * Use these two latter quantities to compute the delta between
167*bd1f8aebSAndroid Build Coastguard Worker * the two clocks.
168*bd1f8aebSAndroid Build Coastguard Worker */
169*bd1f8aebSAndroid Build Coastguard Worker
170*bd1f8aebSAndroid Build Coastguard Worker length = sizeof(struct sockaddr_in);
171*bd1f8aebSAndroid Build Coastguard Worker oicp->type = ICMP_TIMESTAMP;
172*bd1f8aebSAndroid Build Coastguard Worker oicp->code = 0;
173*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = 0;
174*bd1f8aebSAndroid Build Coastguard Worker oicp->un.echo.id = id;
175*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[0] = 0;
176*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[1] = 0;
177*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[2] = 0;
178*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
179*bd1f8aebSAndroid Build Coastguard Worker msgcount = 0;
180*bd1f8aebSAndroid Build Coastguard Worker
181*bd1f8aebSAndroid Build Coastguard Worker acked = seqno = seqno0 = 0;
182*bd1f8aebSAndroid Build Coastguard Worker
183*bd1f8aebSAndroid Build Coastguard Worker for (msgcount = 0; msgcount < MSGS; ) {
184*bd1f8aebSAndroid Build Coastguard Worker
185*bd1f8aebSAndroid Build Coastguard Worker /*
186*bd1f8aebSAndroid Build Coastguard Worker * If no answer is received for TRIALS consecutive times,
187*bd1f8aebSAndroid Build Coastguard Worker * the machine is assumed to be down
188*bd1f8aebSAndroid Build Coastguard Worker */
189*bd1f8aebSAndroid Build Coastguard Worker if (seqno - acked > TRIALS)
190*bd1f8aebSAndroid Build Coastguard Worker return HOSTDOWN;
191*bd1f8aebSAndroid Build Coastguard Worker
192*bd1f8aebSAndroid Build Coastguard Worker oicp->un.echo.sequence = ++seqno;
193*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = 0;
194*bd1f8aebSAndroid Build Coastguard Worker
195*bd1f8aebSAndroid Build Coastguard Worker (void)gettimeofday (&tv1, (struct timezone *)0);
196*bd1f8aebSAndroid Build Coastguard Worker *(__u32*)(oicp+1) = htonl((tv1.tv_sec % (24*60*60)) * 1000
197*bd1f8aebSAndroid Build Coastguard Worker + tv1.tv_usec / 1000);
198*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = in_cksum((u_short *)oicp, sizeof(*oicp) + 12);
199*bd1f8aebSAndroid Build Coastguard Worker
200*bd1f8aebSAndroid Build Coastguard Worker count = sendto(sock_raw, (char *)opacket, sizeof(*oicp)+12, 0,
201*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)addr, sizeof(struct sockaddr_in));
202*bd1f8aebSAndroid Build Coastguard Worker
203*bd1f8aebSAndroid Build Coastguard Worker if (count < 0)
204*bd1f8aebSAndroid Build Coastguard Worker return UNREACHABLE;
205*bd1f8aebSAndroid Build Coastguard Worker
206*bd1f8aebSAndroid Build Coastguard Worker for (;;) {
207*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
208*bd1f8aebSAndroid Build Coastguard Worker FD_SET(sock_raw, &ready);
209*bd1f8aebSAndroid Build Coastguard Worker {
210*bd1f8aebSAndroid Build Coastguard Worker long tmo = rtt + rtt_sigma;
211*bd1f8aebSAndroid Build Coastguard Worker tout.tv_sec = tmo/1000;
212*bd1f8aebSAndroid Build Coastguard Worker tout.tv_usec = (tmo - (tmo/1000)*1000)*1000;
213*bd1f8aebSAndroid Build Coastguard Worker }
214*bd1f8aebSAndroid Build Coastguard Worker
215*bd1f8aebSAndroid Build Coastguard Worker if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
216*bd1f8aebSAndroid Build Coastguard Worker (fd_set *)0, &tout)) <= 0)
217*bd1f8aebSAndroid Build Coastguard Worker break;
218*bd1f8aebSAndroid Build Coastguard Worker
219*bd1f8aebSAndroid Build Coastguard Worker (void)gettimeofday(&tv1, (struct timezone *)0);
220*bd1f8aebSAndroid Build Coastguard Worker cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
221*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)NULL, &length);
222*bd1f8aebSAndroid Build Coastguard Worker
223*bd1f8aebSAndroid Build Coastguard Worker if (cc < 0)
224*bd1f8aebSAndroid Build Coastguard Worker return(-1);
225*bd1f8aebSAndroid Build Coastguard Worker
226*bd1f8aebSAndroid Build Coastguard Worker icp = (struct icmphdr *)(packet + (ip->ihl << 2));
227*bd1f8aebSAndroid Build Coastguard Worker if( icp->type == ICMP_TIMESTAMPREPLY &&
228*bd1f8aebSAndroid Build Coastguard Worker icp->un.echo.id == id && icp->un.echo.sequence >= seqno0 &&
229*bd1f8aebSAndroid Build Coastguard Worker icp->un.echo.sequence <= seqno) {
230*bd1f8aebSAndroid Build Coastguard Worker if (acked < icp->un.echo.sequence)
231*bd1f8aebSAndroid Build Coastguard Worker acked = icp->un.echo.sequence;
232*bd1f8aebSAndroid Build Coastguard Worker
233*bd1f8aebSAndroid Build Coastguard Worker recvtime = (tv1.tv_sec % (24*60*60)) * 1000 +
234*bd1f8aebSAndroid Build Coastguard Worker tv1.tv_usec / 1000;
235*bd1f8aebSAndroid Build Coastguard Worker sendtime = ntohl(*(__u32*)(icp+1));
236*bd1f8aebSAndroid Build Coastguard Worker diff = recvtime - sendtime;
237*bd1f8aebSAndroid Build Coastguard Worker /*
238*bd1f8aebSAndroid Build Coastguard Worker * diff can be less than 0 aroud midnight
239*bd1f8aebSAndroid Build Coastguard Worker */
240*bd1f8aebSAndroid Build Coastguard Worker if (diff < 0)
241*bd1f8aebSAndroid Build Coastguard Worker continue;
242*bd1f8aebSAndroid Build Coastguard Worker rtt = (rtt * 3 + diff)/4;
243*bd1f8aebSAndroid Build Coastguard Worker rtt_sigma = (rtt_sigma *3 + abs(diff-rtt))/4;
244*bd1f8aebSAndroid Build Coastguard Worker msgcount++;
245*bd1f8aebSAndroid Build Coastguard Worker histime = ntohl(((__u32*)(icp+1))[1]);
246*bd1f8aebSAndroid Build Coastguard Worker /*
247*bd1f8aebSAndroid Build Coastguard Worker * a hosts using a time format different from
248*bd1f8aebSAndroid Build Coastguard Worker * ms. since midnight UT (as per RFC792) should
249*bd1f8aebSAndroid Build Coastguard Worker * set the high order bit of the 32-bit time
250*bd1f8aebSAndroid Build Coastguard Worker * value it transmits.
251*bd1f8aebSAndroid Build Coastguard Worker */
252*bd1f8aebSAndroid Build Coastguard Worker if ((histime & 0x80000000) != 0)
253*bd1f8aebSAndroid Build Coastguard Worker return NONSTDTIME;
254*bd1f8aebSAndroid Build Coastguard Worker
255*bd1f8aebSAndroid Build Coastguard Worker if (interactive) {
256*bd1f8aebSAndroid Build Coastguard Worker printf(".");
257*bd1f8aebSAndroid Build Coastguard Worker fflush(stdout);
258*bd1f8aebSAndroid Build Coastguard Worker }
259*bd1f8aebSAndroid Build Coastguard Worker
260*bd1f8aebSAndroid Build Coastguard Worker delta1 = histime - sendtime;
261*bd1f8aebSAndroid Build Coastguard Worker /*
262*bd1f8aebSAndroid Build Coastguard Worker * Handles wrap-around to avoid that around
263*bd1f8aebSAndroid Build Coastguard Worker * midnight small time differences appear
264*bd1f8aebSAndroid Build Coastguard Worker * enormous. However, the two machine's clocks
265*bd1f8aebSAndroid Build Coastguard Worker * must be within 12 hours from each other.
266*bd1f8aebSAndroid Build Coastguard Worker */
267*bd1f8aebSAndroid Build Coastguard Worker if (delta1 < BIASN)
268*bd1f8aebSAndroid Build Coastguard Worker delta1 += MODULO;
269*bd1f8aebSAndroid Build Coastguard Worker else if (delta1 > BIASP)
270*bd1f8aebSAndroid Build Coastguard Worker delta1 -= MODULO;
271*bd1f8aebSAndroid Build Coastguard Worker
272*bd1f8aebSAndroid Build Coastguard Worker delta2 = recvtime - histime;
273*bd1f8aebSAndroid Build Coastguard Worker if (delta2 < BIASN)
274*bd1f8aebSAndroid Build Coastguard Worker delta2 += MODULO;
275*bd1f8aebSAndroid Build Coastguard Worker else if (delta2 > BIASP)
276*bd1f8aebSAndroid Build Coastguard Worker delta2 -= MODULO;
277*bd1f8aebSAndroid Build Coastguard Worker
278*bd1f8aebSAndroid Build Coastguard Worker if (delta1 < min1)
279*bd1f8aebSAndroid Build Coastguard Worker min1 = delta1;
280*bd1f8aebSAndroid Build Coastguard Worker if (delta2 < min2)
281*bd1f8aebSAndroid Build Coastguard Worker min2 = delta2;
282*bd1f8aebSAndroid Build Coastguard Worker if (delta1 + delta2 < min_rtt) {
283*bd1f8aebSAndroid Build Coastguard Worker min_rtt = delta1 + delta2;
284*bd1f8aebSAndroid Build Coastguard Worker measure_delta1 = (delta1 - delta2)/2 + PROCESSING_TIME;
285*bd1f8aebSAndroid Build Coastguard Worker }
286*bd1f8aebSAndroid Build Coastguard Worker if (diff < RANGE) {
287*bd1f8aebSAndroid Build Coastguard Worker min1 = delta1;
288*bd1f8aebSAndroid Build Coastguard Worker min2 = delta2;
289*bd1f8aebSAndroid Build Coastguard Worker goto good_exit;
290*bd1f8aebSAndroid Build Coastguard Worker }
291*bd1f8aebSAndroid Build Coastguard Worker }
292*bd1f8aebSAndroid Build Coastguard Worker }
293*bd1f8aebSAndroid Build Coastguard Worker }
294*bd1f8aebSAndroid Build Coastguard Worker
295*bd1f8aebSAndroid Build Coastguard Worker good_exit:
296*bd1f8aebSAndroid Build Coastguard Worker measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
297*bd1f8aebSAndroid Build Coastguard Worker return GOOD;
298*bd1f8aebSAndroid Build Coastguard Worker }
299*bd1f8aebSAndroid Build Coastguard Worker
300*bd1f8aebSAndroid Build Coastguard Worker char *myname, *hisname;
301*bd1f8aebSAndroid Build Coastguard Worker
302*bd1f8aebSAndroid Build Coastguard Worker int
measure_opt(struct sockaddr_in * addr)303*bd1f8aebSAndroid Build Coastguard Worker measure_opt(struct sockaddr_in * addr)
304*bd1f8aebSAndroid Build Coastguard Worker {
305*bd1f8aebSAndroid Build Coastguard Worker socklen_t length;
306*bd1f8aebSAndroid Build Coastguard Worker int msgcount;
307*bd1f8aebSAndroid Build Coastguard Worker int cc, count;
308*bd1f8aebSAndroid Build Coastguard Worker fd_set ready;
309*bd1f8aebSAndroid Build Coastguard Worker long sendtime, recvtime, histime, histime1;
310*bd1f8aebSAndroid Build Coastguard Worker long min1, min2, diff;
311*bd1f8aebSAndroid Build Coastguard Worker long delta1, delta2;
312*bd1f8aebSAndroid Build Coastguard Worker struct timeval tv1, tout;
313*bd1f8aebSAndroid Build Coastguard Worker u_char packet[PACKET_IN], opacket[64];
314*bd1f8aebSAndroid Build Coastguard Worker struct icmphdr *icp = (struct icmphdr *) packet;
315*bd1f8aebSAndroid Build Coastguard Worker struct icmphdr *oicp = (struct icmphdr *) opacket;
316*bd1f8aebSAndroid Build Coastguard Worker struct iphdr *ip = (struct iphdr *) packet;
317*bd1f8aebSAndroid Build Coastguard Worker
318*bd1f8aebSAndroid Build Coastguard Worker min1 = min2 = 0x7fffffff;
319*bd1f8aebSAndroid Build Coastguard Worker min_rtt = 0x7fffffff;
320*bd1f8aebSAndroid Build Coastguard Worker measure_delta = HOSTDOWN;
321*bd1f8aebSAndroid Build Coastguard Worker measure_delta1 = HOSTDOWN;
322*bd1f8aebSAndroid Build Coastguard Worker
323*bd1f8aebSAndroid Build Coastguard Worker /* empties the icmp input queue */
324*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
325*bd1f8aebSAndroid Build Coastguard Worker empty:
326*bd1f8aebSAndroid Build Coastguard Worker tout.tv_sec = tout.tv_usec = 0;
327*bd1f8aebSAndroid Build Coastguard Worker FD_SET(sock_raw, &ready);
328*bd1f8aebSAndroid Build Coastguard Worker if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
329*bd1f8aebSAndroid Build Coastguard Worker length = sizeof(struct sockaddr_in);
330*bd1f8aebSAndroid Build Coastguard Worker cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
331*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)NULL, &length);
332*bd1f8aebSAndroid Build Coastguard Worker if (cc < 0)
333*bd1f8aebSAndroid Build Coastguard Worker return -1;
334*bd1f8aebSAndroid Build Coastguard Worker goto empty;
335*bd1f8aebSAndroid Build Coastguard Worker }
336*bd1f8aebSAndroid Build Coastguard Worker
337*bd1f8aebSAndroid Build Coastguard Worker /*
338*bd1f8aebSAndroid Build Coastguard Worker * To measure the difference, select MSGS messages whose round-trip
339*bd1f8aebSAndroid Build Coastguard Worker * time is smaller than RANGE if ckrange is 1, otherwise simply
340*bd1f8aebSAndroid Build Coastguard Worker * select MSGS messages regardless of round-trip transmission time.
341*bd1f8aebSAndroid Build Coastguard Worker * Choose the smallest transmission time in each of the two directions.
342*bd1f8aebSAndroid Build Coastguard Worker * Use these two latter quantities to compute the delta between
343*bd1f8aebSAndroid Build Coastguard Worker * the two clocks.
344*bd1f8aebSAndroid Build Coastguard Worker */
345*bd1f8aebSAndroid Build Coastguard Worker
346*bd1f8aebSAndroid Build Coastguard Worker length = sizeof(struct sockaddr_in);
347*bd1f8aebSAndroid Build Coastguard Worker oicp->type = ICMP_ECHO;
348*bd1f8aebSAndroid Build Coastguard Worker oicp->code = 0;
349*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = 0;
350*bd1f8aebSAndroid Build Coastguard Worker oicp->un.echo.id = id;
351*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[0] = 0;
352*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[1] = 0;
353*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[2] = 0;
354*bd1f8aebSAndroid Build Coastguard Worker
355*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
356*bd1f8aebSAndroid Build Coastguard Worker msgcount = 0;
357*bd1f8aebSAndroid Build Coastguard Worker
358*bd1f8aebSAndroid Build Coastguard Worker acked = seqno = seqno0 = 0;
359*bd1f8aebSAndroid Build Coastguard Worker
360*bd1f8aebSAndroid Build Coastguard Worker for (msgcount = 0; msgcount < MSGS; ) {
361*bd1f8aebSAndroid Build Coastguard Worker
362*bd1f8aebSAndroid Build Coastguard Worker /*
363*bd1f8aebSAndroid Build Coastguard Worker * If no answer is received for TRIALS consecutive times,
364*bd1f8aebSAndroid Build Coastguard Worker * the machine is assumed to be down
365*bd1f8aebSAndroid Build Coastguard Worker */
366*bd1f8aebSAndroid Build Coastguard Worker if ( seqno - acked > TRIALS) {
367*bd1f8aebSAndroid Build Coastguard Worker errno = EHOSTDOWN;
368*bd1f8aebSAndroid Build Coastguard Worker return HOSTDOWN;
369*bd1f8aebSAndroid Build Coastguard Worker }
370*bd1f8aebSAndroid Build Coastguard Worker oicp->un.echo.sequence = ++seqno;
371*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = 0;
372*bd1f8aebSAndroid Build Coastguard Worker
373*bd1f8aebSAndroid Build Coastguard Worker gettimeofday (&tv1, NULL);
374*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(oicp+1))[0] = htonl((tv1.tv_sec % (24*60*60)) * 1000
375*bd1f8aebSAndroid Build Coastguard Worker + tv1.tv_usec / 1000);
376*bd1f8aebSAndroid Build Coastguard Worker oicp->checksum = in_cksum((u_short *)oicp, sizeof(*oicp)+12);
377*bd1f8aebSAndroid Build Coastguard Worker
378*bd1f8aebSAndroid Build Coastguard Worker count = sendto(sock_raw, (char *)opacket, sizeof(*oicp)+12, 0,
379*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)addr, sizeof(struct sockaddr_in));
380*bd1f8aebSAndroid Build Coastguard Worker
381*bd1f8aebSAndroid Build Coastguard Worker if (count < 0) {
382*bd1f8aebSAndroid Build Coastguard Worker errno = EHOSTUNREACH;
383*bd1f8aebSAndroid Build Coastguard Worker return UNREACHABLE;
384*bd1f8aebSAndroid Build Coastguard Worker }
385*bd1f8aebSAndroid Build Coastguard Worker
386*bd1f8aebSAndroid Build Coastguard Worker for (;;) {
387*bd1f8aebSAndroid Build Coastguard Worker FD_ZERO(&ready);
388*bd1f8aebSAndroid Build Coastguard Worker FD_SET(sock_raw, &ready);
389*bd1f8aebSAndroid Build Coastguard Worker {
390*bd1f8aebSAndroid Build Coastguard Worker long tmo = rtt + rtt_sigma;
391*bd1f8aebSAndroid Build Coastguard Worker tout.tv_sec = tmo/1000;
392*bd1f8aebSAndroid Build Coastguard Worker tout.tv_usec = (tmo - (tmo/1000)*1000)*1000;
393*bd1f8aebSAndroid Build Coastguard Worker }
394*bd1f8aebSAndroid Build Coastguard Worker
395*bd1f8aebSAndroid Build Coastguard Worker if ((count = select(FD_SETSIZE, &ready, (fd_set *)0,
396*bd1f8aebSAndroid Build Coastguard Worker (fd_set *)0, &tout)) <= 0)
397*bd1f8aebSAndroid Build Coastguard Worker break;
398*bd1f8aebSAndroid Build Coastguard Worker
399*bd1f8aebSAndroid Build Coastguard Worker (void)gettimeofday(&tv1, (struct timezone *)0);
400*bd1f8aebSAndroid Build Coastguard Worker cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,
401*bd1f8aebSAndroid Build Coastguard Worker (struct sockaddr *)NULL, &length);
402*bd1f8aebSAndroid Build Coastguard Worker
403*bd1f8aebSAndroid Build Coastguard Worker if (cc < 0)
404*bd1f8aebSAndroid Build Coastguard Worker return(-1);
405*bd1f8aebSAndroid Build Coastguard Worker
406*bd1f8aebSAndroid Build Coastguard Worker icp = (struct icmphdr *)(packet + (ip->ihl << 2));
407*bd1f8aebSAndroid Build Coastguard Worker if (icp->type == ICMP_ECHOREPLY &&
408*bd1f8aebSAndroid Build Coastguard Worker packet[20] == IPOPT_TIMESTAMP &&
409*bd1f8aebSAndroid Build Coastguard Worker icp->un.echo.id == id &&
410*bd1f8aebSAndroid Build Coastguard Worker icp->un.echo.sequence >= seqno0 &&
411*bd1f8aebSAndroid Build Coastguard Worker icp->un.echo.sequence <= seqno) {
412*bd1f8aebSAndroid Build Coastguard Worker int i;
413*bd1f8aebSAndroid Build Coastguard Worker __u8 *opt = packet+20;
414*bd1f8aebSAndroid Build Coastguard Worker
415*bd1f8aebSAndroid Build Coastguard Worker if (acked < icp->un.echo.sequence)
416*bd1f8aebSAndroid Build Coastguard Worker acked = icp->un.echo.sequence;
417*bd1f8aebSAndroid Build Coastguard Worker if ((opt[3]&0xF) != IPOPT_TS_PRESPEC) {
418*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Wrong timestamp %d\n", opt[3]&0xF);
419*bd1f8aebSAndroid Build Coastguard Worker return NONSTDTIME;
420*bd1f8aebSAndroid Build Coastguard Worker }
421*bd1f8aebSAndroid Build Coastguard Worker if (opt[3]>>4) {
422*bd1f8aebSAndroid Build Coastguard Worker if ((opt[3]>>4) != 1 || ip_opt_len != 4+3*8)
423*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Overflow %d hops\n", opt[3]>>4);
424*bd1f8aebSAndroid Build Coastguard Worker }
425*bd1f8aebSAndroid Build Coastguard Worker sendtime = recvtime = histime = histime1 = 0;
426*bd1f8aebSAndroid Build Coastguard Worker for (i=0; i < (opt[2]-5)/8; i++) {
427*bd1f8aebSAndroid Build Coastguard Worker __u32 *timep = (__u32*)(opt+4+i*8+4);
428*bd1f8aebSAndroid Build Coastguard Worker __u32 t = ntohl(*timep);
429*bd1f8aebSAndroid Build Coastguard Worker
430*bd1f8aebSAndroid Build Coastguard Worker if (t & 0x80000000)
431*bd1f8aebSAndroid Build Coastguard Worker return NONSTDTIME;
432*bd1f8aebSAndroid Build Coastguard Worker
433*bd1f8aebSAndroid Build Coastguard Worker if (i == 0)
434*bd1f8aebSAndroid Build Coastguard Worker sendtime = t;
435*bd1f8aebSAndroid Build Coastguard Worker if (i == 1)
436*bd1f8aebSAndroid Build Coastguard Worker histime = histime1 = t;
437*bd1f8aebSAndroid Build Coastguard Worker if (i == 2) {
438*bd1f8aebSAndroid Build Coastguard Worker if (ip_opt_len == 4+4*8)
439*bd1f8aebSAndroid Build Coastguard Worker histime1 = t;
440*bd1f8aebSAndroid Build Coastguard Worker else
441*bd1f8aebSAndroid Build Coastguard Worker recvtime = t;
442*bd1f8aebSAndroid Build Coastguard Worker }
443*bd1f8aebSAndroid Build Coastguard Worker if (i == 3)
444*bd1f8aebSAndroid Build Coastguard Worker recvtime = t;
445*bd1f8aebSAndroid Build Coastguard Worker }
446*bd1f8aebSAndroid Build Coastguard Worker
447*bd1f8aebSAndroid Build Coastguard Worker if (!(sendtime&histime&histime1&recvtime)) {
448*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "wrong timestamps\n");
449*bd1f8aebSAndroid Build Coastguard Worker return -1;
450*bd1f8aebSAndroid Build Coastguard Worker }
451*bd1f8aebSAndroid Build Coastguard Worker
452*bd1f8aebSAndroid Build Coastguard Worker diff = recvtime - sendtime;
453*bd1f8aebSAndroid Build Coastguard Worker /*
454*bd1f8aebSAndroid Build Coastguard Worker * diff can be less than 0 aroud midnight
455*bd1f8aebSAndroid Build Coastguard Worker */
456*bd1f8aebSAndroid Build Coastguard Worker if (diff < 0)
457*bd1f8aebSAndroid Build Coastguard Worker continue;
458*bd1f8aebSAndroid Build Coastguard Worker rtt = (rtt * 3 + diff)/4;
459*bd1f8aebSAndroid Build Coastguard Worker rtt_sigma = (rtt_sigma *3 + abs(diff-rtt))/4;
460*bd1f8aebSAndroid Build Coastguard Worker msgcount++;
461*bd1f8aebSAndroid Build Coastguard Worker
462*bd1f8aebSAndroid Build Coastguard Worker if (interactive) {
463*bd1f8aebSAndroid Build Coastguard Worker printf(".");
464*bd1f8aebSAndroid Build Coastguard Worker fflush(stdout);
465*bd1f8aebSAndroid Build Coastguard Worker }
466*bd1f8aebSAndroid Build Coastguard Worker
467*bd1f8aebSAndroid Build Coastguard Worker delta1 = histime - sendtime;
468*bd1f8aebSAndroid Build Coastguard Worker /*
469*bd1f8aebSAndroid Build Coastguard Worker * Handles wrap-around to avoid that around
470*bd1f8aebSAndroid Build Coastguard Worker * midnight small time differences appear
471*bd1f8aebSAndroid Build Coastguard Worker * enormous. However, the two machine's clocks
472*bd1f8aebSAndroid Build Coastguard Worker * must be within 12 hours from each other.
473*bd1f8aebSAndroid Build Coastguard Worker */
474*bd1f8aebSAndroid Build Coastguard Worker if (delta1 < BIASN)
475*bd1f8aebSAndroid Build Coastguard Worker delta1 += MODULO;
476*bd1f8aebSAndroid Build Coastguard Worker else if (delta1 > BIASP)
477*bd1f8aebSAndroid Build Coastguard Worker delta1 -= MODULO;
478*bd1f8aebSAndroid Build Coastguard Worker
479*bd1f8aebSAndroid Build Coastguard Worker delta2 = recvtime - histime1;
480*bd1f8aebSAndroid Build Coastguard Worker if (delta2 < BIASN)
481*bd1f8aebSAndroid Build Coastguard Worker delta2 += MODULO;
482*bd1f8aebSAndroid Build Coastguard Worker else if (delta2 > BIASP)
483*bd1f8aebSAndroid Build Coastguard Worker delta2 -= MODULO;
484*bd1f8aebSAndroid Build Coastguard Worker
485*bd1f8aebSAndroid Build Coastguard Worker if (delta1 < min1)
486*bd1f8aebSAndroid Build Coastguard Worker min1 = delta1;
487*bd1f8aebSAndroid Build Coastguard Worker if (delta2 < min2)
488*bd1f8aebSAndroid Build Coastguard Worker min2 = delta2;
489*bd1f8aebSAndroid Build Coastguard Worker if (delta1 + delta2 < min_rtt) {
490*bd1f8aebSAndroid Build Coastguard Worker min_rtt = delta1 + delta2;
491*bd1f8aebSAndroid Build Coastguard Worker measure_delta1 = (delta1 - delta2)/2 + PROCESSING_TIME;
492*bd1f8aebSAndroid Build Coastguard Worker }
493*bd1f8aebSAndroid Build Coastguard Worker if (diff < RANGE) {
494*bd1f8aebSAndroid Build Coastguard Worker min1 = delta1;
495*bd1f8aebSAndroid Build Coastguard Worker min2 = delta2;
496*bd1f8aebSAndroid Build Coastguard Worker goto good_exit;
497*bd1f8aebSAndroid Build Coastguard Worker }
498*bd1f8aebSAndroid Build Coastguard Worker }
499*bd1f8aebSAndroid Build Coastguard Worker }
500*bd1f8aebSAndroid Build Coastguard Worker }
501*bd1f8aebSAndroid Build Coastguard Worker
502*bd1f8aebSAndroid Build Coastguard Worker good_exit:
503*bd1f8aebSAndroid Build Coastguard Worker measure_delta = (min1 - min2)/2 + PROCESSING_TIME;
504*bd1f8aebSAndroid Build Coastguard Worker return GOOD;
505*bd1f8aebSAndroid Build Coastguard Worker }
506*bd1f8aebSAndroid Build Coastguard Worker
507*bd1f8aebSAndroid Build Coastguard Worker
508*bd1f8aebSAndroid Build Coastguard Worker /*
509*bd1f8aebSAndroid Build Coastguard Worker * Clockdiff computes the difference between the time of the machine on
510*bd1f8aebSAndroid Build Coastguard Worker * which it is called and the time of the machines given as argument.
511*bd1f8aebSAndroid Build Coastguard Worker * The time differences measured by clockdiff are obtained using a sequence
512*bd1f8aebSAndroid Build Coastguard Worker * of ICMP TSTAMP messages which are returned to the sender by the IP module
513*bd1f8aebSAndroid Build Coastguard Worker * in the remote machine.
514*bd1f8aebSAndroid Build Coastguard Worker * In order to compare clocks of machines in different time zones, the time
515*bd1f8aebSAndroid Build Coastguard Worker * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
516*bd1f8aebSAndroid Build Coastguard Worker * If a hosts uses a different time format, it should set the high order
517*bd1f8aebSAndroid Build Coastguard Worker * bit of the 32-bit quantity it transmits.
518*bd1f8aebSAndroid Build Coastguard Worker * However, VMS apparently transmits the time in milliseconds since midnight
519*bd1f8aebSAndroid Build Coastguard Worker * local time (rather than GMT) without setting the high order bit.
520*bd1f8aebSAndroid Build Coastguard Worker * Furthermore, it does not understand daylight-saving time. This makes
521*bd1f8aebSAndroid Build Coastguard Worker * clockdiff behaving inconsistently with hosts running VMS.
522*bd1f8aebSAndroid Build Coastguard Worker *
523*bd1f8aebSAndroid Build Coastguard Worker * In order to reduce the sensitivity to the variance of message transmission
524*bd1f8aebSAndroid Build Coastguard Worker * time, clockdiff sends a sequence of messages. Yet, measures between
525*bd1f8aebSAndroid Build Coastguard Worker * two `distant' hosts can be affected by a small error. The error can, however,
526*bd1f8aebSAndroid Build Coastguard Worker * be reduced by increasing the number of messages sent in each measurement.
527*bd1f8aebSAndroid Build Coastguard Worker */
528*bd1f8aebSAndroid Build Coastguard Worker
529*bd1f8aebSAndroid Build Coastguard Worker void
usage()530*bd1f8aebSAndroid Build Coastguard Worker usage() {
531*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "Usage: clockdiff [-o] <host>\n");
532*bd1f8aebSAndroid Build Coastguard Worker exit(1);
533*bd1f8aebSAndroid Build Coastguard Worker }
534*bd1f8aebSAndroid Build Coastguard Worker
drop_rights(void)535*bd1f8aebSAndroid Build Coastguard Worker void drop_rights(void) {
536*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
537*bd1f8aebSAndroid Build Coastguard Worker cap_t caps = cap_init();
538*bd1f8aebSAndroid Build Coastguard Worker if (cap_set_proc(caps)) {
539*bd1f8aebSAndroid Build Coastguard Worker perror("clockdiff: cap_set_proc");
540*bd1f8aebSAndroid Build Coastguard Worker exit(-1);
541*bd1f8aebSAndroid Build Coastguard Worker }
542*bd1f8aebSAndroid Build Coastguard Worker cap_free(caps);
543*bd1f8aebSAndroid Build Coastguard Worker #endif
544*bd1f8aebSAndroid Build Coastguard Worker if (setuid(getuid())) {
545*bd1f8aebSAndroid Build Coastguard Worker perror("clockdiff: setuid");
546*bd1f8aebSAndroid Build Coastguard Worker exit(-1);
547*bd1f8aebSAndroid Build Coastguard Worker }
548*bd1f8aebSAndroid Build Coastguard Worker }
549*bd1f8aebSAndroid Build Coastguard Worker
550*bd1f8aebSAndroid Build Coastguard Worker int
main(int argc,char * argv[])551*bd1f8aebSAndroid Build Coastguard Worker main(int argc, char *argv[])
552*bd1f8aebSAndroid Build Coastguard Worker {
553*bd1f8aebSAndroid Build Coastguard Worker int measure_status;
554*bd1f8aebSAndroid Build Coastguard Worker struct hostent * hp;
555*bd1f8aebSAndroid Build Coastguard Worker char hostname[MAX_HOSTNAMELEN];
556*bd1f8aebSAndroid Build Coastguard Worker int s_errno = 0;
557*bd1f8aebSAndroid Build Coastguard Worker int n_errno = 0;
558*bd1f8aebSAndroid Build Coastguard Worker
559*bd1f8aebSAndroid Build Coastguard Worker if (argc < 2) {
560*bd1f8aebSAndroid Build Coastguard Worker drop_rights();
561*bd1f8aebSAndroid Build Coastguard Worker usage();
562*bd1f8aebSAndroid Build Coastguard Worker }
563*bd1f8aebSAndroid Build Coastguard Worker
564*bd1f8aebSAndroid Build Coastguard Worker sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
565*bd1f8aebSAndroid Build Coastguard Worker s_errno = errno;
566*bd1f8aebSAndroid Build Coastguard Worker
567*bd1f8aebSAndroid Build Coastguard Worker errno = 0;
568*bd1f8aebSAndroid Build Coastguard Worker if (nice(-16) == -1)
569*bd1f8aebSAndroid Build Coastguard Worker n_errno = errno;
570*bd1f8aebSAndroid Build Coastguard Worker drop_rights();
571*bd1f8aebSAndroid Build Coastguard Worker
572*bd1f8aebSAndroid Build Coastguard Worker if (argc == 3) {
573*bd1f8aebSAndroid Build Coastguard Worker if (strcmp(argv[1], "-o") == 0) {
574*bd1f8aebSAndroid Build Coastguard Worker ip_opt_len = 4 + 4*8;
575*bd1f8aebSAndroid Build Coastguard Worker argv++;
576*bd1f8aebSAndroid Build Coastguard Worker } else if (strcmp(argv[1], "-o1") == 0) {
577*bd1f8aebSAndroid Build Coastguard Worker ip_opt_len = 4 + 3*8;
578*bd1f8aebSAndroid Build Coastguard Worker argv++;
579*bd1f8aebSAndroid Build Coastguard Worker } else
580*bd1f8aebSAndroid Build Coastguard Worker usage();
581*bd1f8aebSAndroid Build Coastguard Worker } else if (argc != 2)
582*bd1f8aebSAndroid Build Coastguard Worker usage();
583*bd1f8aebSAndroid Build Coastguard Worker
584*bd1f8aebSAndroid Build Coastguard Worker if (sock_raw < 0) {
585*bd1f8aebSAndroid Build Coastguard Worker errno = s_errno;
586*bd1f8aebSAndroid Build Coastguard Worker perror("clockdiff: socket");
587*bd1f8aebSAndroid Build Coastguard Worker exit(1);
588*bd1f8aebSAndroid Build Coastguard Worker }
589*bd1f8aebSAndroid Build Coastguard Worker
590*bd1f8aebSAndroid Build Coastguard Worker if (n_errno < 0) {
591*bd1f8aebSAndroid Build Coastguard Worker errno = n_errno;
592*bd1f8aebSAndroid Build Coastguard Worker perror("clockdiff: nice");
593*bd1f8aebSAndroid Build Coastguard Worker exit(1);
594*bd1f8aebSAndroid Build Coastguard Worker }
595*bd1f8aebSAndroid Build Coastguard Worker
596*bd1f8aebSAndroid Build Coastguard Worker if (isatty(fileno(stdin)) && isatty(fileno(stdout)))
597*bd1f8aebSAndroid Build Coastguard Worker interactive = 1;
598*bd1f8aebSAndroid Build Coastguard Worker
599*bd1f8aebSAndroid Build Coastguard Worker id = getpid();
600*bd1f8aebSAndroid Build Coastguard Worker
601*bd1f8aebSAndroid Build Coastguard Worker (void)gethostname(hostname,sizeof(hostname));
602*bd1f8aebSAndroid Build Coastguard Worker hp = gethostbyname(hostname);
603*bd1f8aebSAndroid Build Coastguard Worker if (hp == NULL) {
604*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "clockdiff: %s: my host not found\n", hostname);
605*bd1f8aebSAndroid Build Coastguard Worker exit(1);
606*bd1f8aebSAndroid Build Coastguard Worker }
607*bd1f8aebSAndroid Build Coastguard Worker myname = strdup(hp->h_name);
608*bd1f8aebSAndroid Build Coastguard Worker
609*bd1f8aebSAndroid Build Coastguard Worker hp = gethostbyname(argv[1]);
610*bd1f8aebSAndroid Build Coastguard Worker if (hp == NULL) {
611*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "clockdiff: %s: host not found\n", argv[1]);
612*bd1f8aebSAndroid Build Coastguard Worker exit(1);
613*bd1f8aebSAndroid Build Coastguard Worker }
614*bd1f8aebSAndroid Build Coastguard Worker hisname = strdup(hp->h_name);
615*bd1f8aebSAndroid Build Coastguard Worker
616*bd1f8aebSAndroid Build Coastguard Worker memset(&server, 0, sizeof(server));
617*bd1f8aebSAndroid Build Coastguard Worker server.sin_family = hp->h_addrtype;
618*bd1f8aebSAndroid Build Coastguard Worker memcpy(&(server.sin_addr.s_addr), hp->h_addr, 4);
619*bd1f8aebSAndroid Build Coastguard Worker
620*bd1f8aebSAndroid Build Coastguard Worker if (connect(sock_raw, (struct sockaddr*)&server, sizeof(server)) == -1) {
621*bd1f8aebSAndroid Build Coastguard Worker perror("connect");
622*bd1f8aebSAndroid Build Coastguard Worker exit(1);
623*bd1f8aebSAndroid Build Coastguard Worker }
624*bd1f8aebSAndroid Build Coastguard Worker if (ip_opt_len) {
625*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in myaddr;
626*bd1f8aebSAndroid Build Coastguard Worker socklen_t addrlen = sizeof(myaddr);
627*bd1f8aebSAndroid Build Coastguard Worker unsigned char rspace[ip_opt_len];
628*bd1f8aebSAndroid Build Coastguard Worker
629*bd1f8aebSAndroid Build Coastguard Worker memset(rspace, 0, sizeof(rspace));
630*bd1f8aebSAndroid Build Coastguard Worker rspace[0] = IPOPT_TIMESTAMP;
631*bd1f8aebSAndroid Build Coastguard Worker rspace[1] = ip_opt_len;
632*bd1f8aebSAndroid Build Coastguard Worker rspace[2] = 5;
633*bd1f8aebSAndroid Build Coastguard Worker rspace[3] = IPOPT_TS_PRESPEC;
634*bd1f8aebSAndroid Build Coastguard Worker if (getsockname(sock_raw, (struct sockaddr*)&myaddr, &addrlen) == -1) {
635*bd1f8aebSAndroid Build Coastguard Worker perror("getsockname");
636*bd1f8aebSAndroid Build Coastguard Worker exit(1);
637*bd1f8aebSAndroid Build Coastguard Worker }
638*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(rspace+4))[0*2] = myaddr.sin_addr.s_addr;
639*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(rspace+4))[1*2] = server.sin_addr.s_addr;
640*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(rspace+4))[2*2] = myaddr.sin_addr.s_addr;
641*bd1f8aebSAndroid Build Coastguard Worker if (ip_opt_len == 4+4*8) {
642*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(rspace+4))[2*2] = server.sin_addr.s_addr;
643*bd1f8aebSAndroid Build Coastguard Worker ((__u32*)(rspace+4))[3*2] = myaddr.sin_addr.s_addr;
644*bd1f8aebSAndroid Build Coastguard Worker }
645*bd1f8aebSAndroid Build Coastguard Worker
646*bd1f8aebSAndroid Build Coastguard Worker if (setsockopt(sock_raw, IPPROTO_IP, IP_OPTIONS, rspace, ip_opt_len) < 0) {
647*bd1f8aebSAndroid Build Coastguard Worker perror("ping: IP_OPTIONS (fallback to icmp tstamps)");
648*bd1f8aebSAndroid Build Coastguard Worker ip_opt_len = 0;
649*bd1f8aebSAndroid Build Coastguard Worker }
650*bd1f8aebSAndroid Build Coastguard Worker }
651*bd1f8aebSAndroid Build Coastguard Worker
652*bd1f8aebSAndroid Build Coastguard Worker if ((measure_status = (ip_opt_len ? measure_opt : measure)(&server)) < 0) {
653*bd1f8aebSAndroid Build Coastguard Worker if (errno)
654*bd1f8aebSAndroid Build Coastguard Worker perror("measure");
655*bd1f8aebSAndroid Build Coastguard Worker else
656*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "measure: unknown failure\n");
657*bd1f8aebSAndroid Build Coastguard Worker exit(1);
658*bd1f8aebSAndroid Build Coastguard Worker }
659*bd1f8aebSAndroid Build Coastguard Worker
660*bd1f8aebSAndroid Build Coastguard Worker switch (measure_status) {
661*bd1f8aebSAndroid Build Coastguard Worker case HOSTDOWN:
662*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "%s is down\n", hisname);
663*bd1f8aebSAndroid Build Coastguard Worker exit(1);
664*bd1f8aebSAndroid Build Coastguard Worker case NONSTDTIME:
665*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "%s time transmitted in a non-standard format\n", hisname);
666*bd1f8aebSAndroid Build Coastguard Worker exit(1);
667*bd1f8aebSAndroid Build Coastguard Worker case UNREACHABLE:
668*bd1f8aebSAndroid Build Coastguard Worker fprintf(stderr, "%s is unreachable\n", hisname);
669*bd1f8aebSAndroid Build Coastguard Worker exit(1);
670*bd1f8aebSAndroid Build Coastguard Worker default:
671*bd1f8aebSAndroid Build Coastguard Worker break;
672*bd1f8aebSAndroid Build Coastguard Worker }
673*bd1f8aebSAndroid Build Coastguard Worker
674*bd1f8aebSAndroid Build Coastguard Worker
675*bd1f8aebSAndroid Build Coastguard Worker {
676*bd1f8aebSAndroid Build Coastguard Worker time_t now = time(NULL);
677*bd1f8aebSAndroid Build Coastguard Worker
678*bd1f8aebSAndroid Build Coastguard Worker if (interactive)
679*bd1f8aebSAndroid Build Coastguard Worker printf("\nhost=%s rtt=%ld(%ld)ms/%ldms delta=%dms/%dms %s", hisname,
680*bd1f8aebSAndroid Build Coastguard Worker rtt, rtt_sigma, min_rtt,
681*bd1f8aebSAndroid Build Coastguard Worker measure_delta, measure_delta1,
682*bd1f8aebSAndroid Build Coastguard Worker ctime(&now));
683*bd1f8aebSAndroid Build Coastguard Worker else
684*bd1f8aebSAndroid Build Coastguard Worker printf("%ld %d %d\n", now, measure_delta, measure_delta1);
685*bd1f8aebSAndroid Build Coastguard Worker }
686*bd1f8aebSAndroid Build Coastguard Worker exit(0);
687*bd1f8aebSAndroid Build Coastguard Worker }
688