]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpdc/ntpdc.c
Fix multiple denial of service in ntpd.
[FreeBSD/FreeBSD.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 = AF_UNSPEC;           /* address family */
180 static  int ai_fam_default = AF_UNSPEC; /* 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_default = AF_INET;
316         else if (HAVE_OPT(IPV6))
317                 ai_fam_default = AF_INET6;
318
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         ZERO(*argp);
1386         argp->string = str;
1387         argp->type   = code & ~OPT;
1388
1389         switch (argp->type) {
1390         case NTP_STR:
1391                 break;
1392         case NTP_ADD:
1393                 if (!strcmp("-6", str)) {
1394                         ai_fam_templ = AF_INET6;
1395                         return -1;
1396                 } else if (!strcmp("-4", str)) {
1397                         ai_fam_templ = AF_INET;
1398                         return -1;
1399                 }
1400                 if (!getnetnum(str, &(argp->netnum), (char *)0, ai_fam_templ)) {
1401                         return 0;
1402                 }
1403                 break;
1404         case NTP_UINT:
1405                 if (!atouint(str, &argp->uval)) {
1406                         fprintf(stderr, "***Illegal unsigned value %s\n",
1407                                 str);
1408                         return 0;
1409                 }
1410                 break;
1411         case NTP_INT:
1412                 if (!atoint(str, &argp->ival)) {
1413                         fprintf(stderr, "***Illegal integer value %s\n",
1414                                 str);
1415                         return 0;
1416                 }
1417                 break;
1418         case IP_VERSION:
1419                 if (!strcmp("-6", str))
1420                         argp->ival = 6 ;
1421                 else if (!strcmp("-4", str))
1422                         argp->ival = 4 ;
1423                 else {
1424                         (void) fprintf(stderr,
1425                             "***Version must be either 4 or 6\n");
1426                         return 0;
1427                 }
1428                 break;
1429         }
1430
1431         return 1;
1432 }
1433
1434
1435 /*
1436  * getnetnum - given a host name, return its net number
1437  *             and (optional) full name
1438  */
1439 static int
1440 getnetnum(
1441         const char *hname,
1442         sockaddr_u *num,
1443         char *fullhost,
1444         int af
1445         )
1446 {
1447         struct addrinfo hints, *ai = NULL;
1448
1449         ZERO(hints);
1450         hints.ai_family = af;
1451         hints.ai_flags = AI_CANONNAME;
1452 #ifdef AI_ADDRCONFIG
1453         hints.ai_flags |= AI_ADDRCONFIG;
1454 #endif
1455         
1456         /*
1457          * decodenetnum only works with addresses, but handles syntax
1458          * that getaddrinfo doesn't:  [2001::1]:1234
1459          */
1460         if (decodenetnum(hname, num)) {
1461                 if (fullhost != NULL)
1462                         getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1463                                     LENHOSTNAME, NULL, 0, 0);
1464                 return 1;
1465         } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1466                 INSIST(sizeof(*num) >= ai->ai_addrlen);
1467                 memcpy(num, ai->ai_addr, ai->ai_addrlen);
1468                 if (fullhost != NULL) {
1469                         if (ai->ai_canonname != NULL)
1470                                 strlcpy(fullhost, ai->ai_canonname,
1471                                         LENHOSTNAME);
1472                         else
1473                                 getnameinfo(&num->sa, SOCKLEN(num),
1474                                             fullhost, LENHOSTNAME, NULL,
1475                                             0, 0);
1476                 }
1477                 return 1;
1478         }
1479         fprintf(stderr, "***Can't find host %s\n", hname);
1480
1481         return 0;
1482 }
1483
1484
1485 /*
1486  * nntohost - convert network number to host name.  This routine enforces
1487  *             the showhostnames setting.
1488  */
1489 const char *
1490 nntohost(
1491         sockaddr_u *netnum
1492         )
1493 {
1494         if (!showhostnames || SOCK_UNSPEC(netnum))
1495                 return stoa(netnum);
1496         else if (ISREFCLOCKADR(netnum))
1497                 return refnumtoa(netnum);
1498         else
1499                 return socktohost(netnum);
1500 }
1501
1502
1503 /*
1504  * Finally, the built in command handlers
1505  */
1506
1507 /*
1508  * help - tell about commands, or details of a particular command
1509  */
1510 static void
1511 help(
1512         struct parse *pcmd,
1513         FILE *fp
1514         )
1515 {
1516         struct xcmd *xcp;
1517         char *cmd;
1518         const char *list[100];
1519         size_t word, words;
1520         size_t row, rows;
1521         size_t col, cols;
1522         size_t length;
1523
1524         if (pcmd->nargs == 0) {
1525                 words = 0;
1526                 for (xcp = builtins; xcp->keyword != 0; xcp++) {
1527                         if (*(xcp->keyword) != '?')
1528                                 list[words++] = xcp->keyword;
1529                 }
1530                 for (xcp = opcmds; xcp->keyword != 0; xcp++)
1531                         list[words++] = xcp->keyword;
1532
1533                 qsort((void *)list, words, sizeof(list[0]), helpsort);
1534                 col = 0;
1535                 for (word = 0; word < words; word++) {
1536                         length = strlen(list[word]);
1537                         col = max(col, length);
1538                 }
1539
1540                 cols = SCREENWIDTH / ++col;
1541                 rows = (words + cols - 1) / cols;
1542
1543                 fprintf(fp, "ntpdc commands:\n");
1544
1545                 for (row = 0; row < rows; row++) {
1546                         for (word = row; word < words; word += rows)
1547                                 fprintf(fp, "%-*.*s", (int)col,
1548                                         (int)col - 1, list[word]);
1549                         fprintf(fp, "\n");
1550                 }
1551         } else {
1552                 cmd = pcmd->argval[0].string;
1553                 words = findcmd(cmd, builtins, opcmds, &xcp);
1554                 if (words == 0) {
1555                         fprintf(stderr,
1556                                 "Command `%s' is unknown\n", cmd);
1557                         return;
1558                 } else if (words >= 2) {
1559                         fprintf(stderr,
1560                                 "Command `%s' is ambiguous\n", cmd);
1561                         return;
1562                 }
1563                 fprintf(fp, "function: %s\n", xcp->comment);
1564                 printusage(xcp, fp);
1565         }
1566 }
1567
1568
1569 /*
1570  * helpsort - do hostname qsort comparisons
1571  */
1572 static int
1573 helpsort(
1574         const void *t1,
1575         const void *t2
1576         )
1577 {
1578         const char * const *    name1 = t1;
1579         const char * const *    name2 = t2;
1580
1581         return strcmp(*name1, *name2);
1582 }
1583
1584
1585 /*
1586  * printusage - print usage information for a command
1587  */
1588 static void
1589 printusage(
1590         struct xcmd *xcp,
1591         FILE *fp
1592         )
1593 {
1594         int i, opt46;
1595
1596         opt46 = 0;
1597         (void) fprintf(fp, "usage: %s", xcp->keyword);
1598         for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
1599                 if (opt46 == 0 && (xcp->arg[i] & ~OPT) == NTP_ADD) {
1600                         (void) fprintf(fp, " [ -4|-6 ]");
1601                         opt46 = 1;
1602                 }
1603                 if (xcp->arg[i] & OPT)
1604                     (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
1605                 else
1606                     (void) fprintf(fp, " %s", xcp->desc[i]);
1607         }
1608         (void) fprintf(fp, "\n");
1609 }
1610
1611
1612 /*
1613  * timeout - set time out time
1614  */
1615 static void
1616 timeout(
1617         struct parse *pcmd,
1618         FILE *fp
1619         )
1620 {
1621         int val;
1622
1623         if (pcmd->nargs == 0) {
1624                 val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
1625                 (void) fprintf(fp, "primary timeout %d ms\n", val);
1626         } else {
1627                 tvout.tv_sec = pcmd->argval[0].uval / 1000;
1628                 tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000))
1629                         * 1000;
1630         }
1631 }
1632
1633
1634 /*
1635  * my_delay - set delay for auth requests
1636  */
1637 static void
1638 my_delay(
1639         struct parse *pcmd,
1640         FILE *fp
1641         )
1642 {
1643         int isneg;
1644         u_long val;
1645
1646         if (pcmd->nargs == 0) {
1647                 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
1648                 (void) fprintf(fp, "delay %lu ms\n", val);
1649         } else {
1650                 if (pcmd->argval[0].ival < 0) {
1651                         isneg = 1;
1652                         val = ~(u_long)(pcmd->argval[0].ival) + 1UL;
1653                 } else {
1654                         isneg = 0;
1655                         val = (u_long)pcmd->argval[0].ival;
1656                 }
1657
1658                 delay_time.l_ui = val / 1000;
1659                 val %= 1000;
1660                 delay_time.l_uf = val * 4294967;        /* 2**32/1000 */
1661
1662                 if (isneg)
1663                     L_NEG(&delay_time);
1664         }
1665 }
1666
1667
1668 /*
1669  * host - set the host we are dealing with.
1670  */
1671 static void
1672 host(
1673         struct parse *pcmd,
1674         FILE *fp
1675         )
1676 {
1677         int i;
1678
1679         if (pcmd->nargs == 0) {
1680                 if (havehost)
1681                     (void) fprintf(fp, "current host is %s\n", currenthost);
1682                 else
1683                     (void) fprintf(fp, "no current host\n");
1684                 return;
1685         }
1686
1687         i = 0;
1688         if (pcmd->nargs == 2) {
1689                 if (!strcmp("-4", pcmd->argval[i].string))
1690                         ai_fam_templ = AF_INET;
1691                 else if (!strcmp("-6", pcmd->argval[i].string))
1692                         ai_fam_templ = AF_INET6;
1693                 else {
1694                         if (havehost)
1695                                 (void) fprintf(fp,
1696                                     "current host remains %s\n", currenthost);
1697                         else
1698                                 (void) fprintf(fp, "still no current host\n");
1699                         return;
1700                 }
1701                 i = 1;
1702         }
1703         if (openhost(pcmd->argval[i].string)) {
1704                 (void) fprintf(fp, "current host set to %s\n", currenthost);
1705         } else {
1706                 if (havehost)
1707                     (void) fprintf(fp,
1708                                    "current host remains %s\n", currenthost);
1709                 else
1710                     (void) fprintf(fp, "still no current host\n");
1711         }
1712 }
1713
1714
1715 /*
1716  * keyid - get a keyid to use for authenticating requests
1717  */
1718 static void
1719 keyid(
1720         struct parse *pcmd,
1721         FILE *fp
1722         )
1723 {
1724         if (pcmd->nargs == 0) {
1725                 if (info_auth_keyid == 0 && !keyid_entered)
1726                     (void) fprintf(fp, "no keyid defined\n");
1727                 else if (info_auth_keyid == 0 && keyid_entered)
1728                     (void) fprintf(fp, "no keyid will be sent\n");
1729                 else
1730                     (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
1731         } else {
1732                 info_auth_keyid = pcmd->argval[0].uval;
1733                 keyid_entered = 1;
1734         }
1735 }
1736
1737
1738 /*
1739  * keytype - get type of key to use for authenticating requests
1740  */
1741 static void
1742 keytype(
1743         struct parse *pcmd,
1744         FILE *fp
1745         )
1746 {
1747         const char *    digest_name;
1748         size_t          digest_len;
1749         int             key_type;
1750
1751         if (!pcmd->nargs) {
1752                 fprintf(fp, "keytype is %s with %lu octet digests\n",
1753                         keytype_name(info_auth_keytype),
1754                         (u_long)info_auth_hashlen);
1755                 return;
1756         }
1757
1758         digest_name = pcmd->argval[0].string;
1759         digest_len = 0;
1760         key_type = keytype_from_text(digest_name, &digest_len);
1761
1762         if (!key_type) {
1763                 fprintf(fp, "keytype must be 'md5'%s\n",
1764 #ifdef OPENSSL
1765                         " or a digest type provided by OpenSSL");
1766 #else
1767                         "");
1768 #endif
1769                 return;
1770         }
1771
1772         info_auth_keytype = key_type;
1773         info_auth_hashlen = digest_len;
1774 }
1775
1776
1777 /*
1778  * passwd - get an authentication key
1779  */
1780 /*ARGSUSED*/
1781 static void
1782 passwd(
1783         struct parse *pcmd,
1784         FILE *fp
1785         )
1786 {
1787         char *pass;
1788
1789         if (info_auth_keyid == 0) {
1790                 info_auth_keyid = getkeyid("Keyid: ");
1791                 if (info_auth_keyid == 0) {
1792                         (void)fprintf(fp, "Keyid must be defined\n");
1793                         return;
1794                 }
1795         }
1796         if (pcmd->nargs >= 1)
1797                 pass = pcmd->argval[0].string;
1798         else {
1799                 pass = getpass_keytype(info_auth_keytype);
1800                 if ('\0' == *pass) {
1801                         fprintf(fp, "Password unchanged\n");
1802                         return;
1803                 }
1804         }
1805         authusekey(info_auth_keyid, info_auth_keytype, (u_char *)pass);
1806         authtrust(info_auth_keyid, 1);
1807 }
1808
1809
1810 /*
1811  * hostnames - set the showhostnames flag
1812  */
1813 static void
1814 hostnames(
1815         struct parse *pcmd,
1816         FILE *fp
1817         )
1818 {
1819         if (pcmd->nargs == 0) {
1820                 if (showhostnames)
1821                     (void) fprintf(fp, "hostnames being shown\n");
1822                 else
1823                     (void) fprintf(fp, "hostnames not being shown\n");
1824         } else {
1825                 if (STREQ(pcmd->argval[0].string, "yes"))
1826                     showhostnames = 1;
1827                 else if (STREQ(pcmd->argval[0].string, "no"))
1828                     showhostnames = 0;
1829                 else
1830                     (void)fprintf(stderr, "What?\n");
1831         }
1832 }
1833
1834
1835 /*
1836  * setdebug - set/change debugging level
1837  */
1838 static void
1839 setdebug(
1840         struct parse *pcmd,
1841         FILE *fp
1842         )
1843 {
1844         if (pcmd->nargs == 0) {
1845                 (void) fprintf(fp, "debug level is %d\n", debug);
1846                 return;
1847         } else if (STREQ(pcmd->argval[0].string, "no")) {
1848                 debug = 0;
1849         } else if (STREQ(pcmd->argval[0].string, "more")) {
1850                 debug++;
1851         } else if (STREQ(pcmd->argval[0].string, "less")) {
1852                 debug--;
1853         } else {
1854                 (void) fprintf(fp, "What?\n");
1855                 return;
1856         }
1857         (void) fprintf(fp, "debug level set to %d\n", debug);
1858 }
1859
1860
1861 /*
1862  * quit - stop this nonsense
1863  */
1864 /*ARGSUSED*/
1865 static void
1866 quit(
1867         struct parse *pcmd,
1868         FILE *fp
1869         )
1870 {
1871         if (havehost)
1872             closesocket(sockfd);
1873         exit(0);
1874 }
1875
1876
1877 /*
1878  * version - print the current version number
1879  */
1880 /*ARGSUSED*/
1881 static void
1882 version(
1883         struct parse *pcmd,
1884         FILE *fp
1885         )
1886 {
1887
1888         (void) fprintf(fp, "%s\n", Version);
1889         return;
1890 }
1891
1892
1893 static void __attribute__((__format__(__printf__, 1, 0)))
1894 vwarning(const char *fmt, va_list ap)
1895 {
1896         int serrno = errno;
1897         (void) fprintf(stderr, "%s: ", progname);
1898         vfprintf(stderr, fmt, ap);
1899         (void) fprintf(stderr, ": %s\n", strerror(serrno));
1900 }
1901
1902 /*
1903  * warning - print a warning message
1904  */
1905 static void __attribute__((__format__(__printf__, 1, 2)))
1906 warning(
1907         const char *fmt,
1908         ...
1909         )
1910 {
1911         va_list ap;
1912         va_start(ap, fmt);
1913         vwarning(fmt, ap);
1914         va_end(ap);
1915 }
1916
1917
1918 /*
1919  * error - print a message and exit
1920  */
1921 static void __attribute__((__format__(__printf__, 1, 2)))
1922 error(
1923         const char *fmt,
1924         ...
1925         )
1926 {
1927         va_list ap;
1928         va_start(ap, fmt);
1929         vwarning(fmt, ap);
1930         va_end(ap);
1931         exit(1);
1932 }
1933
1934 /*
1935  * getkeyid - prompt the user for a keyid to use
1936  */
1937 static u_long
1938 getkeyid(
1939         const char *keyprompt
1940         )
1941 {
1942         int c;
1943         FILE *fi;
1944         char pbuf[20];
1945         size_t i;
1946         size_t ilim;
1947
1948 #ifndef SYS_WINNT
1949         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
1950 #else
1951         if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
1952 #endif /* SYS_WINNT */
1953                 fi = stdin;
1954         else
1955                 setbuf(fi, (char *)NULL);
1956         fprintf(stderr, "%s", keyprompt); fflush(stderr);
1957         for (i = 0, ilim = COUNTOF(pbuf) - 1;
1958              i < ilim && (c = getc(fi)) != '\n' && c != EOF;
1959              )
1960                 pbuf[i++] = (char)c;
1961         pbuf[i] = '\0';
1962         if (fi != stdin)
1963                 fclose(fi);
1964
1965         return (u_long) atoi(pbuf);
1966 }