xref: /csrg-svn/usr.sbin/timed/timedc/cmds.c (revision 33123)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)cmds.c	2.4 (Berkeley) 12/23/87";
15 #endif /* not lint */
16 
17 #include "timedc.h"
18 #include <netinet/in_systm.h>
19 #include <netinet/ip.h>
20 #include <netinet/ip_icmp.h>
21 #define TSPTYPES
22 #include <protocols/timed.h>
23 #include <sys/file.h>
24 
25 int id;
26 int sock;
27 int sock_raw;
28 char hostname[MAXHOSTNAMELEN];
29 struct hostent *hp, *gethostbyname();
30 struct sockaddr_in server;
31 extern int measure_delta;
32 int bytenetorder(), bytehostorder();
33 char *strcpy();
34 
35 /*
36  * Clockdiff computes the difference between the time of the machine on
37  * which it is called and the time of the machines given as argument.
38  * The time differences measured by clockdiff are obtained using a sequence
39  * of ICMP TSTAMP messages which are returned to the sender by the IP module
40  * in the remote machine.
41  * In order to compare clocks of machines in different time zones, the time
42  * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
43  * If a hosts uses a different time format, it should set the high order
44  * bit of the 32-bit quantity it transmits.
45  * However, VMS apparently transmits the time in milliseconds since midnight
46  * local time (rather than GMT) without setting the high order bit.
47  * Furthermore, it does not understand daylight-saving time.  This makes
48  * clockdiff behaving inconsistently with hosts running VMS.
49  *
50  * In order to reduce the sensitivity to the variance of message transmission
51  * time, clockdiff sends a sequence of messages.  Yet, measures between
52  * two `distant' hosts can be affected by a small error. The error can, however,
53  * be reduced by increasing the number of messages sent in each measurement.
54  */
55 
56 clockdiff(argc, argv)
57 int argc;
58 char *argv[];
59 {
60 	int measure_status;
61 	struct timeval ack;
62 	int measure();
63 
64 	if(argc < 2)  {
65 		printf("Usage: clockdiff host ... \n");
66 		return;
67 	}
68 
69 	id = getpid();
70 	(void)gethostname(hostname,sizeof(hostname));
71 
72 	while (argc > 1) {
73 		argc--; argv++;
74 		hp = gethostbyname(*argv);
75 		if (hp == NULL) {
76 			printf("%s: unknown host\n", *argv);
77 			continue;
78 		}
79 		server.sin_family = hp->h_addrtype;
80 		bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length);
81 		ack.tv_sec = 10;
82 		ack.tv_usec = 0;
83 		if ((measure_status = measure(&ack, &server)) < 0) {
84 			perror("measure");
85 			return;
86 		}
87 		switch (measure_status) {
88 
89 		case HOSTDOWN:
90 			printf("%s is down\n", hp->h_name);
91 			continue;
92 			break;
93 		case NONSTDTIME:
94 			printf("%s time transmitted in a non-standard format\n",						 hp->h_name);
95 			continue;
96 			break;
97 		case UNREACHABLE:
98 			printf("%s is unreachable\n", hp->h_name);
99 			continue;
100 			break;
101 		default:
102 			break;
103 		}
104 
105 		if (measure_delta > 0)
106 			printf("time on %s is %d ms. ahead of time on %s\n",
107 						hp->h_name, measure_delta,
108 						hostname);
109 		else
110 			if (measure_delta == 0)
111 		      		printf("%s and %s have the same time\n",
112 						hp->h_name, hostname);
113 			else
114 		      	     printf("time on %s is %d ms. behind time on %s\n",
115 					hp->h_name, -measure_delta, hostname);
116 	}
117 	return;
118 }
119 /*
120  * finds location of master timedaemon
121  */
122 
123 msite(argc)
124 int argc;
125 {
126 	int length;
127 	int cc;
128 	fd_set ready;
129 	struct sockaddr_in dest;
130 	struct timeval tout;
131 	struct sockaddr_in from;
132 	struct tsp msg;
133 	struct servent *srvp;
134 
135 	if (argc != 1) {
136 		printf("Usage: msite\n");
137 		return;
138 	}
139 
140 	srvp = getservbyname("timed", "udp");
141 	if (srvp == 0) {
142 		fprintf(stderr, "udp/timed: unknown service\n");
143 		return;
144 	}
145 	dest.sin_port = srvp->s_port;
146 	dest.sin_family = AF_INET;
147 
148 	(void)gethostname(hostname,sizeof(hostname));
149 	hp = gethostbyname(hostname);
150 	if (hp == NULL) {
151 		perror("gethostbyname");
152 		return;
153 	}
154 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
155 
156 	(void)strcpy(msg.tsp_name, hostname);
157 	msg.tsp_type = TSP_MSITE;
158 	msg.tsp_vers = TSPVERSION;
159 	bytenetorder(&msg);
160 	length = sizeof(struct sockaddr_in);
161 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
162 						&dest, length) < 0) {
163 		perror("sendto");
164 		return;
165 	}
166 
167 	tout.tv_sec = 15;
168 	tout.tv_usec = 0;
169 	FD_ZERO(&ready);
170 	FD_SET(sock, &ready);
171 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
172 		length = sizeof(struct sockaddr_in);
173 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
174 							&from, &length);
175 		if (cc < 0) {
176 			perror("recvfrom");
177 			return;
178 		}
179 		bytehostorder(&msg);
180 		if (msg.tsp_type == TSP_ACK)
181 			printf("master timedaemon runs on %s\n", msg.tsp_name);
182 		else
183 			printf("received wrong ack: %s\n",
184 						tsptype[msg.tsp_type]);
185 	} else
186 		printf("communication error\n");
187 }
188 
189 /*
190  * quits timedc
191  */
192 
193 quit()
194 {
195 	exit(0);
196 }
197 
198 #define MAXH	4	/* max no. of hosts where election can occur */
199 
200 /*
201  * Causes the election timer to expire on the selected hosts
202  * It sends just one udp message per machine, relying on
203  * reliability of communication channel.
204  */
205 
206 testing(argc, argv)
207 int argc;
208 char *argv[];
209 {
210 	int length;
211 	int nhosts;
212 	struct servent *srvp;
213 	struct sockaddr_in sin[MAXH];
214 	struct tsp msg;
215 
216 	if(argc < 2)  {
217 		printf("Usage: testing host ...\n");
218 		return;
219 	}
220 
221 	srvp = getservbyname("timed", "udp");
222 	if (srvp == 0) {
223 		fprintf(stderr, "udp/timed: unknown service\n");
224 		return;
225 	}
226 
227 	nhosts = 0;
228 	while (argc > 1) {
229 		argc--; argv++;
230 		hp = gethostbyname(*argv);
231 		if (hp == NULL) {
232 			printf("%s: unknown host\n", *argv);
233 			argc--; argv++;
234 			continue;
235 		}
236 		sin[nhosts].sin_port = srvp->s_port;
237 		sin[nhosts].sin_family = hp->h_addrtype;
238 		bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length);
239 		if (++nhosts == MAXH)
240 			break;
241 	}
242 
243 	msg.tsp_type = TSP_TEST;
244 	msg.tsp_vers = TSPVERSION;
245 	(void)gethostname(hostname, sizeof(hostname));
246 	(void)strcpy(msg.tsp_name, hostname);
247 	bytenetorder(&msg);	/* it is not really necessary here */
248 	while (nhosts-- > 0) {
249 		length = sizeof(struct sockaddr_in);
250 		if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
251 						&sin[nhosts], length) < 0) {
252 			perror("sendto");
253 			return;
254 		}
255 	}
256 }
257 
258 /*
259  * Enables or disables tracing on local timedaemon
260  */
261 
262 tracing(argc, argv)
263 int argc;
264 char *argv[];
265 {
266 	int onflag;
267 	int length;
268 	int cc;
269 	fd_set ready;
270 	struct sockaddr_in dest;
271 	struct timeval tout;
272 	struct sockaddr_in from;
273 	struct tsp msg;
274 	struct servent *srvp;
275 
276 	if (argc != 2) {
277 		printf("Usage: tracing { on | off }\n");
278 		return;
279 	}
280 
281 	srvp = getservbyname("timed", "udp");
282 	if (srvp == 0) {
283 		fprintf(stderr, "udp/timed: unknown service\n");
284 		return;
285 	}
286 	dest.sin_port = srvp->s_port;
287 	dest.sin_family = AF_INET;
288 
289 	(void)gethostname(hostname,sizeof(hostname));
290 	hp = gethostbyname(hostname);
291 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
292 
293 	if (strcmp(argv[1], "on") == 0) {
294 		msg.tsp_type = TSP_TRACEON;
295 		onflag = ON;
296 	} else {
297 		msg.tsp_type = TSP_TRACEOFF;
298 		onflag = OFF;
299 	}
300 
301 	(void)strcpy(msg.tsp_name, hostname);
302 	msg.tsp_vers = TSPVERSION;
303 	bytenetorder(&msg);
304 	length = sizeof(struct sockaddr_in);
305 	if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
306 						&dest, length) < 0) {
307 		perror("sendto");
308 		return;
309 	}
310 
311 	tout.tv_sec = 5;
312 	tout.tv_usec = 0;
313 	FD_ZERO(&ready);
314 	FD_SET(sock, &ready);
315 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
316 		length = sizeof(struct sockaddr_in);
317 		cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
318 							&from, &length);
319 		if (cc < 0) {
320 			perror("recvfrom");
321 			return;
322 		}
323 		bytehostorder(&msg);
324 		if (msg.tsp_type == TSP_ACK)
325 			if (onflag)
326 				printf("timed tracing enabled\n");
327 			else
328 				printf("timed tracing disabled\n");
329 		else
330 			printf("wrong ack received: %s\n",
331 						tsptype[msg.tsp_type]);
332 	} else
333 		printf("communication error\n");
334 }
335 
336 priv_resources()
337 {
338 	int port;
339 	struct sockaddr_in sin;
340 
341 	sock = socket(AF_INET, SOCK_DGRAM, 0);
342 	if (sock < 0) {
343 		perror("opening socket");
344 		return(-1);
345 	}
346 
347 	sin.sin_family = AF_INET;
348 	sin.sin_addr.s_addr = 0;
349 	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
350 		sin.sin_port = htons((u_short)port);
351 		if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
352 			break;
353 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
354 			perror("bind");
355 			(void) close(sock);
356 			return(-1);
357 		}
358 	}
359 	if (port == IPPORT_RESERVED / 2) {
360 		fprintf(stderr, "all reserved ports in use\n");
361 		(void) close(sock);
362 		return(-1);
363 	}
364 
365 	sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
366 	if (sock_raw < 0)  {
367 		perror("opening raw socket");
368 		(void) close(sock_raw);
369 		return(-1);
370 	}
371 	return(1);
372 }
373