BSD 4_3 release
[unix-history] / usr / src / etc / timed / cmds.c
CommitLineData
ad4b9c34
RG
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
95f51977 8static char sccsid[] = "@(#)cmds.c 2.2 (Berkeley) 4/21/86";
ad4b9c34
RG
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
ad4b9c34
RG
19int id;
20int sock;
21int sock_raw;
86fe47ef 22char hostname[MAXHOSTNAMELEN];
ad4b9c34
RG
23struct hostent *hp, *gethostbyname();
24struct sockaddr_in server;
25extern int measure_delta;
26int bytenetorder(), bytehostorder();
27char *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
50clockdiff(argc, argv)
51int argc;
52char *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);
38d4e510
JB
75 ack.tv_sec = 10;
76 ack.tv_usec = 0;
77 if ((measure_status = measure(&ack, &server)) < 0) {
ad4b9c34
RG
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
117msite(argc)
118int argc;
119{
120 int length;
75d5ce8a
JB
121 int cc;
122 fd_set ready;
ad4b9c34
RG
123 struct sockaddr_in dest;
124 struct timeval tout;
125 struct sockaddr_in from;
126 struct tsp msg;
127 struct servent *srvp;
128
129 if (argc != 1) {
130 printf("Usage: msite\n");
131 return;
132 }
133
ad4b9c34
RG
134 srvp = getservbyname("timed", "udp");
135 if (srvp == 0) {
136 fprintf(stderr, "udp/timed: unknown service\n");
137 return;
138 }
139 dest.sin_port = srvp->s_port;
140 dest.sin_family = AF_INET;
141
142 (void)gethostname(hostname,sizeof(hostname));
143 hp = gethostbyname(hostname);
144 if (hp == NULL) {
145 perror("gethostbyname");
146 return;
147 }
148 bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
149
150 (void)strcpy(msg.tsp_name, hostname);
151 msg.tsp_type = TSP_MSITE;
152 msg.tsp_vers = TSPVERSION;
153 bytenetorder(&msg);
154 length = sizeof(struct sockaddr_in);
155 if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
156 &dest, length) < 0) {
157 perror("sendto");
158 return;
159 }
160
161 tout.tv_sec = 15;
162 tout.tv_usec = 0;
75d5ce8a
JB
163 FD_ZERO(&ready);
164 FD_SET(sock, &ready);
165 if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
ad4b9c34
RG
166 length = sizeof(struct sockaddr_in);
167 cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
168 &from, &length);
169 if (cc < 0) {
170 perror("recvfrom");
171 return;
172 }
173 bytehostorder(&msg);
174 if (msg.tsp_type == TSP_ACK)
175 printf("master timedaemon runs on %s\n", msg.tsp_name);
176 else
177 printf("received wrong ack: %s\n",
178 tsptype[msg.tsp_type]);
179 } else
180 printf("communication error\n");
181}
182
183/*
184 * quits timedc
185 */
186
187quit()
188{
189 exit(0);
190}
191
192#define MAXH 4 /* max no. of hosts where election can occur */
193
194/*
195 * Causes the election timer to expire on the selected hosts
196 * It sends just one udp message per machine, relying on
197 * reliability of communication channel.
198 */
199
200testing(argc, argv)
201int argc;
202char *argv[];
203{
204 int length;
205 int nhosts;
206 struct servent *srvp;
207 struct sockaddr_in sin[MAXH];
208 struct tsp msg;
209
210 if(argc < 2) {
211 printf("Usage: testing host ...\n");
212 return;
213 }
214
ad4b9c34
RG
215 srvp = getservbyname("timed", "udp");
216 if (srvp == 0) {
217 fprintf(stderr, "udp/timed: unknown service\n");
218 return;
219 }
220
221 nhosts = 0;
222 while (argc > 1) {
223 argc--; argv++;
224 hp = gethostbyname(*argv);
225 if (hp == NULL) {
95f51977 226 printf("%s: unknown host %s\n", *argv);
ad4b9c34
RG
227 argc--; argv++;
228 continue;
229 }
230 sin[nhosts].sin_port = srvp->s_port;
231 sin[nhosts].sin_family = hp->h_addrtype;
232 bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length);
233 if (++nhosts == MAXH)
234 break;
235 }
236
237 msg.tsp_type = TSP_TEST;
238 msg.tsp_vers = TSPVERSION;
239 (void)gethostname(hostname, sizeof(hostname));
240 (void)strcpy(msg.tsp_name, hostname);
241 bytenetorder(&msg); /* it is not really necessary here */
242 while (nhosts-- > 0) {
243 length = sizeof(struct sockaddr_in);
244 if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
245 &sin[nhosts], length) < 0) {
246 perror("sendto");
247 return;
248 }
249 }
250}
251
252/*
253 * Enables or disables tracing on local timedaemon
254 */
255
256tracing(argc, argv)
257int argc;
258char *argv[];
259{
260 int onflag;
261 int length;
75d5ce8a
JB
262 int cc;
263 fd_set ready;
ad4b9c34
RG
264 struct sockaddr_in dest;
265 struct timeval tout;
266 struct sockaddr_in from;
267 struct tsp msg;
268 struct servent *srvp;
269
270 if (argc != 2) {
271 printf("Usage: tracing { on | off }\n");
272 return;
273 }
274
ad4b9c34
RG
275 srvp = getservbyname("timed", "udp");
276 if (srvp == 0) {
277 fprintf(stderr, "udp/timed: unknown service\n");
278 return;
279 }
280 dest.sin_port = srvp->s_port;
281 dest.sin_family = AF_INET;
282
283 (void)gethostname(hostname,sizeof(hostname));
284 hp = gethostbyname(hostname);
285 bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
286
287 if (strcmp(argv[1], "on") == 0) {
288 msg.tsp_type = TSP_TRACEON;
289 onflag = ON;
290 } else {
291 msg.tsp_type = TSP_TRACEOFF;
292 onflag = OFF;
293 }
294
295 (void)strcpy(msg.tsp_name, hostname);
296 msg.tsp_vers = TSPVERSION;
297 bytenetorder(&msg);
298 length = sizeof(struct sockaddr_in);
299 if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0,
300 &dest, length) < 0) {
301 perror("sendto");
302 return;
303 }
304
305 tout.tv_sec = 5;
306 tout.tv_usec = 0;
75d5ce8a
JB
307 FD_ZERO(&ready);
308 FD_SET(sock, &ready);
309 if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
ad4b9c34
RG
310 length = sizeof(struct sockaddr_in);
311 cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0,
312 &from, &length);
313 if (cc < 0) {
314 perror("recvfrom");
315 return;
316 }
317 bytehostorder(&msg);
318 if (msg.tsp_type == TSP_ACK)
319 if (onflag)
320 printf("timed tracing enabled\n");
321 else
322 printf("timed tracing disabled\n");
323 else
324 printf("wrong ack received: %s\n",
325 tsptype[msg.tsp_type]);
326 } else
327 printf("communication error\n");
328}
329
330priv_resources()
331{
332 int port;
333 struct sockaddr_in sin;
334
335 sock = socket(AF_INET, SOCK_DGRAM, 0);
336 if (sock < 0) {
337 perror("opening socket");
338 return(-1);
339 }
340
341 sin.sin_family = AF_INET;
342 sin.sin_addr.s_addr = 0;
343 for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
344 sin.sin_port = htons((u_short)port);
345 if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
346 break;
347 if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
348 perror("bind");
349 (void) close(sock);
350 return(-1);
351 }
352 }
353 if (port == IPPORT_RESERVED / 2) {
354 fprintf(stderr, "all reserved ports in use\n");
355 (void) close(sock);
356 return(-1);
357 }
358
359 sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
360 if (sock_raw < 0) {
361 perror("opening raw socket");
362 (void) close(sock_raw);
363 return(-1);
364 }
365 return(1);
366}