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