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