]>
git.saurik.com Git - apple/network_cmds.git/blob - timed.tproj/timedc.tproj/cmds.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1985, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char sccsid
[] = "@(#)cmds.c 8.2 (Berkeley) 3/26/95";
62 #ident "$Revision: 1.1 $"
68 #include <netinet/in_systm.h>
69 #include <netinet/ip.h>
70 #include <netinet/ip_icmp.h>
77 #include <protocols/timed.h>
81 #include <sys/clock.h>
84 #define SECDAY (24*SECHR)
87 # define DATE_PROTO "udp"
88 # define DATE_PORT "time"
93 char myname
[MAXHOSTNAMELEN
];
95 struct sockaddr_in server
;
96 struct sockaddr_in dayaddr
;
97 extern int measure_delta
;
99 void bytenetorder(struct tsp
*);
100 void bytehostorder(struct tsp
*);
103 #define BU ((unsigned long)2208988800) /* seconds before UNIX epoch */
106 /* compute the difference between our date and another machine
108 static int /* difference in days from our time */
114 struct timeval tout
, now
;
116 struct sockaddr from
;
121 /* wait 2 seconds between 10 tries */
124 for (trials
= 0; trials
< 10; trials
++) {
125 /* ask for the time */
127 if (sendto(sock
, &sec
, sizeof(sec
), 0,
128 (struct sockaddr
*)&dayaddr
, sizeof(dayaddr
)) < 0) {
129 perror("sendto(sock)");
135 FD_SET(sock
, &ready
);
136 i
= select(sock
+1, &ready
, (fd_set
*)0,
141 perror("select(date read)");
147 fromlen
= sizeof(from
);
148 if (recvfrom(sock
,&sec
,sizeof(sec
),0,
149 &from
,&fromlen
) < 0) {
150 perror("recvfrom(date read)");
157 "%s says it is before 1970: %lu",
163 (void)gettimeofday(&now
, (struct timezone
*)0);
164 return (sec
- now
.tv_sec
);
168 /* if we get here, we tried too many times */
169 fprintf(stderr
,"%s will not tell us the date\n", hostname
);
175 * Clockdiff computes the difference between the time of the machine on
176 * which it is called and the time of the machines given as argument.
177 * The time differences measured by clockdiff are obtained using a sequence
178 * of ICMP TSTAMP messages which are returned to the sender by the IP module
179 * in the remote machine.
180 * In order to compare clocks of machines in different time zones, the time
181 * is transmitted (as a 32-bit value) in milliseconds since midnight UT.
182 * If a hosts uses a different time format, it should set the high order
183 * bit of the 32-bit quantity it transmits.
184 * However, VMS apparently transmits the time in milliseconds since midnight
185 * local time (rather than GMT) without setting the high order bit.
186 * Furthermore, it does not understand daylight-saving time. This makes
187 * clockdiff behaving inconsistently with hosts running VMS.
189 * In order to reduce the sensitivity to the variance of message transmission
190 * time, clockdiff sends a sequence of messages. Yet, measures between
191 * two `distant' hosts can be affected by a small error. The error can,
192 * however, be reduced by increasing the number of messages sent in each
196 clockdiff(argc
, argv
)
201 extern int measure(u_long
, u_long
, char *, struct sockaddr_in
*, int);
202 register int avg_cnt
;
207 printf("Usage: clockdiff host ... \n");
211 (void)gethostname(myname
,sizeof(myname
));
213 /* get the address for the date ready */
214 sp
= getservbyname(DATE_PORT
, DATE_PROTO
);
216 (void)fprintf(stderr
, "%s/%s is an unknown service\n",
217 DATE_PORT
, DATE_PROTO
);
218 dayaddr
.sin_port
= 0;
220 dayaddr
.sin_port
= sp
->s_port
;
225 hp
= gethostbyname(*argv
);
227 fprintf(stderr
, "timedc: %s: ", *argv
);
232 server
.sin_family
= hp
->h_addrtype
;
233 bcopy(hp
->h_addr
, &server
.sin_addr
.s_addr
, hp
->h_length
);
234 for (avg_cnt
= 0, avg
= 0; avg_cnt
< 16; avg_cnt
++) {
235 measure_status
= measure(10000,100, *argv
, &server
, 1);
236 if (measure_status
!= GOOD
)
238 avg
+= measure_delta
;
240 if (measure_status
== GOOD
)
241 measure_delta
= avg
/avg_cnt
;
243 switch (measure_status
) {
245 printf("%s is down\n", hp
->h_name
);
248 printf("%s transmitts a non-standard time format\n",
252 printf("%s is unreachable\n", hp
->h_name
);
257 * Try to get the date only after using ICMP timestamps to
258 * get the time. This is because the date protocol
261 if (dayaddr
.sin_port
!= 0) {
262 dayaddr
.sin_family
= hp
->h_addrtype
;
263 bcopy(hp
->h_addr
, &dayaddr
.sin_addr
.s_addr
,
265 avg
= daydiff(*argv
);
267 printf("time on %s is %ld days ahead %s\n",
268 hp
->h_name
, avg
/SECDAY
, myname
);
270 } else if (avg
< -SECDAY
) {
271 printf("time on %s is %ld days behind %s\n",
272 hp
->h_name
, -avg
/SECDAY
, myname
);
277 if (measure_delta
> 0) {
278 printf("time on %s is %d ms. ahead of time on %s\n",
279 hp
->h_name
, measure_delta
, myname
);
280 } else if (measure_delta
== 0) {
281 printf("%s and %s have the same time\n",
284 printf("time on %s is %d ms. behind time on %s\n",
285 hp
->h_name
, -measure_delta
, myname
);
293 * finds location of master timedaemon
302 struct sockaddr_in dest
;
304 struct sockaddr from
;
307 struct servent
*srvp
;
311 printf("Usage: msite [hostname]\n");
315 srvp
= getservbyname("timed", "udp");
317 fprintf(stderr
, "udp/timed: unknown service\n");
320 dest
.sin_port
= srvp
->s_port
;
321 dest
.sin_family
= AF_INET
;
323 (void)gethostname(myname
, sizeof(myname
));
326 tgtname
= (i
>= argc
) ? myname
: argv
[i
];
327 hp
= gethostbyname(tgtname
);
329 fprintf(stderr
, "timedc: %s: ", tgtname
);
333 bcopy(hp
->h_addr
, &dest
.sin_addr
.s_addr
, hp
->h_length
);
335 (void)strcpy(msg
.tsp_name
, myname
);
336 msg
.tsp_type
= TSP_MSITE
;
337 msg
.tsp_vers
= TSPVERSION
;
339 if (sendto(sock
, &msg
, sizeof(struct tsp
), 0,
340 (struct sockaddr
*)&dest
,
341 sizeof(struct sockaddr
)) < 0) {
349 FD_SET(sock
, &ready
);
350 if (select(FD_SETSIZE
, &ready
, (fd_set
*)0, (fd_set
*)0,
352 length
= sizeof(struct sockaddr
);
353 cc
= recvfrom(sock
, &msg
, sizeof(struct tsp
), 0,
360 if (msg
.tsp_type
== TSP_ACK
) {
361 printf("master timedaemon at %s is %s\n",
362 tgtname
, msg
.tsp_name
);
364 printf("received wrong ack: %s\n",
365 tsptype
[msg
.tsp_type
]);
368 printf("communication error with %s\n", tgtname
);
370 } while (++i
< argc
);
384 * Causes the election timer to expire on the selected hosts
385 * It sends just one udp message per machine, relying on
386 * reliability of communication channel.
393 struct servent
*srvp
;
394 struct sockaddr_in sin
;
398 printf("Usage: election host1 [host2 ...]\n");
402 srvp
= getservbyname("timed", "udp");
404 fprintf(stderr
, "udp/timed: unknown service\n");
410 hp
= gethostbyname(*argv
);
412 fprintf(stderr
, "timedc: %s: ", *argv
);
417 sin
.sin_port
= srvp
->s_port
;
418 sin
.sin_family
= hp
->h_addrtype
;
419 bcopy(hp
->h_addr
, &sin
.sin_addr
.s_addr
, hp
->h_length
);
421 msg
.tsp_type
= TSP_TEST
;
422 msg
.tsp_vers
= TSPVERSION
;
423 (void)gethostname(myname
, sizeof(myname
));
424 (void)strncpy(msg
.tsp_name
, myname
, sizeof(msg
.tsp_name
));
426 if (sendto(sock
, &msg
, sizeof(struct tsp
), 0,
427 (struct sockaddr
*)&sin
,
428 sizeof(struct sockaddr
)) < 0) {
436 * Enables or disables tracing on local timedaemon
447 struct sockaddr_in dest
;
448 struct sockaddr from
;
451 struct servent
*srvp
;
454 printf("Usage: tracing { on | off }\n");
458 srvp
= getservbyname("timed", "udp");
460 fprintf(stderr
, "udp/timed: unknown service\n");
463 dest
.sin_port
= srvp
->s_port
;
464 dest
.sin_family
= AF_INET
;
466 (void)gethostname(myname
,sizeof(myname
));
467 hp
= gethostbyname(myname
);
468 bcopy(hp
->h_addr
, &dest
.sin_addr
.s_addr
, hp
->h_length
);
470 if (strcmp(argv
[1], "on") == 0) {
471 msg
.tsp_type
= TSP_TRACEON
;
474 msg
.tsp_type
= TSP_TRACEOFF
;
478 (void)strcpy(msg
.tsp_name
, myname
);
479 msg
.tsp_vers
= TSPVERSION
;
481 if (sendto(sock
, &msg
, sizeof(struct tsp
), 0,
482 (struct sockaddr
*)&dest
, sizeof(struct sockaddr
)) < 0) {
490 FD_SET(sock
, &ready
);
491 if (select(FD_SETSIZE
, &ready
, (fd_set
*)0, (fd_set
*)0, &tout
)) {
492 length
= sizeof(struct sockaddr
);
493 cc
= recvfrom(sock
, &msg
, sizeof(struct tsp
), 0,
500 if (msg
.tsp_type
== TSP_ACK
)
502 printf("timed tracing enabled\n");
504 printf("timed tracing disabled\n");
506 printf("wrong ack received: %s\n",
507 tsptype
[msg
.tsp_type
]);
509 printf("communication error\n");
516 struct sockaddr_in sin
;
518 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
520 perror("opening socket");
524 sin
.sin_family
= AF_INET
;
525 sin
.sin_addr
.s_addr
= 0;
526 for (port
= IPPORT_RESERVED
- 1; port
> IPPORT_RESERVED
/ 2; port
--) {
527 sin
.sin_port
= htons((u_short
)port
);
528 if (bind(sock
, (struct sockaddr
*)&sin
, sizeof (sin
)) >= 0)
530 if (errno
!= EADDRINUSE
&& errno
!= EADDRNOTAVAIL
) {
536 if (port
== IPPORT_RESERVED
/ 2) {
537 fprintf(stderr
, "all reserved ports in use\n");
542 sock_raw
= socket(AF_INET
, SOCK_RAW
, IPPROTO_ICMP
);
544 perror("opening raw socket");