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