xref: /original-bsd/usr.sbin/timed/timedc/cmds.c (revision 5843bbc1)
1e9f1ce36Sbostic /*-
224002341Sbostic  * Copyright (c) 1985, 1993
324002341Sbostic  *	The Regents of the University of California.  All rights reserved.
4b0eb8cefSbostic  *
5e1a0b129Sbostic  * %sccs.include.redist.c%
6da4a32c4Sgusella  */
7da4a32c4Sgusella 
8da4a32c4Sgusella #ifndef lint
9*5843bbc1Svjs static char sccsid[] = "@(#)cmds.c	8.2 (Berkeley) 03/26/95";
10b0eb8cefSbostic #endif /* not lint */
11da4a32c4Sgusella 
12e9f1ce36Sbostic #ifdef sgi
13e9f1ce36Sbostic #ident "$Revision: 1.10 $"
14e9f1ce36Sbostic #endif
15e9f1ce36Sbostic 
16da4a32c4Sgusella #include "timedc.h"
17e9f1ce36Sbostic #include <sys/file.h>
18e9f1ce36Sbostic 
19da4a32c4Sgusella #include <netinet/in_systm.h>
20da4a32c4Sgusella #include <netinet/ip.h>
21da4a32c4Sgusella #include <netinet/ip_icmp.h>
22e9f1ce36Sbostic 
23e9f1ce36Sbostic #include <stdlib.h>
24e9f1ce36Sbostic #include <strings.h>
25e9f1ce36Sbostic #include <unistd.h>
26e9f1ce36Sbostic 
27da4a32c4Sgusella #define TSPTYPES
28da4a32c4Sgusella #include <protocols/timed.h>
29da4a32c4Sgusella 
30e9f1ce36Sbostic #ifdef sgi
31e9f1ce36Sbostic #include <bstring.h>
32e9f1ce36Sbostic #include <sys/clock.h>
33e9f1ce36Sbostic #else
34e9f1ce36Sbostic #define	SECHR	(60*60)
35e9f1ce36Sbostic #define	SECDAY	(24*SECHR)
36e9f1ce36Sbostic #endif /* sgi */
37e9f1ce36Sbostic 
38e9f1ce36Sbostic # define DATE_PROTO "udp"
39e9f1ce36Sbostic # define DATE_PORT "time"
40e9f1ce36Sbostic 
41e9f1ce36Sbostic 
42da4a32c4Sgusella int sock;
43da4a32c4Sgusella int sock_raw;
44e9f1ce36Sbostic char myname[MAXHOSTNAMELEN];
45e9f1ce36Sbostic struct hostent *hp;
46da4a32c4Sgusella struct sockaddr_in server;
47e9f1ce36Sbostic struct sockaddr_in dayaddr;
48da4a32c4Sgusella extern int measure_delta;
49e9f1ce36Sbostic 
50e9f1ce36Sbostic void bytenetorder(struct tsp *);
51e9f1ce36Sbostic void bytehostorder(struct tsp *);
52e9f1ce36Sbostic 
53e9f1ce36Sbostic 
54e9f1ce36Sbostic #define BU ((unsigned long)2208988800)	/* seconds before UNIX epoch */
55e9f1ce36Sbostic 
56e9f1ce36Sbostic 
57e9f1ce36Sbostic /* compute the difference between our date and another machine
58e9f1ce36Sbostic  */
59e9f1ce36Sbostic static int				/* difference in days from our time */
daydiff(hostname)60e9f1ce36Sbostic daydiff(hostname)
61e9f1ce36Sbostic 	char *hostname;
62e9f1ce36Sbostic {
63e9f1ce36Sbostic 	int i;
64e9f1ce36Sbostic 	int trials;
65e9f1ce36Sbostic 	struct timeval tout, now;
66e9f1ce36Sbostic 	fd_set ready;
67e9f1ce36Sbostic 	struct sockaddr from;
68e9f1ce36Sbostic 	int fromlen;
69e9f1ce36Sbostic 	unsigned long sec;
70e9f1ce36Sbostic 
71e9f1ce36Sbostic 
72e9f1ce36Sbostic 	/* wait 2 seconds between 10 tries */
73e9f1ce36Sbostic 	tout.tv_sec = 2;
74e9f1ce36Sbostic 	tout.tv_usec = 0;
75e9f1ce36Sbostic 	for (trials = 0; trials < 10; trials++) {
76e9f1ce36Sbostic 		/* ask for the time */
77e9f1ce36Sbostic 		sec = 0;
78e9f1ce36Sbostic 		if (sendto(sock, &sec, sizeof(sec), 0,
79e9f1ce36Sbostic 			   (struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) {
80e9f1ce36Sbostic 			perror("sendto(sock)");
81e9f1ce36Sbostic 			return 0;
82e9f1ce36Sbostic 		}
83e9f1ce36Sbostic 
84e9f1ce36Sbostic 		for (;;) {
85e9f1ce36Sbostic 			FD_ZERO(&ready);
86e9f1ce36Sbostic 			FD_SET(sock, &ready);
87e9f1ce36Sbostic 			i = select(sock+1, &ready, (fd_set *)0,
88e9f1ce36Sbostic 				   (fd_set *)0, &tout);
89e9f1ce36Sbostic 			if (i < 0) {
90*5843bbc1Svjs 				if (errno == EINTR)
91e9f1ce36Sbostic 					continue;
92e9f1ce36Sbostic 				perror("select(date read)");
93e9f1ce36Sbostic 				return 0;
94e9f1ce36Sbostic 			}
95e9f1ce36Sbostic 			if (0 == i)
96e9f1ce36Sbostic 				break;
97e9f1ce36Sbostic 
98e9f1ce36Sbostic 			fromlen = sizeof(from);
99e9f1ce36Sbostic 			if (recvfrom(sock,&sec,sizeof(sec),0,
100e9f1ce36Sbostic 				     &from,&fromlen) < 0) {
101e9f1ce36Sbostic 				perror("recvfrom(date read)");
102e9f1ce36Sbostic 				return 0;
103e9f1ce36Sbostic 			}
104e9f1ce36Sbostic 
105e9f1ce36Sbostic 			sec = ntohl(sec);
106e9f1ce36Sbostic 			if (sec < BU) {
107e9f1ce36Sbostic 				fprintf(stderr,
108e9f1ce36Sbostic 					"%s says it is before 1970: %lu",
109e9f1ce36Sbostic 					hostname, sec);
110e9f1ce36Sbostic 				return 0;
111e9f1ce36Sbostic 			}
112e9f1ce36Sbostic 			sec -= BU;
113e9f1ce36Sbostic 
114e9f1ce36Sbostic 			(void)gettimeofday(&now, (struct timezone*)0);
115e9f1ce36Sbostic 			return (sec - now.tv_sec);
116e9f1ce36Sbostic 		}
117e9f1ce36Sbostic 	}
118e9f1ce36Sbostic 
119e9f1ce36Sbostic 	/* if we get here, we tried too many times */
120e9f1ce36Sbostic 	fprintf(stderr,"%s will not tell us the date\n", hostname);
121e9f1ce36Sbostic 	return 0;
122e9f1ce36Sbostic }
123e9f1ce36Sbostic 
124da4a32c4Sgusella 
125da4a32c4Sgusella /*
126da4a32c4Sgusella  * Clockdiff computes the difference between the time of the machine on
127da4a32c4Sgusella  * which it is called and the time of the machines given as argument.
128da4a32c4Sgusella  * The time differences measured by clockdiff are obtained using a sequence
129da4a32c4Sgusella  * of ICMP TSTAMP messages which are returned to the sender by the IP module
130da4a32c4Sgusella  * in the remote machine.
131da4a32c4Sgusella  * In order to compare clocks of machines in different time zones, the time
132da4a32c4Sgusella  * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
133da4a32c4Sgusella  * If a hosts uses a different time format, it should set the high order
134da4a32c4Sgusella  * bit of the 32-bit quantity it transmits.
135da4a32c4Sgusella  * However, VMS apparently transmits the time in milliseconds since midnight
136da4a32c4Sgusella  * local time (rather than GMT) without setting the high order bit.
137da4a32c4Sgusella  * Furthermore, it does not understand daylight-saving time.  This makes
138da4a32c4Sgusella  * clockdiff behaving inconsistently with hosts running VMS.
139da4a32c4Sgusella  *
140da4a32c4Sgusella  * In order to reduce the sensitivity to the variance of message transmission
141da4a32c4Sgusella  * time, clockdiff sends a sequence of messages.  Yet, measures between
142e9f1ce36Sbostic  * two `distant' hosts can be affected by a small error. The error can,
143e9f1ce36Sbostic  * however, be reduced by increasing the number of messages sent in each
144e9f1ce36Sbostic  * measurement.
145da4a32c4Sgusella  */
146e9f1ce36Sbostic void
clockdiff(argc,argv)147da4a32c4Sgusella clockdiff(argc, argv)
148da4a32c4Sgusella 	int argc;
149da4a32c4Sgusella 	char *argv[];
150da4a32c4Sgusella {
151da4a32c4Sgusella 	int measure_status;
152e9f1ce36Sbostic 	extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
153e9f1ce36Sbostic 	register int avg_cnt;
154e9f1ce36Sbostic 	register long avg;
155e9f1ce36Sbostic 	struct servent *sp;
156da4a32c4Sgusella 
157da4a32c4Sgusella 	if (argc < 2)  {
158da4a32c4Sgusella 		printf("Usage: clockdiff host ... \n");
159da4a32c4Sgusella 		return;
160da4a32c4Sgusella 	}
161da4a32c4Sgusella 
162e9f1ce36Sbostic 	(void)gethostname(myname,sizeof(myname));
163e9f1ce36Sbostic 
164e9f1ce36Sbostic 	/* get the address for the date ready */
165e9f1ce36Sbostic 	sp = getservbyname(DATE_PORT, DATE_PROTO);
166e9f1ce36Sbostic 	if (!sp) {
167e9f1ce36Sbostic 		(void)fprintf(stderr, "%s/%s is an unknown service\n",
168e9f1ce36Sbostic 			      DATE_PORT, DATE_PROTO);
169e9f1ce36Sbostic 		dayaddr.sin_port = 0;
170e9f1ce36Sbostic 	} else {
171e9f1ce36Sbostic 		dayaddr.sin_port = sp->s_port;
172e9f1ce36Sbostic 	}
173da4a32c4Sgusella 
174da4a32c4Sgusella 	while (argc > 1) {
175da4a32c4Sgusella 		argc--; argv++;
176da4a32c4Sgusella 		hp = gethostbyname(*argv);
177da4a32c4Sgusella 		if (hp == NULL) {
178e9f1ce36Sbostic 			fprintf(stderr, "timedc: %s: ", *argv);
179e9f1ce36Sbostic 			herror(0);
180da4a32c4Sgusella 			continue;
181da4a32c4Sgusella 		}
182da4a32c4Sgusella 
183e9f1ce36Sbostic 		server.sin_family = hp->h_addrtype;
184e9f1ce36Sbostic 		bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length);
185e9f1ce36Sbostic 		for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) {
186e9f1ce36Sbostic 			measure_status = measure(10000,100, *argv, &server, 1);
187e9f1ce36Sbostic 			if (measure_status != GOOD)
188e9f1ce36Sbostic 				break;
189e9f1ce36Sbostic 			avg += measure_delta;
190e9f1ce36Sbostic 		}
191e9f1ce36Sbostic 		if (measure_status == GOOD)
192e9f1ce36Sbostic 			measure_delta = avg/avg_cnt;
193e9f1ce36Sbostic 
194e9f1ce36Sbostic 		switch (measure_status) {
195da4a32c4Sgusella 		case HOSTDOWN:
196da4a32c4Sgusella 			printf("%s is down\n", hp->h_name);
197da4a32c4Sgusella 			continue;
198da4a32c4Sgusella 		case NONSTDTIME:
199e9f1ce36Sbostic 			printf("%s transmitts a non-standard time format\n",
200e9f1ce36Sbostic 			       hp->h_name);
201da4a32c4Sgusella 			continue;
202da4a32c4Sgusella 		case UNREACHABLE:
203da4a32c4Sgusella 			printf("%s is unreachable\n", hp->h_name);
204da4a32c4Sgusella 			continue;
205da4a32c4Sgusella 		}
206da4a32c4Sgusella 
207e9f1ce36Sbostic 		/*
208e9f1ce36Sbostic 		 * Try to get the date only after using ICMP timestamps to
209e9f1ce36Sbostic 		 * get the time.  This is because the date protocol
210e9f1ce36Sbostic 		 * is optional.
211e9f1ce36Sbostic 		 */
212e9f1ce36Sbostic 		if (dayaddr.sin_port != 0) {
213e9f1ce36Sbostic 			dayaddr.sin_family = hp->h_addrtype;
214e9f1ce36Sbostic 			bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr,
215e9f1ce36Sbostic 			      hp->h_length);
216e9f1ce36Sbostic 			avg = daydiff(*argv);
217e9f1ce36Sbostic 			if (avg > SECDAY) {
218e9f1ce36Sbostic 				printf("time on %s is %ld days ahead %s\n",
219e9f1ce36Sbostic 				       hp->h_name, avg/SECDAY, myname);
220e9f1ce36Sbostic 				continue;
221e9f1ce36Sbostic 			} else if (avg < -SECDAY) {
222e9f1ce36Sbostic 				printf("time on %s is %ld days behind %s\n",
223e9f1ce36Sbostic 				       hp->h_name, -avg/SECDAY, myname);
224e9f1ce36Sbostic 				continue;
225e9f1ce36Sbostic 			}
226e9f1ce36Sbostic 		}
227e9f1ce36Sbostic 
228e9f1ce36Sbostic 		if (measure_delta > 0) {
229da4a32c4Sgusella 			printf("time on %s is %d ms. ahead of time on %s\n",
230e9f1ce36Sbostic 			       hp->h_name, measure_delta, myname);
231e9f1ce36Sbostic 		} else if (measure_delta == 0) {
232da4a32c4Sgusella 			printf("%s and %s have the same time\n",
233e9f1ce36Sbostic 			       hp->h_name, myname);
234e9f1ce36Sbostic 		} else {
235da4a32c4Sgusella 			printf("time on %s is %d ms. behind time on %s\n",
236e9f1ce36Sbostic 			       hp->h_name, -measure_delta, myname);
237e9f1ce36Sbostic 		}
238da4a32c4Sgusella 	}
239da4a32c4Sgusella 	return;
240da4a32c4Sgusella }
241e9f1ce36Sbostic 
242e9f1ce36Sbostic 
243da4a32c4Sgusella /*
244da4a32c4Sgusella  * finds location of master timedaemon
245da4a32c4Sgusella  */
246e9f1ce36Sbostic void
msite(argc,argv)247e9f1ce36Sbostic msite(argc, argv)
248da4a32c4Sgusella 	int argc;
249e9f1ce36Sbostic 	char *argv[];
250da4a32c4Sgusella {
251ec142418Sbloom 	int cc;
252ec142418Sbloom 	fd_set ready;
253da4a32c4Sgusella 	struct sockaddr_in dest;
254e9f1ce36Sbostic 	int i, length;
255e9f1ce36Sbostic 	struct sockaddr from;
256da4a32c4Sgusella 	struct timeval tout;
257da4a32c4Sgusella 	struct tsp msg;
258da4a32c4Sgusella 	struct servent *srvp;
259e9f1ce36Sbostic 	char *tgtname;
260da4a32c4Sgusella 
261e9f1ce36Sbostic 	if (argc < 1) {
262e9f1ce36Sbostic 		printf("Usage: msite [hostname]\n");
263da4a32c4Sgusella 		return;
264da4a32c4Sgusella 	}
265da4a32c4Sgusella 
266da4a32c4Sgusella 	srvp = getservbyname("timed", "udp");
267da4a32c4Sgusella 	if (srvp == 0) {
268da4a32c4Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
269da4a32c4Sgusella 		return;
270da4a32c4Sgusella 	}
271da4a32c4Sgusella 	dest.sin_port = srvp->s_port;
272da4a32c4Sgusella 	dest.sin_family = AF_INET;
273da4a32c4Sgusella 
274e9f1ce36Sbostic 	(void)gethostname(myname, sizeof(myname));
275e9f1ce36Sbostic 	i = 1;
276e9f1ce36Sbostic 	do {
277e9f1ce36Sbostic 		tgtname = (i >= argc) ? myname : argv[i];
278e9f1ce36Sbostic 		hp = gethostbyname(tgtname);
279e9f1ce36Sbostic 		if (hp == 0) {
280e9f1ce36Sbostic 			fprintf(stderr, "timedc: %s: ", tgtname);
281e9f1ce36Sbostic 			herror(0);
282e9f1ce36Sbostic 			continue;
283da4a32c4Sgusella 		}
284da4a32c4Sgusella 		bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
285da4a32c4Sgusella 
286e9f1ce36Sbostic 		(void)strcpy(msg.tsp_name, myname);
287da4a32c4Sgusella 		msg.tsp_type = TSP_MSITE;
288da4a32c4Sgusella 		msg.tsp_vers = TSPVERSION;
289da4a32c4Sgusella 		bytenetorder(&msg);
290e9f1ce36Sbostic 		if (sendto(sock, &msg, sizeof(struct tsp), 0,
291e9f1ce36Sbostic 			   (struct sockaddr*)&dest,
292e9f1ce36Sbostic 			   sizeof(struct sockaddr)) < 0) {
293da4a32c4Sgusella 			perror("sendto");
294e9f1ce36Sbostic 			continue;
295da4a32c4Sgusella 		}
296da4a32c4Sgusella 
297da4a32c4Sgusella 		tout.tv_sec = 15;
298da4a32c4Sgusella 		tout.tv_usec = 0;
299ec142418Sbloom 		FD_ZERO(&ready);
300ec142418Sbloom 		FD_SET(sock, &ready);
301e9f1ce36Sbostic 		if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
302e9f1ce36Sbostic 			   &tout)) {
303e9f1ce36Sbostic 			length = sizeof(struct sockaddr);
304e9f1ce36Sbostic 			cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
305e9f1ce36Sbostic 				      &from, &length);
306da4a32c4Sgusella 			if (cc < 0) {
307da4a32c4Sgusella 				perror("recvfrom");
308e9f1ce36Sbostic 				continue;
309da4a32c4Sgusella 			}
310da4a32c4Sgusella 			bytehostorder(&msg);
311e9f1ce36Sbostic 			if (msg.tsp_type == TSP_ACK) {
312e9f1ce36Sbostic 				printf("master timedaemon at %s is %s\n",
313e9f1ce36Sbostic 				       tgtname, msg.tsp_name);
314e9f1ce36Sbostic 			} else {
315da4a32c4Sgusella 				printf("received wrong ack: %s\n",
316da4a32c4Sgusella 				       tsptype[msg.tsp_type]);
317e9f1ce36Sbostic 			}
318e9f1ce36Sbostic 		} else {
319e9f1ce36Sbostic 			printf("communication error with %s\n", tgtname);
320e9f1ce36Sbostic 		}
321e9f1ce36Sbostic 	} while (++i < argc);
322da4a32c4Sgusella }
323da4a32c4Sgusella 
324da4a32c4Sgusella /*
325da4a32c4Sgusella  * quits timedc
326da4a32c4Sgusella  */
327e9f1ce36Sbostic void
quit()328da4a32c4Sgusella quit()
329da4a32c4Sgusella {
330da4a32c4Sgusella 	exit(0);
331da4a32c4Sgusella }
332da4a32c4Sgusella 
333da4a32c4Sgusella 
334da4a32c4Sgusella /*
335da4a32c4Sgusella  * Causes the election timer to expire on the selected hosts
336da4a32c4Sgusella  * It sends just one udp message per machine, relying on
337da4a32c4Sgusella  * reliability of communication channel.
338da4a32c4Sgusella  */
339e9f1ce36Sbostic void
testing(argc,argv)340da4a32c4Sgusella testing(argc, argv)
341da4a32c4Sgusella 	int argc;
342da4a32c4Sgusella 	char *argv[];
343da4a32c4Sgusella {
344da4a32c4Sgusella 	struct servent *srvp;
345e9f1ce36Sbostic 	struct sockaddr_in sin;
346da4a32c4Sgusella 	struct tsp msg;
347da4a32c4Sgusella 
348da4a32c4Sgusella 	if (argc < 2)  {
349e9f1ce36Sbostic 		printf("Usage: election host1 [host2 ...]\n");
350da4a32c4Sgusella 		return;
351da4a32c4Sgusella 	}
352da4a32c4Sgusella 
353da4a32c4Sgusella 	srvp = getservbyname("timed", "udp");
354da4a32c4Sgusella 	if (srvp == 0) {
355da4a32c4Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
356da4a32c4Sgusella 		return;
357da4a32c4Sgusella 	}
358da4a32c4Sgusella 
359da4a32c4Sgusella 	while (argc > 1) {
360da4a32c4Sgusella 		argc--; argv++;
361da4a32c4Sgusella 		hp = gethostbyname(*argv);
362da4a32c4Sgusella 		if (hp == NULL) {
363e9f1ce36Sbostic 			fprintf(stderr, "timedc: %s: ", *argv);
364e9f1ce36Sbostic 			herror(0);
365da4a32c4Sgusella 			argc--; argv++;
366da4a32c4Sgusella 			continue;
367da4a32c4Sgusella 		}
368e9f1ce36Sbostic 		sin.sin_port = srvp->s_port;
369e9f1ce36Sbostic 		sin.sin_family = hp->h_addrtype;
370e9f1ce36Sbostic 		bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length);
371da4a32c4Sgusella 
372da4a32c4Sgusella 		msg.tsp_type = TSP_TEST;
373da4a32c4Sgusella 		msg.tsp_vers = TSPVERSION;
374e9f1ce36Sbostic 		(void)gethostname(myname, sizeof(myname));
375e9f1ce36Sbostic 		(void)strncpy(msg.tsp_name, myname, sizeof(msg.tsp_name));
376e9f1ce36Sbostic 		bytenetorder(&msg);
377e9f1ce36Sbostic 		if (sendto(sock, &msg, sizeof(struct tsp), 0,
378e9f1ce36Sbostic 			   (struct sockaddr*)&sin,
379e9f1ce36Sbostic 			   sizeof(struct sockaddr)) < 0) {
380da4a32c4Sgusella 			perror("sendto");
381da4a32c4Sgusella 		}
382da4a32c4Sgusella 	}
383da4a32c4Sgusella }
384da4a32c4Sgusella 
385e9f1ce36Sbostic 
386da4a32c4Sgusella /*
387da4a32c4Sgusella  * Enables or disables tracing on local timedaemon
388da4a32c4Sgusella  */
389e9f1ce36Sbostic void
tracing(argc,argv)390da4a32c4Sgusella tracing(argc, argv)
391da4a32c4Sgusella 	int argc;
392da4a32c4Sgusella 	char *argv[];
393da4a32c4Sgusella {
394da4a32c4Sgusella 	int onflag;
395da4a32c4Sgusella 	int length;
396ec142418Sbloom 	int cc;
397ec142418Sbloom 	fd_set ready;
398da4a32c4Sgusella 	struct sockaddr_in dest;
399e9f1ce36Sbostic 	struct sockaddr from;
400da4a32c4Sgusella 	struct timeval tout;
401da4a32c4Sgusella 	struct tsp msg;
402da4a32c4Sgusella 	struct servent *srvp;
403da4a32c4Sgusella 
404da4a32c4Sgusella 	if (argc != 2) {
405da4a32c4Sgusella 		printf("Usage: tracing { on | off }\n");
406da4a32c4Sgusella 		return;
407da4a32c4Sgusella 	}
408da4a32c4Sgusella 
409da4a32c4Sgusella 	srvp = getservbyname("timed", "udp");
410da4a32c4Sgusella 	if (srvp == 0) {
411da4a32c4Sgusella 		fprintf(stderr, "udp/timed: unknown service\n");
412da4a32c4Sgusella 		return;
413da4a32c4Sgusella 	}
414da4a32c4Sgusella 	dest.sin_port = srvp->s_port;
415da4a32c4Sgusella 	dest.sin_family = AF_INET;
416da4a32c4Sgusella 
417e9f1ce36Sbostic 	(void)gethostname(myname,sizeof(myname));
418e9f1ce36Sbostic 	hp = gethostbyname(myname);
419da4a32c4Sgusella 	bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length);
420da4a32c4Sgusella 
421da4a32c4Sgusella 	if (strcmp(argv[1], "on") == 0) {
422da4a32c4Sgusella 		msg.tsp_type = TSP_TRACEON;
423da4a32c4Sgusella 		onflag = ON;
424da4a32c4Sgusella 	} else {
425da4a32c4Sgusella 		msg.tsp_type = TSP_TRACEOFF;
426da4a32c4Sgusella 		onflag = OFF;
427da4a32c4Sgusella 	}
428da4a32c4Sgusella 
429e9f1ce36Sbostic 	(void)strcpy(msg.tsp_name, myname);
430da4a32c4Sgusella 	msg.tsp_vers = TSPVERSION;
431da4a32c4Sgusella 	bytenetorder(&msg);
432e9f1ce36Sbostic 	if (sendto(sock, &msg, sizeof(struct tsp), 0,
433e9f1ce36Sbostic 		   (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) {
434da4a32c4Sgusella 		perror("sendto");
435da4a32c4Sgusella 		return;
436da4a32c4Sgusella 	}
437da4a32c4Sgusella 
438da4a32c4Sgusella 	tout.tv_sec = 5;
439da4a32c4Sgusella 	tout.tv_usec = 0;
440ec142418Sbloom 	FD_ZERO(&ready);
441ec142418Sbloom 	FD_SET(sock, &ready);
442ec142418Sbloom 	if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) {
443e9f1ce36Sbostic 		length = sizeof(struct sockaddr);
444e9f1ce36Sbostic 		cc = recvfrom(sock, &msg, sizeof(struct tsp), 0,
445e9f1ce36Sbostic 			      &from, &length);
446da4a32c4Sgusella 		if (cc < 0) {
447da4a32c4Sgusella 			perror("recvfrom");
448da4a32c4Sgusella 			return;
449da4a32c4Sgusella 		}
450da4a32c4Sgusella 		bytehostorder(&msg);
451da4a32c4Sgusella 		if (msg.tsp_type == TSP_ACK)
452da4a32c4Sgusella 			if (onflag)
453da4a32c4Sgusella 				printf("timed tracing enabled\n");
454da4a32c4Sgusella 			else
455da4a32c4Sgusella 				printf("timed tracing disabled\n");
456da4a32c4Sgusella 		else
457da4a32c4Sgusella 			printf("wrong ack received: %s\n",
458da4a32c4Sgusella 						tsptype[msg.tsp_type]);
459da4a32c4Sgusella 	} else
460da4a32c4Sgusella 		printf("communication error\n");
461da4a32c4Sgusella }
462da4a32c4Sgusella 
463e9f1ce36Sbostic int
priv_resources()464da4a32c4Sgusella priv_resources()
465da4a32c4Sgusella {
466da4a32c4Sgusella 	int port;
467da4a32c4Sgusella 	struct sockaddr_in sin;
468da4a32c4Sgusella 
469da4a32c4Sgusella 	sock = socket(AF_INET, SOCK_DGRAM, 0);
470da4a32c4Sgusella 	if (sock < 0) {
471da4a32c4Sgusella 		perror("opening socket");
472da4a32c4Sgusella 		return(-1);
473da4a32c4Sgusella 	}
474da4a32c4Sgusella 
475da4a32c4Sgusella 	sin.sin_family = AF_INET;
476da4a32c4Sgusella 	sin.sin_addr.s_addr = 0;
477da4a32c4Sgusella 	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
478da4a32c4Sgusella 		sin.sin_port = htons((u_short)port);
479da4a32c4Sgusella 		if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0)
480da4a32c4Sgusella 			break;
481da4a32c4Sgusella 		if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
482da4a32c4Sgusella 			perror("bind");
483da4a32c4Sgusella 			(void) close(sock);
484da4a32c4Sgusella 			return(-1);
485da4a32c4Sgusella 		}
486da4a32c4Sgusella 	}
487da4a32c4Sgusella 	if (port == IPPORT_RESERVED / 2) {
488da4a32c4Sgusella 		fprintf(stderr, "all reserved ports in use\n");
489da4a32c4Sgusella 		(void) close(sock);
490da4a32c4Sgusella 		return(-1);
491da4a32c4Sgusella 	}
492da4a32c4Sgusella 
493da4a32c4Sgusella 	sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
494da4a32c4Sgusella 	if (sock_raw < 0)  {
495da4a32c4Sgusella 		perror("opening raw socket");
496e9f1ce36Sbostic 		(void) close(sock);
497da4a32c4Sgusella 		return(-1);
498da4a32c4Sgusella 	}
499da4a32c4Sgusella 	return(1);
500da4a32c4Sgusella }
501