xref: /aosp_15_r20/external/iputils/clockdiff.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
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