convert-from-bsd-to-posix-string-and-memory-functions-20010807
[openafs.git] / src / ntp / ntpdc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <signal.h>
18 #include <sys/uio.h>
19 #include <sys/socket.h>
20 #include <sys/time.h>
21 #include <netinet/in.h>
22 #include <netinet/udp.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <netdb.h>
26 #include <strings.h>
27 #include <arpa/inet.h>
28
29 #ifdef AFS_AIX32_ENV
30 #include <sys/select.h>
31 #endif
32
33 #include "ntp.h"
34
35 #define WTIME   10              /* Time to wait for all responses */
36 #define STIME   500000          /* usec to wait for another response */
37 #define MAXPACKETSIZE 1500
38
39 extern int errno;
40 int debug;
41 int s;
42 int timedout;
43 void timeout();
44 int nflag, vflag;
45
46 struct sockaddr_in sin = {AF_INET};
47
48 char packet[MAXPACKETSIZE];
49 #ifndef MAXHOSTNAMELEN
50 #define MAXHOSTNAMELEN  64
51 #endif
52 char    LocalHostName[MAXHOSTNAMELEN+1];        /* our hostname */
53 char    *LocalDomain;           /* our local domain name */
54
55 #include "AFS_component_version_number.c"
56
57 main(argc, argv)
58         int argc;
59         char *argv[];
60 {
61         char *p;
62         int on = 48*1024;
63
64 #ifdef  AFS_AIX32_ENV
65         /*
66          * The following signal action for AIX is necessary so that in case of a 
67          * crash (i.e. core is generated) we can include the user's data section 
68          * in the core dump. Unfortunately, by default, only a partial core is
69          * generated which, in many cases, isn't too useful.
70          */
71         struct sigaction nsa;
72     
73         sigemptyset(&nsa.sa_mask);
74         nsa.sa_handler = SIG_DFL;
75         nsa.sa_flags = SA_FULLDUMP;
76         sigaction(SIGSEGV, &nsa, NULL);
77 #endif
78         (void) gethostname(LocalHostName, sizeof LocalHostName);
79         if (p = strchr(LocalHostName, '.')) {
80                 *p++ = '\0';
81                 LocalDomain = p;
82         }
83         else
84                 LocalDomain = "";
85
86         if (argc < 2) {
87 usage:
88                 printf("usage: %s [ -v ][ -n ] hosts...\n", argv[0]);
89                 exit(1);
90         }
91
92         argv++, argc--;
93         if (*argv[0] == '-') {
94                 switch (argv[0][1]) {
95                 case 'n':
96                         nflag++;
97                         break;
98                 case 'v':
99                         vflag++;
100                         break;
101                 default:
102                         goto usage;
103                 }
104                 argc--, argv++;
105         }
106         if (argc > 1)
107                 printf("--- %s ---\n", *argv);
108
109         while (argc > 0) {
110                 /*
111                  * Get a new socket each time - this will cause us to ignore
112                  * packets from the previously queried host.
113                  */
114                 s = socket(AF_INET, SOCK_DGRAM, 0);
115                 if (s < 0) {
116                         perror("socket");
117                         exit(2);
118                 }
119 #ifdef  SO_RCVBUF
120                 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
121                                 (char *) &on, sizeof (on)) < 0) {
122                         fprintf(stderr, "setsockopt SO_RCVBUF\n");
123                 }
124 #endif
125                 if (query(*argv))
126                         answer(*argv);
127                 close(s);
128                 argv++;
129                 if (argc-- > 1)
130                         printf("--- %s ---\n", *argv);
131         }
132
133 }
134
135 answer(host)
136         char *host;
137 {
138         register struct ntpinfo *msg = (struct ntpinfo *) packet;
139         register struct clockinfo *n;
140         struct sockaddr_in from;
141         int fromlen = sizeof(from);
142         int count, cc;
143         fd_set bits;
144         struct timeval shorttime;
145         int first = 1;
146         afs_int32 replies = 0;
147
148         /*
149          * Listen for returning packets; may be more than one packet per
150          * host. 
151          */
152         FD_ZERO(&bits);
153         FD_SET(s, &bits);
154         shorttime.tv_sec = 0;
155         shorttime.tv_usec = STIME;
156         (void) signal(SIGALRM, timeout);
157         (void) alarm(WTIME);
158         timedout = 0;
159         while ((first || replies) && 
160                (!timedout || select(FD_SETSIZE, &bits, (fd_set *) 0,
161                                     (fd_set *) 0, &shorttime) > 0)) {
162                 if ((cc = recvfrom(s, packet, sizeof(packet), 0,
163                              (struct sockaddr *)&from, &fromlen)) <= 0) {
164                         if (cc == 0 || errno == EINTR)
165                                 continue;
166                         fflush(stdout);
167                         perror(host);
168                         (void) close(s);
169                         return;
170                 }
171                 FD_SET(s, &bits);
172
173                 if (msg->type != INFO_REPLY)
174                         return;
175
176                 if (msg->version != NTPDC_VERSION) {
177                         printf("ntpd(%d) - ntpdc(%d) version mismatch\n",
178                                msg->version, NTPDC_VERSION);
179                         alarm(0);
180                         return;
181                 }
182
183                 if (first) {
184                         first = 0;
185                         replies = (1L << msg->npkts) - 1;
186                         if (!vflag) {
187                                 printf("   (rem)  Address   (lcl)      Strat Poll Reach    Delay   Offset    Disp\n");
188                                 printf("==========================================================================\n");
189                         }
190                 }
191                 replies &= ~(1L << msg->seq);
192                 n = (struct clockinfo *)&msg[1];
193                 for (count = msg->count; count > 0; count--) {
194                         if(vflag)
195                                 print_verbose(n);
196                         else
197                                 print_terse(n);
198                         n++;
199                 }
200         }
201         alarm(0);
202         if (replies)
203                 printf("Timed out waiting for replies\n");
204 }
205
206 int
207 query(host)
208         char *host;
209 {
210         struct sockaddr_in watcher;
211         register struct ntpdata *msg = (struct ntpdata *) packet;
212         struct hostent *hp;
213         static struct servent *sp = NULL;
214         afs_int32 HostAddr;
215
216         memset((char *) &watcher, 0, sizeof(watcher));
217         watcher.sin_family = AF_INET;
218         HostAddr = inet_addr(host);
219         watcher.sin_addr.s_addr = (afs_uint32) HostAddr;
220         if (HostAddr == -1) {
221                 hp = gethostbyname(host);
222                 if (hp == 0) {
223                         fprintf(stderr,"%s: unknown\n", host);
224                         return 0;
225                 }
226                 memcpy((char *) &watcher.sin_addr, hp->h_addr, hp->h_length);
227         }
228         sp = getservbyname("ntp", "udp");
229         if (sp == 0) {
230                 fprintf(stderr,"udp/ntp: service unknown, using default %d\n",
231                         NTP_PORT);
232                 watcher.sin_port = htons(NTP_PORT);
233         } else
234                 watcher.sin_port = sp->s_port;
235         msg->status = NTPVERSION_1;
236         msg->stratum = INFO_QUERY;
237         if (connect(s, (struct sockaddr *) &watcher, sizeof(watcher))) {
238                 perror("connect");
239                 return 0;
240         }
241         if (send(s, packet, sizeof(struct ntpdata), 0) < 0) {
242                 perror("send");
243                 return 0;
244         }
245         return 1;
246 }
247
248 void timeout()
249 {
250         timedout = 1;
251 }
252
253 print_terse (n)
254         struct clockinfo *n;
255 {
256         int i;
257         double offset[PEER_SHIFT], delay[PEER_SHIFT], dsp,del,off;
258         char c;
259         char *cvthname();
260         int flags;
261
262         sin.sin_addr.s_addr = n->net_address;
263         for (i = 0; i < PEER_SHIFT; i++) {
264                 delay[i] = (double) ((afs_int32) (ntohl(n->info_filter.delay[i])/1000.0));
265                 offset[i] = (double) ((afs_int32) (ntohl(n->info_filter.offset[i])/1000.0));
266         }
267         dsp = (afs_int32) ntohl(n->estdisp);            /* leave in milliseconds */
268         del = (afs_int32) ntohl(n->estdelay);   /* leave in milliseconds */
269         off = (afs_int32) ntohl(n->estoffset);  /* leave in milliseconds */
270         c = ' ';
271         flags = ntohs(n->flags);
272         if (flags & PEER_FL_CONFIG)
273                 c = '-';                /* mark pre-configured */
274         if (flags & PEER_FL_SANE)
275                 c = '.';                /* passed sanity check */
276         if (flags & PEER_FL_CANDIDATE)
277                 c = '+';                /* made candidate list */
278         if (flags & PEER_FL_SELECTED)
279                 c = '*';                /* mark peer selection */
280         sin.sin_addr.s_addr = n->net_address;
281         printf("%c%-15.15s ", c, cvthname(&sin));
282         sin.sin_addr.s_addr = n->my_address;
283         printf("%-16.16s %2d %4d  %03o  %8.1f %8.1f %8.1f\n",
284                sin.sin_addr.s_addr ? inet_ntoa(sin.sin_addr) : "wildcard", 
285                n->stratum, (int)ntohl((afs_uint32)n->timer), 
286                ntohs(n->reach) & SHIFT_MASK, del, off, dsp);
287 }       
288
289 print_verbose(n)
290         struct clockinfo *n;
291 {
292         int i;
293         struct in_addr clock_host;
294         double offset[PEER_SHIFT], delay[PEER_SHIFT], dsp,del,off;
295         char *cvthname();
296
297         sin.sin_addr.s_addr = n->net_address;
298         for (i = 0; i < PEER_SHIFT; i++) {
299                 delay[i] = (double) (afs_int32) ntohl(n->info_filter.delay[i]);
300                 offset[i] = (double) (afs_int32) ntohl(n->info_filter.offset[i]);
301         }
302         dsp = (double) ((afs_int32) ntohl(n->estdisp)); /* in milliseconds */
303         del = (double) ((afs_int32) ntohl(n->estdelay));        /* in milliseconds */
304         off = (double) ((afs_int32) ntohl(n->estoffset));       /* in milliseconds */
305         printf("Neighbor address %s port:%d",
306                inet_ntoa(sin.sin_addr), (int)ntohs(n->port));
307         sin.sin_addr.s_addr = n->my_address;
308         printf("  local address %s\n", inet_ntoa(sin.sin_addr));
309         printf("Reach: 0%o stratum: %d, precision: %d\n",
310                ntohs(n->reach) & SHIFT_MASK, n->stratum, n->precision);
311         printf("dispersion: %f, flags: %x, leap: %x\n",
312                dsp,
313                ntohs(n->flags),
314                n->leap);
315         if (n->stratum == 1 || n->stratum == 0) {
316                 printf("Reference clock ID: %.4s", (char *)&n->refid);
317         } else {
318                 clock_host.s_addr = (afs_uint32) n->refid;
319                 printf("Reference clock ID: [%s]", inet_ntoa(clock_host));
320         }
321         printf(" timestamp: %08lx.%08lx\n", ntohl(n->reftime.int_part),
322                ntohl(n->reftime.fraction));
323
324         printf("hpoll: %d, ppoll: %d, timer: %d, sent: %d received: %d dropped: %d\n",
325                n->hpoll, n->ppoll,
326                (int)ntohl((afs_uint32)n->timer),
327                (int)ntohl(n->pkt_sent),
328                (int)ntohl(n->pkt_rcvd),
329                (int)ntohl(n->pkt_dropped));
330         printf("Delay(ms)  ");
331         for (i = 0; i < PEER_SHIFT; i++)
332                 printf("%7.2f ", delay[i]);
333         printf("\n");
334         printf("Offset(ms) ");
335         for (i = 0; i < PEER_SHIFT; i++)
336                 printf("%7.2f ", offset[i]);
337         printf("\n");
338         printf("\n\tdelay: %f offset: %f dsp %f\n", del, off, dsp);
339         printf("\n");
340 }
341 /*
342  * Return a printable representation of a host address.
343  */
344 char *
345 cvthname(f)
346         struct sockaddr_in *f;
347 {
348         struct hostent *hp;
349         register char *p;
350         extern char *inet_ntoa();
351
352         if (f->sin_family != AF_INET) {
353                 printf("Malformed from address\n");
354                 return ("???");
355         }
356         if (!nflag)
357                 hp = gethostbyaddr((char *) &f->sin_addr,
358                                    sizeof(struct in_addr),
359                                    f->sin_family);
360         else
361                 return (inet_ntoa(f->sin_addr));
362
363         if (hp == 0)
364                 return (inet_ntoa(f->sin_addr));
365
366         if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
367                 *p = '\0';
368         return (hp->h_name);
369 }