2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * This program expects a list of host names. It will send off a
12 * network time protocol packet and print out the replies on the
18 * Packet from: [128.8.10.1]
19 * Leap 0, version 1, mode Server, poll 6, precision -10 stratum 1 (WWVB)
20 * Synch Distance is 0000.1999 0.099991
21 * Synch Dispersion is 0000.0000 0.000000
22 * Reference Timestamp is a7bea6c3.88b40000 Tue Mar 7 14:06:43 1989
23 * Originate Timestamp is a7bea6d7.d7e6e652 Tue Mar 7 14:07:03 1989
24 * Receive Timestamp is a7bea6d7.cf1a0000 Tue Mar 7 14:07:03 1989
25 * Transmit Timestamp is a7bea6d8.0ccc0000 Tue Mar 7 14:07:04 1989
26 * Input Timestamp is a7bea6d8.1a77e5ea Tue Mar 7 14:07:04 1989
27 * umd1: delay:0.019028 offset:-0.043890
28 * Tue Mar 7 14:07:04 1989
32 #include <afsconfig.h>
33 #include <afs/param.h>
42 #include <sys/types.h>
43 #include <sys/param.h>
46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52 #include <netinet/udp.h>
53 #include <arpa/inet.h>
58 #include <sys/select.h>
75 #define RETRY_COUNT 2 /* number of times we want to retry */
76 #define TIME_OUT 10 /* time to wait for reply, in secs */
79 struct sockaddr_in sin = { AF_INET };
80 struct sockaddr_in dst = { AF_INET };
82 extern double ul_fixed_to_double(), s_fixed_to_double();
84 int set, verbose, force;
88 #include "AFS_component_version_number.c"
95 struct in_addr clock_host;
96 struct l_fixedpt in_timestamp;
97 static struct ntpdata ntp_data;
98 struct ntpdata *pkt = &ntp_data;
99 struct timeval tp, timeout;
100 int host, n, retry, s;
102 int dstlen = sizeof(dst);
103 double t1, t2, t3, t4, offset, delay;
109 * The following signal action for AIX is necessary so that in case of a
110 * crash (i.e. core is generated) we can include the user's data section
111 * in the core dump. Unfortunately, by default, only a partial core is
112 * generated which, in many cases, isn't too useful.
114 struct sigaction nsa;
116 sigemptyset(&nsa.sa_mask);
117 nsa.sa_handler = SIG_DFL;
118 nsa.sa_flags = SA_FULLDUMP;
119 sigaction(SIGSEGV, &nsa, NULL);
122 timeout.tv_sec = TIME_OUT;
126 sp = getservbyname("ntp", "udp");
128 fprintf(stderr, "udp/ntp: service unknown; using default %d\n",
130 dst.sin_port = htons(NTP_PORT);
132 dst.sin_port = sp->s_port;
134 dst.sin_family = AF_INET;
135 while ((n = getopt(argc, argv, "vsf")) != EOF) {
148 for (host = optind; host < argc; ++host) {
151 if (argv[host] == NULL)
155 HostAddr = inet_addr(argv[host]);
156 dst.sin_addr.s_addr = (afs_uint32) HostAddr;
157 if (HostAddr == -1) {
158 hp = gethostbyname(argv[host]);
160 fprintf(stderr, "\nNo such host: %s\n", argv[host]);
163 memcpy((char *)&dst.sin_addr, hp->h_addr, hp->h_length);
166 memset((char *)pkt, 0, sizeof(ntp_data));
168 pkt->status = NTPVERSION_1 | NO_WARNING | MODE_CLIENT;
169 pkt->stratum = UNSPECIFIED;
172 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
173 perror("ntp socket");
178 FD_SET(s, &readfds); /* since it's always modified on ret */
180 if (connect(s, (struct sockaddr *)&dst, dstlen)) {
186 * Needed to fill in the time stamp fields
188 (void)gettimeofday(&tp, NULL);
189 tstamp(&pkt->xmt, &tp);
191 if (send(s, (char *)pkt, sizeof(ntp_data), 0) < 0) {
197 * Wait for the reply by watching the file descriptor
200 select(FD_SETSIZE, (fd_set *) & readfds, (fd_set *) 0,
201 (fd_set *) 0, &timeout)) < 0) {
202 perror("ntp select");
207 fprintf(stderr, "*Timeout*\n");
211 fprintf(stderr, "Host %s is not responding\n", argv[host]);
217 (s, (char *)pkt, sizeof(ntp_data), 0, (struct sockaddr *)&sin,
222 (void)gettimeofday(&tp, NULL);
223 tstamp(&in_timestamp, &tp);
227 printf("Packet from: [%s]\n", inet_ntoa(sin.sin_addr));
229 ("Leap %d, version %d, mode %s, poll %d, precision %d stratum %d",
230 (pkt->status & LEAPMASK) >> 6,
231 (pkt->status & VERSIONMASK) >> 3,
232 modename[pkt->status & MODEMASK], pkt->ppoll, pkt->precision,
234 switch (pkt->stratum) {
237 (void)strncpy(ref_clock, (char *)&pkt->refid, 4);
239 printf(" (%s)\n", ref_clock);
242 clock_host.s_addr = (afs_uint32) pkt->refid;
243 printf(" [%s]\n", inet_ntoa(clock_host));
246 printf("Synch Distance is %04X.%04x %f\n",
247 ntohs(pkt->distance.int_part),
248 ntohs(pkt->distance.fraction),
249 s_fixed_to_double(&pkt->distance));
251 printf("Synch Dispersion is %04X.%04x %f\n",
252 ntohs(pkt->dispersion.int_part),
253 ntohs(pkt->dispersion.fraction),
254 s_fixed_to_double(&pkt->dispersion));
256 net_time = ntohl(pkt->reftime.int_part) - JAN_1970;
257 printf("Reference Timestamp is %08lx.%08lx %s",
258 ntohl(pkt->reftime.int_part), ntohl(pkt->reftime.fraction),
261 net_time = ntohl(pkt->org.int_part) - JAN_1970;
262 printf("Originate Timestamp is %08lx.%08lx %s",
263 ntohl(pkt->org.int_part), ntohl(pkt->org.fraction),
266 net_time = ntohl(pkt->rec.int_part) - JAN_1970;
267 printf("Receive Timestamp is %08lx.%08lx %s",
268 ntohl(pkt->rec.int_part), ntohl(pkt->rec.fraction),
271 net_time = ntohl(pkt->xmt.int_part) - JAN_1970;
272 printf("Transmit Timestamp is %08lx.%08lx %s",
273 ntohl(pkt->xmt.int_part), ntohl(pkt->xmt.fraction),
276 t1 = ul_fixed_to_double(&pkt->org);
277 t2 = ul_fixed_to_double(&pkt->rec);
278 t3 = ul_fixed_to_double(&pkt->xmt);
279 t4 = ul_fixed_to_double(&in_timestamp);
281 net_time = ntohl(in_timestamp.int_part) - JAN_1970;
283 printf("Input Timestamp is %08lx.%08lx %s",
284 ntohl(in_timestamp.int_part), ntohl(in_timestamp.fraction),
287 delay = (t4 - t1) - (t3 - t2);
288 offset = (t2 - t1) + (t3 - t4);
289 offset = offset / 2.0;
290 printf("%.20s: delay:%f offset:%f ", hp ? hp->h_name : argv[host],
292 net_time = ntohl(pkt->xmt.int_part) - JAN_1970 + delay;
293 fputs(ctime(&net_time), stdout);
294 (void)fflush(stdout);
299 if ((offset < 0 ? -offset : offset) > WAYTOOBIG && !force) {
301 "Offset too large - use -f option to force clock set.\n");
305 if (pkt->status & LEAPMASK == ALARM) {
306 fprintf(stderr, "Can't set time from %s - unsynchronized\n",
312 gettimeofday(&tp, NULL);
314 offset += tp.tv_usec / 1000000.0;
316 tp.tv_usec = (offset - tp.tv_sec) * 1000000.0;
318 if (settimeofday(&tp, NULL)) {
319 perror("Can't set time (settimeofday)");
322 } /* end of for each host */