]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/ntp/ntpdc/ntpdc.c
MFC r338126: MFV r338092: ntp 4.2.8p12.
[FreeBSD/stable/10.git] / contrib / ntp / ntpdc / ntpdc.c
1 /*
2  * ntpdc - control and monitor your ntpd daemon
3  */
4 #include <config.h>
5 #include <stdio.h>
6 #include <stddef.h>
7 #include <ctype.h>
8 #include <signal.h>
9 #include <setjmp.h>
10 #ifdef HAVE_UNISTD_H
11 # include <unistd.h>
12 #endif
13 #ifdef HAVE_FCNTL_H
14 # include <fcntl.h>
15 #endif
16 #ifdef SYS_WINNT
17 # include <mswsock.h>
18 #endif
19 #include <isc/net.h>
20 #include <isc/result.h>
21
22 #include "ntpdc.h"
23 #include "ntp_select.h"
24 #include "ntp_stdlib.h"
25 #include "ntp_assert.h"
26 #include "ntp_lineedit.h"
27 #ifdef OPENSSL
28 #include "openssl/evp.h"
29 #include "openssl/objects.h"
30 #endif
31 #include <ssl_applink.c>
32
33 #include "ntp_libopts.h"
34 #include "ntpdc-opts.h"
35 #include "safecast.h"
36
37 #ifdef SYS_VXWORKS
38                                 /* vxWorks needs mode flag -casey*/
39 # define open(name, flags)   open(name, flags, 0777)
40 # define SERVER_PORT_NUM     123
41 #endif
42
43 /* We use COMMAND as an autogen keyword */
44 #ifdef COMMAND
45 # undef COMMAND
46 #endif
47
48 /*
49  * Because we now potentially understand a lot of commands (and
50  * it requires a lot of commands to talk to ntpd) we will run
51  * interactive if connected to a terminal.
52  */
53 static  int     interactive = 0;        /* set to 1 when we should prompt */
54 static  const char *    prompt = "ntpdc> ";     /* prompt to ask him about */
55
56 /*
57  * Keyid used for authenticated requests.  Obtained on the fly.
58  */
59 static  u_long  info_auth_keyid;
60 static int keyid_entered = 0;
61
62 static  int     info_auth_keytype = NID_md5;    /* MD5 */
63 static  size_t  info_auth_hashlen = 16;         /* MD5 */
64 u_long  current_time;           /* needed by authkeys; not used */
65
66 /*
67  * for get_systime()
68  */
69 s_char  sys_precision;          /* local clock precision (log2 s) */
70
71 int             ntpdcmain       (int,   char **);
72 /*
73  * Built in command handler declarations
74  */
75 static  int     openhost        (const char *);
76 static  int     sendpkt         (void *, size_t);
77 static  void    growpktdata     (void);
78 static  int     getresponse     (int, int, size_t *, size_t *, const char **, size_t);
79 static  int     sendrequest     (int, int, int, size_t, size_t, const char *);
80 static  void    getcmds         (void);
81 static  RETSIGTYPE abortcmd     (int);
82 static  void    docmd           (const char *);
83 static  void    tokenize        (const char *, char **, int *);
84 static  int     findcmd         (char *, struct xcmd *, struct xcmd *, struct xcmd **);
85 static  int     getarg          (char *, int, arg_v *);
86 static  int     getnetnum       (const char *, sockaddr_u *, char *, int);
87 static  void    help            (struct parse *, FILE *);
88 static  int     helpsort        (const void *, const void *);
89 static  void    printusage      (struct xcmd *, FILE *);
90 static  void    timeout         (struct parse *, FILE *);
91 static  void    my_delay        (struct parse *, FILE *);
92 static  void    host            (struct parse *, FILE *);
93 static  void    keyid           (struct parse *, FILE *);
94 static  void    keytype         (struct parse *, FILE *);
95 static  void    passwd          (struct parse *, FILE *);
96 static  void    hostnames       (struct parse *, FILE *);
97 static  void    setdebug        (struct parse *, FILE *);
98 static  void    quit            (struct parse *, FILE *);
99 static  void    version         (struct parse *, FILE *);
100 static  void    warning         (const char *, ...)
101     __attribute__((__format__(__printf__, 1, 2)));
102 static  void    error           (const char *, ...)
103     __attribute__((__format__(__printf__, 1, 2)));
104 static  u_long  getkeyid        (const char *);
105
106
107
108 /*
109  * Built-in commands we understand
110  */
111 static  struct xcmd builtins[] = {
112         { "?",          help,           {  OPT|NTP_STR, NO, NO, NO },
113           { "command", "", "", "" },
114           "tell the use and syntax of commands" },
115         { "help",       help,           {  OPT|NTP_STR, NO, NO, NO },
116           { "command", "", "", "" },
117           "tell the use and syntax of commands" },
118         { "timeout",    timeout,        { OPT|NTP_UINT, NO, NO, NO },
119           { "msec", "", "", "" },
120           "set the primary receive time out" },
121         { "delay",      my_delay,       { OPT|NTP_INT, NO, NO, NO },
122           { "msec", "", "", "" },
123           "set the delay added to encryption time stamps" },
124         { "host",       host,           { OPT|NTP_STR, OPT|NTP_STR, NO, NO },
125           { "-4|-6", "hostname", "", "" },
126           "specify the host whose NTP server we talk to" },
127         { "passwd",     passwd,         { OPT|NTP_STR, NO, NO, NO },
128           { "", "", "", "" },
129           "specify a password to use for authenticated requests"},
130         { "hostnames",  hostnames,      { OPT|NTP_STR, NO, NO, NO },
131           { "yes|no", "", "", "" },
132           "specify whether hostnames or net numbers are printed"},
133         { "debug",      setdebug,       { OPT|NTP_STR, NO, NO, NO },
134           { "no|more|less", "", "", "" },
135           "set/change debugging level" },
136         { "quit",       quit,           { NO, NO, NO, NO },
137           { "", "", "", "" },
138           "exit ntpdc" },
139         { "exit",       quit,           { NO, NO, NO, NO },
140           { "", "", "", "" },
141           "exit ntpdc" },
142         { "keyid",      keyid,          { OPT|NTP_UINT, NO, NO, NO },
143           { "key#", "", "", "" },
144           "set/show keyid to use for authenticated requests" },
145         { "keytype",    keytype,        { OPT|NTP_STR, NO, NO, NO },
146           { "(md5|des)", "", "", "" },
147           "set/show key authentication type for authenticated requests (des|md5)" },
148         { "version",    version,        { NO, NO, NO, NO },
149           { "", "", "", "" },
150           "print version number" },
151         { 0,            0,              { NO, NO, NO, NO },
152           { "", "", "", "" }, "" }
153 };
154
155
156 /*
157  * Default values we use.
158  */
159 #define DEFHOST         "localhost"     /* default host name */
160 #define DEFTIMEOUT      (5)             /* 5 second time out */
161 #define DEFSTIMEOUT     (2)             /* 2 second time out after first */
162 #define DEFDELAY        0x51EB852       /* 20 milliseconds, l_fp fraction */
163 #define LENHOSTNAME     256             /* host name is 256 characters long */
164 #define MAXCMDS         100             /* maximum commands on cmd line */
165 #define MAXHOSTS        200             /* maximum hosts on cmd line */
166 #define MAXLINE         512             /* maximum line length */
167 #define MAXTOKENS       (1+1+MAXARGS+MOREARGS+2)        /* maximum number of usable tokens */
168 #define SCREENWIDTH     78              /* nominal screen width in columns */
169
170 /*
171  * Some variables used and manipulated locally
172  */
173 static  struct sock_timeval tvout = { DEFTIMEOUT, 0 };  /* time out for reads */
174 static  struct sock_timeval tvsout = { DEFSTIMEOUT, 0 };/* secondary time out */
175 static  l_fp delay_time;                                /* delay time */
176 static  char currenthost[LENHOSTNAME];                  /* current host name */
177 int showhostnames = 1;                                  /* show host names by default */
178
179 static  int ai_fam_templ;                               /* address family */
180 static  int ai_fam_default;                             /* default address family */
181 static  SOCKET sockfd;                                  /* fd socket is opened on */
182 static  int havehost = 0;                               /* set to 1 when host open */
183 int s_port = 0;
184
185 /*
186  * Holds data returned from queries.  We allocate INITDATASIZE
187  * octets to begin with, increasing this as we need to.
188  */
189 #define INITDATASIZE    (sizeof(struct resp_pkt) * 16)
190 #define INCDATASIZE     (sizeof(struct resp_pkt) * 8)
191
192 static  char *pktdata;
193 static  int pktdatasize;
194
195 /*
196  * These are used to help the magic with old and new versions of ntpd.
197  */
198 int impl_ver = IMPL_XNTPD;
199 static int req_pkt_size = REQ_LEN_NOMAC;
200
201 /*
202  * For commands typed on the command line (with the -c option)
203  */
204 static  int numcmds = 0;
205 static  const char *ccmds[MAXCMDS];
206 #define ADDCMD(cp)      if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp)
207
208 /*
209  * When multiple hosts are specified.
210  */
211 static  int numhosts = 0;
212 static  const char *chosts[MAXHOSTS];
213 #define ADDHOST(cp)     if (numhosts < MAXHOSTS) chosts[numhosts++] = (cp)
214
215 /*
216  * Error codes for internal use
217  */
218 #define ERR_INCOMPLETE          16
219 #define ERR_TIMEOUT             17
220
221 /*
222  * Macro definitions we use
223  */
224 #define ISSPACE(c)      ((c) == ' ' || (c) == '\t')
225 #define ISEOL(c)        ((c) == '\n' || (c) == '\r' || (c) == '\0')
226 #define STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
227
228 /*
229  * Jump buffer for longjumping back to the command level.
230  *
231  * See ntpq/ntpq.c for an explanation why 'sig{set,long}jmp()' is used
232  * when available.
233  */
234 #if HAVE_DECL_SIGSETJMP && HAVE_DECL_SIGLONGJMP
235 # define JMP_BUF        sigjmp_buf
236 # define SETJMP(x)      sigsetjmp((x), 1)
237 # define LONGJMP(x, v)  siglongjmp((x),(v))
238 #else
239 # define JMP_BUF        jmp_buf
240 # define SETJMP(x)      setjmp((x))
241 # define LONGJMP(x, v)  longjmp((x),(v))
242 #endif
243 static  JMP_BUF         interrupt_buf;
244 static  volatile int    jump = 0;
245
246 /*
247  * Pointer to current output unit
248  */
249 static  FILE *current_output = NULL;
250
251 /*
252  * Command table imported from ntpdc_ops.c
253  */
254 extern struct xcmd opcmds[];
255
256 char const *progname;
257
258 #ifdef NO_MAIN_ALLOWED
259 CALL(ntpdc,"ntpdc",ntpdcmain);
260 #else
261 int
262 main(
263         int argc,
264         char *argv[]
265         )
266 {
267         return ntpdcmain(argc, argv);
268 }
269 #endif
270
271 #ifdef SYS_VXWORKS
272 void clear_globals(void)
273 {
274     showhostnames = 0;              /* show host names by default */
275     havehost = 0;                   /* set to 1 when host open */
276     numcmds = 0;
277     numhosts = 0;
278 }
279 #endif
280
281 /*
282  * main - parse arguments and handle options
283  */
284 int
285 ntpdcmain(
286         int argc,
287         char *argv[]
288         )
289 {
290         delay_time.l_ui = 0;
291         delay_time.l_uf = DEFDELAY;
292
293 #ifdef SYS_VXWORKS
294         clear_globals();
295         taskPrioritySet(taskIdSelf(), 100 );
296 #endif
297
298         init_lib();     /* sets up ipv4_works, ipv6_works */
299         ssl_applink();
300         init_auth();
301
302         /* Check to see if we have IPv6. Otherwise default to IPv4 */
303         if (!ipv6_works)
304                 ai_fam_default = AF_INET;
305
306         progname = argv[0];
307
308         {
309                 int optct = ntpOptionProcess(&ntpdcOptions, argc, argv);
310                 argc -= optct;
311                 argv += optct;
312         }
313
314         if (HAVE_OPT(IPV4))
315                 ai_fam_templ = AF_INET;
316         else if (HAVE_OPT(IPV6))
317                 ai_fam_templ = AF_INET6;
318         else
319                 ai_fam_templ = ai_fam_default;
320
321         if (HAVE_OPT(COMMAND)) {
322                 int             cmdct = STACKCT_OPT( COMMAND );
323                 const char**    cmds  = STACKLST_OPT( COMMAND );
324
325                 while (cmdct-- > 0) {
326                         ADDCMD(*cmds++);
327                 }
328         }
329
330         debug = OPT_VALUE_SET_DEBUG_LEVEL;
331
332         if (HAVE_OPT(INTERACTIVE)) {
333                 interactive = 1;
334         }
335
336         if (HAVE_OPT(NUMERIC)) {
337                 showhostnames = 0;
338         }
339
340         if (HAVE_OPT(LISTPEERS)) {
341                 ADDCMD("listpeers");
342         }
343
344         if (HAVE_OPT(PEERS)) {
345                 ADDCMD("peers");
346         }
347
348         if (HAVE_OPT(SHOWPEERS)) {
349                 ADDCMD("dmpeers");
350         }
351
352         if (ntp_optind == argc) {
353                 ADDHOST(DEFHOST);
354         } else {
355                 for (; ntp_optind < argc; ntp_optind++)
356                     ADDHOST(argv[ntp_optind]);
357         }
358
359         if (numcmds == 0 && interactive == 0
360             && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
361                 interactive = 1;
362         }
363
364 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
365         if (interactive)
366                 (void) signal_no_reset(SIGINT, abortcmd);
367 #endif /* SYS_WINNT */
368
369         /*
370          * Initialize the packet data buffer
371          */
372         pktdatasize = INITDATASIZE;
373         pktdata = emalloc(INITDATASIZE);
374
375         if (numcmds == 0) {
376                 (void) openhost(chosts[0]);
377                 getcmds();
378         } else {
379                 int ihost;
380                 int icmd;
381
382                 for (ihost = 0; ihost < numhosts; ihost++) {
383                         if (openhost(chosts[ihost]))
384                             for (icmd = 0; icmd < numcmds; icmd++) {
385                                     if (numhosts > 1) 
386                                         printf ("--- %s ---\n",chosts[ihost]);
387                                     docmd(ccmds[icmd]);
388                             }
389                 }
390         }
391 #ifdef SYS_WINNT
392         WSACleanup();
393 #endif
394         return(0);
395 } /* main end */
396
397
398 /*
399  * openhost - open a socket to a host
400  */
401 static int
402 openhost(
403         const char *hname
404         )
405 {
406         char temphost[LENHOSTNAME];
407         int a_info;
408         struct addrinfo hints, *ai = NULL;
409         sockaddr_u addr;
410         size_t octets;
411         const char *cp;
412         char name[LENHOSTNAME];
413         char service[5];
414
415         /*
416          * We need to get by the [] if they were entered 
417          */
418         if (*hname == '[') {
419                 cp = strchr(hname + 1, ']');
420                 if (!cp || (octets = (size_t)(cp - hname) - 1) >= sizeof(name)) {
421                         errno = EINVAL;
422                         warning("%s", "bad hostname/address");
423                         return 0;
424                 }
425                 memcpy(name, hname + 1, octets);
426                 name[octets] = '\0';
427                 hname = name;
428         }
429
430         /*
431          * First try to resolve it as an ip address and if that fails,
432          * do a fullblown (dns) lookup. That way we only use the dns
433          * when it is needed and work around some implementations that
434          * will return an "IPv4-mapped IPv6 address" address if you
435          * give it an IPv4 address to lookup.
436          */
437         strlcpy(service, "ntp", sizeof(service));
438         ZERO(hints);
439         hints.ai_family = ai_fam_templ;
440         hints.ai_protocol = IPPROTO_UDP;
441         hints.ai_socktype = SOCK_DGRAM;
442         hints.ai_flags = Z_AI_NUMERICHOST;
443
444         a_info = getaddrinfo(hname, service, &hints, &ai);
445         if (a_info == EAI_NONAME
446 #ifdef EAI_NODATA
447             || a_info == EAI_NODATA
448 #endif
449            ) {
450                 hints.ai_flags = AI_CANONNAME;
451 #ifdef AI_ADDRCONFIG
452                 hints.ai_flags |= AI_ADDRCONFIG;
453 #endif
454                 a_info = getaddrinfo(hname, service, &hints, &ai);      
455         }
456         /* Some older implementations don't like AI_ADDRCONFIG. */
457         if (a_info == EAI_BADFLAGS) {
458                 hints.ai_flags = AI_CANONNAME;
459                 a_info = getaddrinfo(hname, service, &hints, &ai);      
460         }
461         if (a_info != 0) {
462                 fprintf(stderr, "%s\n", gai_strerror(a_info));
463                 if (ai != NULL)
464                         freeaddrinfo(ai);
465                 return 0;
466         }
467
468         /* 
469          * getaddrinfo() has returned without error so ai should not 
470          * be NULL.
471          */
472         INSIST(ai != NULL);
473         ZERO(addr);
474         octets = min(sizeof(addr), ai->ai_addrlen);
475         memcpy(&addr, ai->ai_addr, octets);
476
477         if (ai->ai_canonname == NULL)
478                 strlcpy(temphost, stoa(&addr), sizeof(temphost));
479         else
480                 strlcpy(temphost, ai->ai_canonname, sizeof(temphost));
481
482         if (debug > 2)
483                 printf("Opening host %s\n", temphost);
484
485         if (havehost == 1) {
486                 if (debug > 2)
487                         printf("Closing old host %s\n", currenthost);
488                 closesocket(sockfd);
489                 havehost = 0;
490         }
491         strlcpy(currenthost, temphost, sizeof(currenthost));
492         
493         /* port maps to the same in both families */
494         s_port = NSRCPORT(&addr);; 
495 #ifdef SYS_VXWORKS
496         ((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
497         if (ai->ai_family == AF_INET)
498                 *(struct sockaddr_in *)&hostaddr= 
499                         *((struct sockaddr_in *)ai->ai_addr);
500         else 
501                 *(struct sockaddr_in6 *)&hostaddr= 
502                         *((struct sockaddr_in6 *)ai->ai_addr);
503 #endif /* SYS_VXWORKS */
504
505 #ifdef SYS_WINNT
506         {
507                 int optionValue = SO_SYNCHRONOUS_NONALERT;
508                 int err;
509
510                 err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (void *)&optionValue, sizeof(optionValue));
511                 if (err != NO_ERROR) {
512                         (void) fprintf(stderr, "cannot open nonoverlapped sockets\n");
513                         exit(1);
514                 }
515         }
516 #endif /* SYS_WINNT */
517
518         sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
519         if (sockfd == INVALID_SOCKET) {
520                 error("socket");
521                 exit(-1);
522         }
523         
524 #ifdef NEED_RCVBUF_SLOP
525 # ifdef SO_RCVBUF
526         {
527                 int rbufsize = INITDATASIZE + 2048; /* 2K for slop */
528
529                 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
530                                (void *)&rbufsize, sizeof(int)) == -1)
531                     error("setsockopt");
532         }
533 # endif
534 #endif
535
536 #ifdef SYS_VXWORKS
537         if (connect(sockfd, (struct sockaddr *)&hostaddr, 
538                     sizeof(hostaddr)) == -1)
539 #else
540         if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == -1)
541 #endif /* SYS_VXWORKS */
542         {
543                 error("connect");
544                 exit(-1);
545         }
546
547         freeaddrinfo(ai);
548         havehost = 1;
549         req_pkt_size = REQ_LEN_NOMAC;
550         impl_ver = IMPL_XNTPD;
551         return 1;
552 }
553
554
555 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
556 /*
557  * sendpkt - send a packet to the remote host
558  */
559 static int
560 sendpkt(
561         void *  xdata,
562         size_t  xdatalen
563         )
564 {
565         if (send(sockfd, xdata, xdatalen, 0) == -1) {
566                 warning("write to %s failed", currenthost);
567                 return -1;
568         }
569
570         return 0;
571 }
572
573
574 /*
575  * growpktdata - grow the packet data area
576  */
577 static void
578 growpktdata(void)
579 {
580         size_t priorsz;
581
582         priorsz = (size_t)pktdatasize;
583         pktdatasize += INCDATASIZE;
584         pktdata = erealloc_zero(pktdata, (size_t)pktdatasize, priorsz);
585 }
586
587
588 /*
589  * getresponse - get a (series of) response packet(s) and return the data
590  */
591 static int
592 getresponse(
593         int implcode,
594         int reqcode,
595         size_t *ritems,
596         size_t *rsize,
597         const char **rdata,
598         size_t esize
599         )
600 {
601         struct resp_pkt rpkt;
602         struct sock_timeval tvo;
603         size_t items;
604         size_t i;
605         size_t size;
606         size_t datasize;
607         char *datap;
608         char *tmp_data;
609         char haveseq[MAXSEQ+1];
610         int firstpkt;
611         int lastseq;
612         int numrecv;
613         int seq;
614         fd_set fds;
615         ssize_t n;
616         int pad;
617         /* absolute timeout checks. Not 'time_t' by intention! */
618         uint32_t tobase;        /* base value for timeout */
619         uint32_t tospan;        /* timeout span (max delay) */
620         uint32_t todiff;        /* current delay */
621
622         /*
623          * This is pretty tricky.  We may get between 1 and many packets
624          * back in response to the request.  We peel the data out of
625          * each packet and collect it in one long block.  When the last
626          * packet in the sequence is received we'll know how many we
627          * should have had.  Note we use one long time out, should reconsider.
628          */
629         *ritems = 0;
630         *rsize = 0;
631         firstpkt = 1;
632         numrecv = 0;
633         *rdata = datap = pktdata;
634         lastseq = 999;  /* too big to be a sequence number */
635         ZERO(haveseq);
636         FD_ZERO(&fds);
637         tobase = (uint32_t)time(NULL);
638
639     again:
640         if (firstpkt)
641                 tvo = tvout;
642         else
643                 tvo = tvsout;
644         tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
645         
646         FD_SET(sockfd, &fds);
647         n = select(sockfd+1, &fds, NULL, NULL, &tvo);
648         if (n == -1) {
649                 warning("select fails");
650                 return -1;
651         }
652         
653         /*
654          * Check if this is already too late. Trash the data and fake a
655          * timeout if this is so.
656          */
657         todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
658         if ((n > 0) && (todiff > tospan)) {
659                 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
660                 n -= n; /* faked timeout return from 'select()'*/
661         }
662         
663         if (n == 0) {
664                 /*
665                  * Timed out.  Return what we have
666                  */
667                 if (firstpkt) {
668                         (void) fprintf(stderr,
669                                        "%s: timed out, nothing received\n",
670                                        currenthost);
671                         return ERR_TIMEOUT;
672                 } else {
673                         (void) fprintf(stderr,
674                                        "%s: timed out with incomplete data\n",
675                                        currenthost);
676                         if (debug) {
677                                 printf("Received sequence numbers");
678                                 for (n = 0; n <= MAXSEQ; n++)
679                                     if (haveseq[n])
680                                         printf(" %zd,", (size_t)n);
681                                 if (lastseq != 999)
682                                     printf(" last frame received\n");
683                                 else
684                                     printf(" last frame not received\n");
685                         }
686                         return ERR_INCOMPLETE;
687                 }
688         }
689
690         n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
691         if (n == -1) {
692                 warning("read");
693                 return -1;
694         }
695
696
697         /*
698          * Check for format errors.  Bug proofing.
699          */
700         if (n < (ssize_t)RESP_HEADER_SIZE) {
701                 if (debug)
702                         printf("Short (%zd byte) packet received\n", (size_t)n);
703                 goto again;
704         }
705         if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION ||
706             INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) {
707                 if (debug)
708                         printf("Packet received with version %d\n",
709                                INFO_VERSION(rpkt.rm_vn_mode));
710                 goto again;
711         }
712         if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) {
713                 if (debug)
714                         printf("Packet received with mode %d\n",
715                                INFO_MODE(rpkt.rm_vn_mode));
716                 goto again;
717         }
718         if (INFO_IS_AUTH(rpkt.auth_seq)) {
719                 if (debug)
720                         printf("Encrypted packet received\n");
721                 goto again;
722         }
723         if (!ISRESPONSE(rpkt.rm_vn_mode)) {
724                 if (debug)
725                         printf("Received request packet, wanted response\n");
726                 goto again;
727         }
728         if (INFO_MBZ(rpkt.mbz_itemsize) != 0) {
729                 if (debug)
730                         printf("Received packet with nonzero MBZ field!\n");
731                 goto again;
732         }
733
734         /*
735          * Check implementation/request.  Could be old data getting to us.
736          */
737         if (rpkt.implementation != implcode || rpkt.request != reqcode) {
738                 if (debug)
739                         printf(
740                             "Received implementation/request of %d/%d, wanted %d/%d",
741                             rpkt.implementation, rpkt.request,
742                             implcode, reqcode);
743                 goto again;
744         }
745
746         /*
747          * Check the error code.  If non-zero, return it.
748          */
749         if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) {
750                 if (debug && ISMORE(rpkt.rm_vn_mode)) {
751                         printf("Error code %d received on not-final packet\n",
752                                INFO_ERR(rpkt.err_nitems));
753                 }
754                 return (int)INFO_ERR(rpkt.err_nitems);
755         }
756
757         /*
758          * Collect items and size.  Make sure they make sense.
759          */
760         items = INFO_NITEMS(rpkt.err_nitems);
761         size = INFO_ITEMSIZE(rpkt.mbz_itemsize);
762         if (esize > size)
763                 pad = esize - size;
764         else 
765                 pad = 0;
766         datasize = items * size;
767         if ((size_t)datasize > (n-RESP_HEADER_SIZE)) {
768                 if (debug)
769                     printf(
770                             "Received items %zu, size %zu (total %zu), data in packet is %zu\n",
771                             items, size, datasize, n-RESP_HEADER_SIZE);
772                 goto again;
773         }
774
775         /*
776          * If this isn't our first packet, make sure the size matches
777          * the other ones.
778          */
779         if (!firstpkt && size != *rsize) {
780                 if (debug)
781                     printf("Received itemsize %zu, previous %zu\n",
782                            size, *rsize);
783                 goto again;
784         }
785         /*
786          * If we've received this before, +toss it
787          */
788         seq = INFO_SEQ(rpkt.auth_seq);
789         if (haveseq[seq]) {
790                 if (debug)
791                     printf("Received duplicate sequence number %d\n", seq);
792                 goto again;
793         }
794         haveseq[seq] = 1;
795
796         /*
797          * If this is the last in the sequence, record that.
798          */
799         if (!ISMORE(rpkt.rm_vn_mode)) {
800                 if (lastseq != 999) {
801                         printf("Received second end sequence packet\n");
802                         goto again;
803                 }
804                 lastseq = seq;
805         }
806
807         /*
808          * So far, so good.  Copy this data into the output array. Bump
809          * the timeout base, in case we expect more data.
810          */
811         tobase = (uint32_t)time(NULL);
812         if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
813                 size_t offset = datap - pktdata;
814                 growpktdata();
815                 *rdata = pktdata; /* might have been realloced ! */
816                 datap = pktdata + offset;
817         }
818         /* 
819          * We now move the pointer along according to size and number of
820          * items.  This is so we can play nice with older implementations
821          */
822
823         tmp_data = rpkt.u.data;
824         for (i = 0; i < items; i++) {
825                 memcpy(datap, tmp_data, (unsigned)size);
826                 tmp_data += size;
827                 zero_mem(datap + size, pad);
828                 datap += size + pad;
829         }
830
831         if (firstpkt) {
832                 firstpkt = 0;
833                 *rsize = size + pad;
834         }
835         *ritems += items;
836
837         /*
838          * Finally, check the count of received packets.  If we've got them
839          * all, return
840          */
841         ++numrecv;
842         if (numrecv <= lastseq)
843                 goto again;
844         return INFO_OKAY;
845 }
846
847
848 /*
849  * sendrequest - format and send a request packet
850  *
851  * Historically, ntpdc has used a fixed-size request packet regardless
852  * of the actual payload size.  When authenticating, the timestamp, key
853  * ID, and digest have been placed just before the end of the packet.
854  * With the introduction in late 2009 of support for authenticated
855  * ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we
856  * come up four bytes short.
857  *
858  * To maintain interop while allowing for larger digests, the behavior
859  * is unchanged when using 16-octet digests.  For larger digests, the
860  * timestamp, key ID, and digest are placed immediately following the
861  * request payload, with the overall packet size variable.  ntpd can
862  * distinguish 16-octet digests by the overall request size being
863  * REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled.  When using a
864  * longer digest, that request size should be avoided.
865  *
866  * With the form used with 20-octet and larger digests, the timestamp,
867  * key ID, and digest are located by ntpd relative to the start of the
868  * packet, and the size of the digest is then implied by the packet
869  * size.
870  */
871 static int
872 sendrequest(
873         int implcode,
874         int reqcode,
875         int auth,
876         size_t qitems,
877         size_t qsize,
878         const char *qdata
879         )
880 {
881         struct req_pkt qpkt;
882         size_t  datasize;
883         size_t  reqsize;
884         u_long  key_id;
885         l_fp    ts;
886         l_fp *  ptstamp;
887         size_t  maclen;
888         char *  pass;
889
890         ZERO(qpkt);
891         qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
892         qpkt.implementation = (u_char)implcode;
893         qpkt.request = (u_char)reqcode;
894
895         datasize = qitems * qsize;
896         if (datasize && qdata != NULL) {
897                 memcpy(qpkt.u.data, qdata, datasize);
898                 qpkt.err_nitems = ERR_NITEMS(0, qitems);
899                 qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);
900         } else {
901                 qpkt.err_nitems = ERR_NITEMS(0, 0);
902                 qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);  /* allow for optional first item */
903         }
904
905         if (!auth || (keyid_entered && info_auth_keyid == 0)) {
906                 qpkt.auth_seq = AUTH_SEQ(0, 0);
907                 return sendpkt(&qpkt, req_pkt_size);
908         }
909
910         if (info_auth_keyid == 0) {
911                 key_id = getkeyid("Keyid: ");
912                 if (!key_id) {
913                         fprintf(stderr, "Invalid key identifier\n");
914                         return 1;
915                 }
916                 info_auth_keyid = key_id;
917         }
918         if (!authistrusted(info_auth_keyid)) {
919                 pass = getpass_keytype(info_auth_keytype);
920                 if ('\0' == pass[0]) {
921                         fprintf(stderr, "Invalid password\n");
922                         return 1;
923                 }
924                 authusekey(info_auth_keyid, info_auth_keytype,
925                            (u_char *)pass);
926                 authtrust(info_auth_keyid, 1);
927         }
928         qpkt.auth_seq = AUTH_SEQ(1, 0);
929         if (info_auth_hashlen > 16) {
930                 /*
931                  * Only ntpd which expects REQ_LEN_NOMAC plus maclen
932                  * octets in an authenticated request using a 16 octet
933                  * digest (that is, a newer ntpd) will handle digests
934                  * larger than 16 octets, so for longer digests, do
935                  * not attempt to shorten the requests for downlevel
936                  * ntpd compatibility.
937                  */
938                 if (REQ_LEN_NOMAC != req_pkt_size)
939                         return 1;
940                 reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp);
941                 /* align to 32 bits */
942                 reqsize = (reqsize + 3) & ~3;
943         } else
944                 reqsize = req_pkt_size;
945         ptstamp = (void *)((char *)&qpkt + reqsize);
946         ptstamp--;
947         get_systime(&ts);
948         L_ADD(&ts, &delay_time);
949         HTONL_FP(&ts, ptstamp);
950         maclen = authencrypt(
951                 info_auth_keyid, (void *)&qpkt, size2int_chk(reqsize));
952         if (!maclen) {  
953                 fprintf(stderr, "Key not found\n");
954                 return 1;
955         } else if (maclen != (size_t)(info_auth_hashlen + sizeof(keyid_t))) {
956                 fprintf(stderr,
957                         "%zu octet MAC, %zu expected with %zu octet digest\n",
958                         maclen, (info_auth_hashlen + sizeof(keyid_t)),
959                         info_auth_hashlen);
960                 return 1;
961         }
962         return sendpkt(&qpkt, reqsize + maclen);
963 }
964
965
966 /*
967  * doquery - send a request and process the response
968  */
969 int
970 doquery(
971         int implcode,
972         int reqcode,
973         int auth,
974         size_t qitems,
975         size_t qsize,
976         const char *qdata,
977         size_t *ritems,
978         size_t *rsize,
979         const char **rdata,
980         int quiet_mask,
981         int esize
982         )
983 {
984         int res;
985         char junk[512];
986         fd_set fds;
987         struct sock_timeval tvzero;
988
989         /*
990          * Check to make sure host is open
991          */
992         if (!havehost) {
993                 (void) fprintf(stderr, "***No host open, use `host' command\n");
994                 return -1;
995         }
996
997         /*
998          * Poll the socket and clear out any pending data
999          */
1000 again:
1001         do {
1002                 tvzero.tv_sec = tvzero.tv_usec = 0;
1003                 FD_ZERO(&fds);
1004                 FD_SET(sockfd, &fds);
1005                 res = select(sockfd+1, &fds, NULL, NULL, &tvzero);
1006                 if (res == -1) {
1007                         warning("polling select");
1008                         return -1;
1009                 } else if (res > 0)
1010
1011                     (void) recv(sockfd, junk, sizeof junk, 0);
1012         } while (res > 0);
1013
1014
1015         /*
1016          * send a request
1017          */
1018         res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata);
1019         if (res != 0)
1020                 return res;
1021         
1022         /*
1023          * Get the response.  If we got a standard error, print a message
1024          */
1025         res = getresponse(implcode, reqcode, ritems, rsize, rdata, esize);
1026
1027         /*
1028          * Try to be compatible with older implementations of ntpd.
1029          */
1030         if (res == INFO_ERR_FMT && req_pkt_size != 48) {
1031                 int oldsize;
1032
1033                 oldsize = req_pkt_size;
1034
1035                 switch(req_pkt_size) {
1036                 case REQ_LEN_NOMAC:
1037                         req_pkt_size = 160;
1038                         break;
1039                 case 160:
1040                         req_pkt_size = 48;
1041                         break;
1042                 }
1043                 if (impl_ver == IMPL_XNTPD) {
1044                         fprintf(stderr,
1045                             "***Warning changing to older implementation\n");
1046                         return INFO_ERR_IMPL;
1047                 }
1048
1049                 fprintf(stderr,
1050                     "***Warning changing the request packet size from %d to %d\n",
1051                     oldsize, req_pkt_size);
1052                 goto again;
1053         }
1054
1055         /* log error message if not told to be quiet */
1056         if ((res > 0) && (((1 << res) & quiet_mask) == 0)) {
1057                 switch(res) {
1058                 case INFO_ERR_IMPL:
1059                         /* Give us a chance to try the older implementation. */
1060                         if (implcode == IMPL_XNTPD)
1061                                 break;
1062                         (void) fprintf(stderr,
1063                                        "***Server implementation incompatible with our own\n");
1064                         break;
1065                 case INFO_ERR_REQ:
1066                         (void) fprintf(stderr,
1067                                        "***Server doesn't implement this request\n");
1068                         break;
1069                 case INFO_ERR_FMT:
1070                         (void) fprintf(stderr,
1071                                        "***Server reports a format error in the received packet (shouldn't happen)\n");
1072                         break;
1073                 case INFO_ERR_NODATA:
1074                         (void) fprintf(stderr,
1075                                        "***Server reports data not found\n");
1076                         break;
1077                 case INFO_ERR_AUTH:
1078                         (void) fprintf(stderr, "***Permission denied\n");
1079                         break;
1080                 case ERR_TIMEOUT:
1081                         (void) fprintf(stderr, "***Request timed out\n");
1082                         break;
1083                 case ERR_INCOMPLETE:
1084                         (void) fprintf(stderr,
1085                                        "***Response from server was incomplete\n");
1086                         break;
1087                 default:
1088                         (void) fprintf(stderr,
1089                                        "***Server returns unknown error code %d\n", res);
1090                         break;
1091                 }
1092         }
1093         return res;
1094 }
1095
1096
1097 /*
1098  * getcmds - read commands from the standard input and execute them
1099  */
1100 static void
1101 getcmds(void)
1102 {
1103         char *  line;
1104         int     count;
1105
1106         ntp_readline_init(interactive ? prompt : NULL);
1107
1108         for (;;) {
1109                 line = ntp_readline(&count);
1110                 if (NULL == line)
1111                         break;
1112                 docmd(line);
1113                 free(line);
1114         }
1115
1116         ntp_readline_uninit();
1117 }
1118
1119
1120 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
1121 /*
1122  * abortcmd - catch interrupts and abort the current command
1123  */
1124 static RETSIGTYPE
1125 abortcmd(
1126         int sig
1127         )
1128 {
1129         if (current_output == stdout)
1130                 (void)fflush(stdout);
1131         putc('\n', stderr);
1132         (void)fflush(stderr);
1133         if (jump) {
1134                 jump = 0;
1135                 LONGJMP(interrupt_buf, 1);
1136         }
1137 }
1138 #endif /* SYS_WINNT */
1139
1140 /*
1141  * docmd - decode the command line and execute a command
1142  */
1143 static void
1144 docmd(
1145         const char *cmdline
1146         )
1147 {
1148         char *tokens[1+MAXARGS+MOREARGS+2];
1149         struct parse pcmd;
1150         int ntok;
1151         int i, ti;
1152         int rval;
1153         struct xcmd *xcmd;
1154
1155         ai_fam_templ = ai_fam_default;
1156         /*
1157          * Tokenize the command line.  If nothing on it, return.
1158          */
1159         if (strlen(cmdline) >= MAXLINE) {
1160                 fprintf(stderr, "***Command ignored, more than %d characters:\n%s\n",
1161                         MAXLINE - 1, cmdline);
1162                 return;
1163         }
1164         tokenize(cmdline, tokens, &ntok);
1165         if (ntok == 0)
1166             return;
1167         
1168         /*
1169          * Find the appropriate command description.
1170          */
1171         i = findcmd(tokens[0], builtins, opcmds, &xcmd);
1172         if (i == 0) {
1173                 (void) fprintf(stderr, "***Command `%s' unknown\n",
1174                                tokens[0]);
1175                 return;
1176         } else if (i >= 2) {
1177                 (void) fprintf(stderr, "***Command `%s' ambiguous\n",
1178                                tokens[0]);
1179                 return;
1180         }
1181         
1182         /*
1183          * Save the keyword, then walk through the arguments, interpreting
1184          * as we go.
1185          */
1186         pcmd.keyword = tokens[0];
1187         pcmd.nargs = 0;
1188         ti = 1;
1189         for (i = 0; i < MAXARGS && xcmd->arg[i] != NO;) {
1190                 if ((i+ti) >= ntok) {
1191                         if (!(xcmd->arg[i] & OPT)) {
1192                                 printusage(xcmd, stderr);
1193                                 return;
1194                         }
1195                         break;
1196                 }
1197                 if ((xcmd->arg[i] & OPT) && (*tokens[i+ti] == '>'))
1198                         break;
1199                 rval = getarg(tokens[i+ti], (int)xcmd->arg[i], &pcmd.argval[i]);
1200                 if (rval == -1) {
1201                         ti++;
1202                         continue;
1203                 }
1204                 if (rval == 0)
1205                         return;
1206                 pcmd.nargs++;
1207                 i++;
1208         }
1209
1210         /* Any extra args are assumed to be "OPT|NTP_STR". */
1211         for ( ; i < MAXARGS + MOREARGS;) {
1212              if ((i+ti) >= ntok)
1213                   break;
1214                 rval = getarg(tokens[i+ti], (int)(OPT|NTP_STR), &pcmd.argval[i]);
1215                 if (rval == -1) {
1216                         ti++;
1217                         continue;
1218                 }
1219                 if (rval == 0)
1220                         return;
1221                 pcmd.nargs++;
1222                 i++;
1223         }
1224
1225         i += ti;
1226         if (i < ntok && *tokens[i] == '>') {
1227                 char *fname;
1228
1229                 if (*(tokens[i]+1) != '\0')
1230                     fname = tokens[i]+1;
1231                 else if ((i+1) < ntok)
1232                     fname = tokens[i+1];
1233                 else {
1234                         (void) fprintf(stderr, "***No file for redirect\n");
1235                         return;
1236                 }
1237
1238                 current_output = fopen(fname, "w");
1239                 if (current_output == NULL) {
1240                         (void) fprintf(stderr, "***Error opening %s: ", fname);
1241                         perror("");
1242                         return;
1243                 }
1244         } else {
1245                 current_output = stdout;
1246         }
1247
1248         if (interactive) {
1249                 if ( ! SETJMP(interrupt_buf)) {
1250                         jump = 1;
1251                         (xcmd->handler)(&pcmd, current_output);
1252                         jump = 0;
1253                 } else {
1254                         fflush(current_output);
1255                         fputs("\n >>> command aborted <<<\n", stderr);
1256                         fflush(stderr);
1257                 }
1258         } else {
1259                 jump = 0;
1260                 (xcmd->handler)(&pcmd, current_output);
1261         }
1262         if ((NULL != current_output) && (stdout != current_output)) {
1263                 (void)fclose(current_output);
1264                 current_output = NULL;
1265         }
1266 }
1267
1268
1269 /*
1270  * tokenize - turn a command line into tokens
1271  */
1272 static void
1273 tokenize(
1274         const char *line,
1275         char **tokens,
1276         int *ntok
1277         )
1278 {
1279         register const char *cp;
1280         register char *sp;
1281         static char tspace[MAXLINE];
1282
1283         sp = tspace;
1284         cp = line;
1285         for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
1286                 tokens[*ntok] = sp;
1287                 while (ISSPACE(*cp))
1288                     cp++;
1289                 if (ISEOL(*cp))
1290                     break;
1291                 do {
1292                         *sp++ = *cp++;
1293                 } while (!ISSPACE(*cp) && !ISEOL(*cp));
1294
1295                 *sp++ = '\0';
1296         }
1297 }
1298
1299
1300
1301 /*
1302  * findcmd - find a command in a command description table
1303  */
1304 static int
1305 findcmd(
1306         register char *str,
1307         struct xcmd *clist1,
1308         struct xcmd *clist2,
1309         struct xcmd **cmd
1310         )
1311 {
1312         register struct xcmd *cl;
1313         size_t clen;
1314         int nmatch;
1315         struct xcmd *nearmatch = NULL;
1316         struct xcmd *clist;
1317
1318         clen = strlen(str);
1319         nmatch = 0;
1320         if (clist1 != 0)
1321             clist = clist1;
1322         else if (clist2 != 0)
1323             clist = clist2;
1324         else
1325             return 0;
1326
1327     again:
1328         for (cl = clist; cl->keyword != 0; cl++) {
1329                 /* do a first character check, for efficiency */
1330                 if (*str != *(cl->keyword))
1331                     continue;
1332                 if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
1333                         /*
1334                          * Could be extact match, could be approximate.
1335                          * Is exact if the length of the keyword is the
1336                          * same as the str.
1337                          */
1338                         if (*((cl->keyword) + clen) == '\0') {
1339                                 *cmd = cl;
1340                                 return 1;
1341                         }
1342                         nmatch++;
1343                         nearmatch = cl;
1344                 }
1345         }
1346
1347                                 /*
1348                                  * See if there is more to do.  If so, go again.  Sorry about the
1349                                  * goto, too much looking at BSD sources...
1350                                  */
1351         if (clist == clist1 && clist2 != 0) {
1352                 clist = clist2;
1353                 goto again;
1354         }
1355
1356                                 /*
1357                                  * If we got extactly 1 near match, use it, else return number
1358                                  * of matches.
1359                                  */
1360         if (nmatch == 1) {
1361                 *cmd = nearmatch;
1362                 return 1;
1363         }
1364         return nmatch;
1365 }
1366
1367
1368 /*
1369  * getarg - interpret an argument token
1370  *
1371  * string is always set.
1372  * type is set to the decoded type.
1373  *
1374  * return:       0 - failure
1375  *               1 - success
1376  *              -1 - skip to next token
1377  */
1378 static int
1379 getarg(
1380         char *str,
1381         int code,
1382         arg_v *argp
1383         )
1384 {
1385         int isneg;
1386         char *cp, *np;
1387         static const char *digits = "0123456789";
1388
1389         ZERO(*argp);
1390         argp->string = str;
1391         argp->type   = code & ~OPT;
1392
1393         switch (argp->type) {
1394             case NTP_STR:
1395                 break;
1396             case NTP_ADD:
1397                 if (!strcmp("-6", str)) {
1398                         ai_fam_templ = AF_INET6;
1399                         return -1;
1400                 } else if (!strcmp("-4", str)) {
1401                         ai_fam_templ = AF_INET;
1402                         return -1;
1403                 }
1404                 if (!getnetnum(str, &(argp->netnum), (char *)0, 0)) {
1405                         return 0;
1406                 }
1407                 break;
1408             case NTP_INT:
1409             case NTP_UINT:
1410                 isneg = 0;
1411                 np = str;
1412                 if (*np == '-') {
1413                         np++;
1414                         isneg = 1;
1415                 }
1416
1417                 argp->uval = 0;
1418                 do {
1419                         cp = strchr(digits, *np);
1420                         if (cp == NULL) {
1421                                 (void) fprintf(stderr,
1422                                                "***Illegal integer value %s\n", str);
1423                                 return 0;
1424                         }
1425                         argp->uval *= 10;
1426                         argp->uval += (u_long)(cp - digits);
1427                 } while (*(++np) != '\0');
1428
1429                 if (isneg) {
1430                         if ((code & ~OPT) == NTP_UINT) {
1431                                 (void) fprintf(stderr,
1432                                                "***Value %s should be unsigned\n", str);
1433                                 return 0;
1434                         }
1435                         argp->ival = -argp->ival;
1436                 }
1437                 break;
1438             case IP_VERSION:
1439                 if (!strcmp("-6", str))
1440                         argp->ival = 6 ;
1441                 else if (!strcmp("-4", str))
1442                         argp->ival = 4 ;
1443                 else {
1444                         (void) fprintf(stderr,
1445                             "***Version must be either 4 or 6\n");
1446                         return 0;
1447                 }
1448                 break;
1449         }
1450
1451         return 1;
1452 }
1453
1454
1455 /*
1456  * getnetnum - given a host name, return its net number
1457  *             and (optional) full name
1458  */
1459 static int
1460 getnetnum(
1461         const char *hname,
1462         sockaddr_u *num,
1463         char *fullhost,
1464         int af
1465         )
1466 {
1467         struct addrinfo hints, *ai = NULL;
1468
1469         ZERO(hints);
1470         hints.ai_flags = AI_CANONNAME;
1471 #ifdef AI_ADDRCONFIG
1472         hints.ai_flags |= AI_ADDRCONFIG;
1473 #endif
1474         
1475         /*
1476          * decodenetnum only works with addresses, but handles syntax
1477          * that getaddrinfo doesn't:  [2001::1]:1234
1478          */
1479         if (decodenetnum(hname, num)) {
1480                 if (fullhost != NULL)
1481                         getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1482                                     LENHOSTNAME, NULL, 0, 0);
1483                 return 1;
1484         } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1485                 INSIST(sizeof(*num) >= ai->ai_addrlen);
1486                 memcpy(num, ai->ai_addr, ai->ai_addrlen);
1487                 if (fullhost != NULL) {
1488                         if (ai->ai_canonname != NULL)
1489                                 strlcpy(fullhost, ai->ai_canonname,
1490                                         LENHOSTNAME);
1491                         else
1492                                 getnameinfo(&num->sa, SOCKLEN(num),
1493                                             fullhost, LENHOSTNAME, NULL,
1494                                             0, 0);
1495                 }
1496                 return 1;
1497         }
1498         fprintf(stderr, "***Can't find host %s\n", hname);
1499
1500         return 0;
1501 }
1502
1503
1504 /*
1505  * nntohost - convert network number to host name.  This routine enforces
1506  *             the showhostnames setting.
1507  */
1508 const char *
1509 nntohost(
1510         sockaddr_u *netnum
1511         )
1512 {
1513         if (!showhostnames || SOCK_UNSPEC(netnum))
1514                 return stoa(netnum);
1515         else if (ISREFCLOCKADR(netnum))
1516                 return refnumtoa(netnum);
1517         else
1518                 return socktohost(netnum);
1519 }
1520
1521
1522 /*
1523  * Finally, the built in command handlers
1524  */
1525
1526 /*
1527  * help - tell about commands, or details of a particular command
1528  */
1529 static void
1530 help(
1531         struct parse *pcmd,
1532         FILE *fp
1533         )
1534 {
1535         struct xcmd *xcp;
1536         char *cmd;
1537         const char *list[100];
1538         size_t word, words;
1539         size_t row, rows;
1540         size_t col, cols;
1541         size_t length;
1542
1543         if (pcmd->nargs == 0) {
1544                 words = 0;
1545                 for (xcp = builtins; xcp->keyword != 0; xcp++) {
1546                         if (*(xcp->keyword) != '?')
1547                                 list[words++] = xcp->keyword;
1548                 }
1549                 for (xcp = opcmds; xcp->keyword != 0; xcp++)
1550                         list[words++] = xcp->keyword;
1551
1552                 qsort((void *)list, words, sizeof(list[0]), helpsort);
1553                 col = 0;
1554                 for (word = 0; word < words; word++) {
1555                         length = strlen(list[word]);
1556                         col = max(col, length);
1557                 }
1558
1559                 cols = SCREENWIDTH / ++col;
1560                 rows = (words + cols - 1) / cols;
1561
1562                 fprintf(fp, "ntpdc commands:\n");
1563
1564                 for (row = 0; row < rows; row++) {
1565                         for (word = row; word < words; word += rows)
1566                                 fprintf(fp, "%-*.*s", (int)col,
1567                                         (int)col - 1, list[word]);
1568                         fprintf(fp, "\n");
1569                 }
1570         } else {
1571                 cmd = pcmd->argval[0].string;
1572                 words = findcmd(cmd, builtins, opcmds, &xcp);
1573                 if (words == 0) {
1574                         fprintf(stderr,
1575                                 "Command `%s' is unknown\n", cmd);
1576                         return;
1577                 } else if (words >= 2) {
1578                         fprintf(stderr,
1579                                 "Command `%s' is ambiguous\n", cmd);
1580                         return;
1581                 }
1582                 fprintf(fp, "function: %s\n", xcp->comment);
1583                 printusage(xcp, fp);
1584         }
1585 }
1586
1587
1588 /*
1589  * helpsort - do hostname qsort comparisons
1590  */
1591 static int
1592 helpsort(
1593         const void *t1,
1594         const void *t2
1595         )
1596 {
1597         const char * const *    name1 = t1;
1598         const char * const *    name2 = t2;
1599
1600         return strcmp(*name1, *name2);
1601 }
1602
1603
1604 /*
1605  * printusage - print usage information for a command
1606  */
1607 static void
1608 printusage(
1609         struct xcmd *xcp,
1610         FILE *fp
1611         )
1612 {
1613         int i, opt46;
1614
1615         opt46 = 0;
1616         (void) fprintf(fp, "usage: %s", xcp->keyword);
1617         for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
1618                 if (opt46 == 0 && (xcp->arg[i] & ~OPT) == NTP_ADD) {
1619                         (void) fprintf(fp, " [ -4|-6 ]");
1620                         opt46 = 1;
1621                 }
1622                 if (xcp->arg[i] & OPT)
1623                     (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
1624                 else
1625                     (void) fprintf(fp, " %s", xcp->desc[i]);
1626         }
1627         (void) fprintf(fp, "\n");
1628 }
1629
1630
1631 /*
1632  * timeout - set time out time
1633  */
1634 static void
1635 timeout(
1636         struct parse *pcmd,
1637         FILE *fp
1638         )
1639 {
1640         int val;
1641
1642         if (pcmd->nargs == 0) {
1643                 val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
1644                 (void) fprintf(fp, "primary timeout %d ms\n", val);
1645         } else {
1646                 tvout.tv_sec = pcmd->argval[0].uval / 1000;
1647                 tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000))
1648                         * 1000;
1649         }
1650 }
1651
1652
1653 /*
1654  * my_delay - set delay for auth requests
1655  */
1656 static void
1657 my_delay(
1658         struct parse *pcmd,
1659         FILE *fp
1660         )
1661 {
1662         int isneg;
1663         u_long val;
1664
1665         if (pcmd->nargs == 0) {
1666                 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
1667                 (void) fprintf(fp, "delay %lu ms\n", val);
1668         } else {
1669                 if (pcmd->argval[0].ival < 0) {
1670                         isneg = 1;
1671                         val = (u_long)(-pcmd->argval[0].ival);
1672                 } else {
1673                         isneg = 0;
1674                         val = (u_long)pcmd->argval[0].ival;
1675                 }
1676
1677                 delay_time.l_ui = val / 1000;
1678                 val %= 1000;
1679                 delay_time.l_uf = val * 4294967;        /* 2**32/1000 */
1680
1681                 if (isneg)
1682                     L_NEG(&delay_time);
1683         }
1684 }
1685
1686
1687 /*
1688  * host - set the host we are dealing with.
1689  */
1690 static void
1691 host(
1692         struct parse *pcmd,
1693         FILE *fp
1694         )
1695 {
1696         int i;
1697
1698         if (pcmd->nargs == 0) {
1699                 if (havehost)
1700                     (void) fprintf(fp, "current host is %s\n", currenthost);
1701                 else
1702                     (void) fprintf(fp, "no current host\n");
1703                 return;
1704         }
1705
1706         i = 0;
1707         if (pcmd->nargs == 2) {
1708                 if (!strcmp("-4", pcmd->argval[i].string))
1709                         ai_fam_templ = AF_INET;
1710                 else if (!strcmp("-6", pcmd->argval[i].string))
1711                         ai_fam_templ = AF_INET6;
1712                 else {
1713                         if (havehost)
1714                                 (void) fprintf(fp,
1715                                     "current host remains %s\n", currenthost);
1716                         else
1717                                 (void) fprintf(fp, "still no current host\n");
1718                         return;
1719                 }
1720                 i = 1;
1721         }
1722         if (openhost(pcmd->argval[i].string)) {
1723                 (void) fprintf(fp, "current host set to %s\n", currenthost);
1724         } else {
1725                 if (havehost)
1726                     (void) fprintf(fp,
1727                                    "current host remains %s\n", currenthost);
1728                 else
1729                     (void) fprintf(fp, "still no current host\n");
1730         }
1731 }
1732
1733
1734 /*
1735  * keyid - get a keyid to use for authenticating requests
1736  */
1737 static void
1738 keyid(
1739         struct parse *pcmd,
1740         FILE *fp
1741         )
1742 {
1743         if (pcmd->nargs == 0) {
1744                 if (info_auth_keyid == 0 && !keyid_entered)
1745                     (void) fprintf(fp, "no keyid defined\n");
1746                 else if (info_auth_keyid == 0 && keyid_entered)
1747                     (void) fprintf(fp, "no keyid will be sent\n");
1748                 else
1749                     (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
1750         } else {
1751                 info_auth_keyid = pcmd->argval[0].uval;
1752                 keyid_entered = 1;
1753         }
1754 }
1755
1756
1757 /*
1758  * keytype - get type of key to use for authenticating requests
1759  */
1760 static void
1761 keytype(
1762         struct parse *pcmd,
1763         FILE *fp
1764         )
1765 {
1766         const char *    digest_name;
1767         size_t          digest_len;
1768         int             key_type;
1769
1770         if (!pcmd->nargs) {
1771                 fprintf(fp, "keytype is %s with %lu octet digests\n",
1772                         keytype_name(info_auth_keytype),
1773                         (u_long)info_auth_hashlen);
1774                 return;
1775         }
1776
1777         digest_name = pcmd->argval[0].string;
1778         digest_len = 0;
1779         key_type = keytype_from_text(digest_name, &digest_len);
1780
1781         if (!key_type) {
1782                 fprintf(fp, "keytype must be 'md5'%s\n",
1783 #ifdef OPENSSL
1784                         " or a digest type provided by OpenSSL");
1785 #else
1786                         "");
1787 #endif
1788                 return;
1789         }
1790
1791         info_auth_keytype = key_type;
1792         info_auth_hashlen = digest_len;
1793 }
1794
1795
1796 /*
1797  * passwd - get an authentication key
1798  */
1799 /*ARGSUSED*/
1800 static void
1801 passwd(
1802         struct parse *pcmd,
1803         FILE *fp
1804         )
1805 {
1806         char *pass;
1807
1808         if (info_auth_keyid == 0) {
1809                 info_auth_keyid = getkeyid("Keyid: ");
1810                 if (info_auth_keyid == 0) {
1811                         (void)fprintf(fp, "Keyid must be defined\n");
1812                         return;
1813                 }
1814         }
1815         if (pcmd->nargs >= 1)
1816                 pass = pcmd->argval[0].string;
1817         else {
1818                 pass = getpass_keytype(info_auth_keytype);
1819                 if ('\0' == *pass) {
1820                         fprintf(fp, "Password unchanged\n");
1821                         return;
1822                 }
1823         }
1824         authusekey(info_auth_keyid, info_auth_keytype, (u_char *)pass);
1825         authtrust(info_auth_keyid, 1);
1826 }
1827
1828
1829 /*
1830  * hostnames - set the showhostnames flag
1831  */
1832 static void
1833 hostnames(
1834         struct parse *pcmd,
1835         FILE *fp
1836         )
1837 {
1838         if (pcmd->nargs == 0) {
1839                 if (showhostnames)
1840                     (void) fprintf(fp, "hostnames being shown\n");
1841                 else
1842                     (void) fprintf(fp, "hostnames not being shown\n");
1843         } else {
1844                 if (STREQ(pcmd->argval[0].string, "yes"))
1845                     showhostnames = 1;
1846                 else if (STREQ(pcmd->argval[0].string, "no"))
1847                     showhostnames = 0;
1848                 else
1849                     (void)fprintf(stderr, "What?\n");
1850         }
1851 }
1852
1853
1854 /*
1855  * setdebug - set/change debugging level
1856  */
1857 static void
1858 setdebug(
1859         struct parse *pcmd,
1860         FILE *fp
1861         )
1862 {
1863         if (pcmd->nargs == 0) {
1864                 (void) fprintf(fp, "debug level is %d\n", debug);
1865                 return;
1866         } else if (STREQ(pcmd->argval[0].string, "no")) {
1867                 debug = 0;
1868         } else if (STREQ(pcmd->argval[0].string, "more")) {
1869                 debug++;
1870         } else if (STREQ(pcmd->argval[0].string, "less")) {
1871                 debug--;
1872         } else {
1873                 (void) fprintf(fp, "What?\n");
1874                 return;
1875         }
1876         (void) fprintf(fp, "debug level set to %d\n", debug);
1877 }
1878
1879
1880 /*
1881  * quit - stop this nonsense
1882  */
1883 /*ARGSUSED*/
1884 static void
1885 quit(
1886         struct parse *pcmd,
1887         FILE *fp
1888         )
1889 {
1890         if (havehost)
1891             closesocket(sockfd);
1892         exit(0);
1893 }
1894
1895
1896 /*
1897  * version - print the current version number
1898  */
1899 /*ARGSUSED*/
1900 static void
1901 version(
1902         struct parse *pcmd,
1903         FILE *fp
1904         )
1905 {
1906
1907         (void) fprintf(fp, "%s\n", Version);
1908         return;
1909 }
1910
1911
1912 static void __attribute__((__format__(__printf__, 1, 0)))
1913 vwarning(const char *fmt, va_list ap)
1914 {
1915         int serrno = errno;
1916         (void) fprintf(stderr, "%s: ", progname);
1917         vfprintf(stderr, fmt, ap);
1918         (void) fprintf(stderr, ": %s\n", strerror(serrno));
1919 }
1920
1921 /*
1922  * warning - print a warning message
1923  */
1924 static void __attribute__((__format__(__printf__, 1, 2)))
1925 warning(
1926         const char *fmt,
1927         ...
1928         )
1929 {
1930         va_list ap;
1931         va_start(ap, fmt);
1932         vwarning(fmt, ap);
1933         va_end(ap);
1934 }
1935
1936
1937 /*
1938  * error - print a message and exit
1939  */
1940 static void __attribute__((__format__(__printf__, 1, 2)))
1941 error(
1942         const char *fmt,
1943         ...
1944         )
1945 {
1946         va_list ap;
1947         va_start(ap, fmt);
1948         vwarning(fmt, ap);
1949         va_end(ap);
1950         exit(1);
1951 }
1952
1953 /*
1954  * getkeyid - prompt the user for a keyid to use
1955  */
1956 static u_long
1957 getkeyid(
1958         const char *keyprompt
1959         )
1960 {
1961         int c;
1962         FILE *fi;
1963         char pbuf[20];
1964         size_t i;
1965         size_t ilim;
1966
1967 #ifndef SYS_WINNT
1968         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
1969 #else
1970         if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
1971 #endif /* SYS_WINNT */
1972                 fi = stdin;
1973         else
1974                 setbuf(fi, (char *)NULL);
1975         fprintf(stderr, "%s", keyprompt); fflush(stderr);
1976         for (i = 0, ilim = COUNTOF(pbuf) - 1;
1977              i < ilim && (c = getc(fi)) != '\n' && c != EOF;
1978              )
1979                 pbuf[i++] = (char)c;
1980         pbuf[i] = '\0';
1981         if (fi != stdin)
1982                 fclose(fi);
1983
1984         return (u_long) atoi(pbuf);
1985 }