]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/ntpq/ntpq.c
Fix multiple vulnerabilities of ntp.
[FreeBSD/releng/10.2.git] / contrib / ntp / ntpq / ntpq.c
1 /*
2  * ntpq - query an NTP server using mode 6 commands
3  */
4 #include <config.h>
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <signal.h>
8 #include <setjmp.h>
9 #include <sys/types.h>
10 #include <sys/time.h>
11 #ifdef HAVE_UNISTD_H
12 # include <unistd.h>
13 #endif
14 #ifdef HAVE_FCNTL_H
15 # include <fcntl.h>
16 #endif
17 #ifdef SYS_WINNT
18 # include <mswsock.h>
19 #endif
20 #include <isc/net.h>
21 #include <isc/result.h>
22
23 #include "ntpq.h"
24 #include "ntp_assert.h"
25 #include "ntp_stdlib.h"
26 #include "ntp_unixtime.h"
27 #include "ntp_calendar.h"
28 #include "ntp_select.h"
29 #include "ntp_assert.h"
30 #include "lib_strbuf.h"
31 #include "ntp_lineedit.h"
32 #include "ntp_debug.h"
33 #ifdef OPENSSL
34 #include "openssl/evp.h"
35 #include "openssl/objects.h"
36 #include "openssl/err.h"
37 #include "libssl_compat.h"
38 #endif
39 #include <ssl_applink.c>
40
41 #include "ntp_libopts.h"
42 #include "safecast.h"
43
44 #ifdef SYS_VXWORKS              /* vxWorks needs mode flag -casey*/
45 # define open(name, flags)   open(name, flags, 0777)
46 # define SERVER_PORT_NUM     123
47 #endif
48
49 /* we use COMMAND as an autogen keyword */
50 #ifdef COMMAND
51 # undef COMMAND
52 #endif
53
54 /*
55  * Because we potentially understand a lot of commands we will run
56  * interactive if connected to a terminal.
57  */
58 int interactive = 0;            /* set to 1 when we should prompt */
59 const char *prompt = "ntpq> ";  /* prompt to ask him about */
60
61 /*
62  * use old readvars behavior?  --old-rv processing in ntpq resets
63  * this value based on the presence or absence of --old-rv.  It is
64  * initialized to 1 here to maintain backward compatibility with
65  * libntpq clients such as ntpsnmpd, which are free to reset it as
66  * desired.
67  */
68 int     old_rv = 1;
69
70 /*
71  * How should we display the refid?
72  * REFID_HASH, REFID_IPV4
73  */
74 te_Refid drefid = -1;
75
76 /*
77  * for get_systime()
78  */
79 s_char  sys_precision;          /* local clock precision (log2 s) */
80
81 /*
82  * Keyid used for authenticated requests.  Obtained on the fly.
83  */
84 u_long info_auth_keyid = 0;
85
86 static  int     info_auth_keytype = NID_md5;    /* MD5 */
87 static  size_t  info_auth_hashlen = 16;         /* MD5 */
88 u_long  current_time;           /* needed by authkeys; not used */
89
90 /*
91  * Flag which indicates we should always send authenticated requests
92  */
93 int always_auth = 0;
94
95 /*
96  * Flag which indicates raw mode output.
97  */
98 int rawmode = 0;
99
100 /*
101  * Packet version number we use
102  */
103 u_char pktversion = NTP_OLDVERSION + 1;
104
105 /*
106  * Don't jump if no set jmp.
107  */
108 volatile int jump = 0;
109
110 /*
111  * Format values
112  */
113 #define PADDING 0
114 #define HA      1       /* host address */
115 #define NA      2       /* network address */
116 #define LP      3       /* leap (print in binary) */
117 #define RF      4       /* refid (sometimes string, sometimes not) */
118 #define AR      5       /* array of times */
119 #define FX      6       /* test flags */
120 #define TS      7       /* l_fp timestamp in hex */
121 #define OC      8       /* integer, print in octal */
122 #define EOV     255     /* end of table */
123
124 /*
125  * For the most part ntpq simply displays what ntpd provides in the
126  * mostly plain-text mode 6 responses.  A few variable names are by
127  * default "cooked" to provide more human-friendly output.
128  */
129 const var_format cookedvars[] = {
130         { "leap",               LP },
131         { "reach",              OC },
132         { "refid",              RF },
133         { "reftime",            TS },
134         { "clock",              TS },
135         { "org",                TS },
136         { "rec",                TS },
137         { "xmt",                TS },
138         { "flash",              FX },
139         { "srcadr",             HA },
140         { "peeradr",            HA },   /* compat with others */
141         { "dstadr",             NA },
142         { "filtdelay",          AR },
143         { "filtoffset",         AR },
144         { "filtdisp",           AR },
145         { "filterror",          AR },   /* compat with others */
146 };
147
148
149
150 /*
151  * flasher bits
152  */
153 static const char *tstflagnames[] = {
154         "pkt_dup",              /* TEST1 */
155         "pkt_bogus",            /* TEST2 */
156         "pkt_unsync",           /* TEST3 */
157         "pkt_denied",           /* TEST4 */
158         "pkt_auth",             /* TEST5 */
159         "pkt_stratum",          /* TEST6 */
160         "pkt_header",           /* TEST7 */
161         "pkt_autokey",          /* TEST8 */
162         "pkt_crypto",           /* TEST9 */
163         "peer_stratum",         /* TEST10 */
164         "peer_dist",            /* TEST11 */
165         "peer_loop",            /* TEST12 */
166         "peer_unreach"          /* TEST13 */
167 };
168
169
170 int             ntpqmain        (int,   char **);
171 /*
172  * Built in command handler declarations
173  */
174 static  int     openhost        (const char *, int);
175 static  void    dump_hex_printable(const void *, size_t);
176 static  int     sendpkt         (void *, size_t);
177 static  int     getresponse     (int, int, u_short *, size_t *, const char **, int);
178 static  int     sendrequest     (int, associd_t, int, size_t, const char *);
179 static  char *  tstflags        (u_long);
180 #ifndef BUILD_AS_LIB
181 static  void    getcmds         (void);
182 #ifndef SYS_WINNT
183 static  int     abortcmd        (void);
184 #endif  /* SYS_WINNT */
185 static  void    docmd           (const char *);
186 static  void    tokenize        (const char *, char **, int *);
187 static  int     getarg          (const char *, int, arg_v *);
188 #endif  /* BUILD_AS_LIB */
189 static  int     findcmd         (const char *, struct xcmd *,
190                                  struct xcmd *, struct xcmd **);
191 static  int     rtdatetolfp     (char *, l_fp *);
192 static  int     decodearr       (char *, int *, l_fp *);
193 static  void    help            (struct parse *, FILE *);
194 static  int     helpsort        (const void *, const void *);
195 static  void    printusage      (struct xcmd *, FILE *);
196 static  void    timeout         (struct parse *, FILE *);
197 static  void    auth_delay      (struct parse *, FILE *);
198 static  void    host            (struct parse *, FILE *);
199 static  void    ntp_poll        (struct parse *, FILE *);
200 static  void    keyid           (struct parse *, FILE *);
201 static  void    keytype         (struct parse *, FILE *);
202 static  void    passwd          (struct parse *, FILE *);
203 static  void    hostnames       (struct parse *, FILE *);
204 static  void    setdebug        (struct parse *, FILE *);
205 static  void    quit            (struct parse *, FILE *);
206 static  void    showdrefid      (struct parse *, FILE *);
207 static  void    version         (struct parse *, FILE *);
208 static  void    raw             (struct parse *, FILE *);
209 static  void    cooked          (struct parse *, FILE *);
210 static  void    authenticate    (struct parse *, FILE *);
211 static  void    ntpversion      (struct parse *, FILE *);
212 static  void    warning         (const char *, ...)
213     __attribute__((__format__(__printf__, 1, 2)));
214 static  void    error           (const char *, ...)
215     __attribute__((__format__(__printf__, 1, 2)));
216 static  u_long  getkeyid        (const char *);
217 static  void    atoascii        (const char *, size_t, char *, size_t);
218 static  void    cookedprint     (int, size_t, const char *, int, int, FILE *);
219 static  void    rawprint        (int, size_t, const char *, int, int, FILE *);
220 static  void    startoutput     (void);
221 static  void    output          (FILE *, const char *, const char *);
222 static  void    endoutput       (FILE *);
223 static  void    outputarr       (FILE *, char *, int, l_fp *);
224 static  int     assoccmp        (const void *, const void *);
225 static  void    on_ctrlc        (void);
226         u_short varfmt          (const char *);
227 static  int     my_easprintf    (char**, const char *, ...) NTP_PRINTF(2, 3);
228 void    ntpq_custom_opt_handler (tOptions *, tOptDesc *);
229
230 #ifdef OPENSSL
231 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
232 static void list_md_fn(const EVP_MD *m, const char *from,
233                        const char *to, void *arg );
234 # endif
235 #endif
236 static char *list_digest_names(void);
237
238 /*
239  * Built-in commands we understand
240  */
241 struct xcmd builtins[] = {
242         { "?",          help,           {  OPT|NTP_STR, NO, NO, NO },
243           { "command", "", "", "" },
244           "tell the use and syntax of commands" },
245         { "help",       help,           {  OPT|NTP_STR, NO, NO, NO },
246           { "command", "", "", "" },
247           "tell the use and syntax of commands" },
248         { "timeout",    timeout,        { OPT|NTP_UINT, NO, NO, NO },
249           { "msec", "", "", "" },
250           "set the primary receive time out" },
251         { "delay",      auth_delay,     { OPT|NTP_INT, NO, NO, NO },
252           { "msec", "", "", "" },
253           "set the delay added to encryption time stamps" },
254         { "host",       host,           { OPT|NTP_STR, OPT|NTP_STR, NO, NO },
255           { "-4|-6", "hostname", "", "" },
256           "specify the host whose NTP server we talk to" },
257         { "poll",       ntp_poll,       { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
258           { "n", "verbose", "", "" },
259           "poll an NTP server in client mode `n' times" },
260         { "passwd",     passwd,         { OPT|NTP_STR, NO, NO, NO },
261           { "", "", "", "" },
262           "specify a password to use for authenticated requests"},
263         { "hostnames",  hostnames,      { OPT|NTP_STR, NO, NO, NO },
264           { "yes|no", "", "", "" },
265           "specify whether hostnames or net numbers are printed"},
266         { "debug",      setdebug,       { OPT|NTP_STR, NO, NO, NO },
267           { "no|more|less", "", "", "" },
268           "set/change debugging level" },
269         { "quit",       quit,           { NO, NO, NO, NO },
270           { "", "", "", "" },
271           "exit ntpq" },
272         { "exit",       quit,           { NO, NO, NO, NO },
273           { "", "", "", "" },
274           "exit ntpq" },
275         { "keyid",      keyid,          { OPT|NTP_UINT, NO, NO, NO },
276           { "key#", "", "", "" },
277           "set keyid to use for authenticated requests" },
278         { "drefid",     showdrefid,     { OPT|NTP_STR, NO, NO, NO },
279           { "hash|ipv4", "", "", "" },
280           "display refid's as IPv4 or hash" },
281         { "version",    version,        { NO, NO, NO, NO },
282           { "", "", "", "" },
283           "print version number" },
284         { "raw",        raw,            { NO, NO, NO, NO },
285           { "", "", "", "" },
286           "do raw mode variable output" },
287         { "cooked",     cooked,         { NO, NO, NO, NO },
288           { "", "", "", "" },
289           "do cooked mode variable output" },
290         { "authenticate", authenticate, { OPT|NTP_STR, NO, NO, NO },
291           { "yes|no", "", "", "" },
292           "always authenticate requests to this server" },
293         { "ntpversion", ntpversion,     { OPT|NTP_UINT, NO, NO, NO },
294           { "version number", "", "", "" },
295           "set the NTP version number to use for requests" },
296         { "keytype",    keytype,        { OPT|NTP_STR, NO, NO, NO },
297           { "key type %s", "", "", "" },
298           NULL },
299         { 0,            0,              { NO, NO, NO, NO },
300           { "", "", "", "" }, "" }
301 };
302
303
304 /*
305  * Default values we use.
306  */
307 #define DEFHOST         "localhost"     /* default host name */
308 #define DEFTIMEOUT      5               /* wait 5 seconds for 1st pkt */
309 #define DEFSTIMEOUT     3               /* and 3 more for each additional */
310 /*
311  * Requests are automatically retried once, so total timeout with no
312  * response is a bit over 2 * DEFTIMEOUT, or 10 seconds.  At the other
313  * extreme, a request eliciting 32 packets of responses each for some
314  * reason nearly DEFSTIMEOUT seconds after the prior in that series,
315  * with a single packet dropped, would take around 32 * DEFSTIMEOUT, or
316  * 93 seconds to fail each of two times, or 186 seconds.
317  * Some commands involve a series of requests, such as "peers" and
318  * "mrulist", so the cumulative timeouts are even longer for those.
319  */
320 #define DEFDELAY        0x51EB852       /* 20 milliseconds, l_fp fraction */
321 #define LENHOSTNAME     256             /* host name is 256 characters long */
322 #define MAXCMDS         100             /* maximum commands on cmd line */
323 #define MAXHOSTS        200             /* maximum hosts on cmd line */
324 #define MAXLINE         512             /* maximum line length */
325 #define MAXTOKENS       (1+MAXARGS+2)   /* maximum number of usable tokens */
326 #define MAXVARLEN       256             /* maximum length of a variable name */
327 #define MAXVALLEN       2048            /* maximum length of a variable value */
328 #define MAXOUTLINE      72              /* maximum length of an output line */
329 #define SCREENWIDTH     76              /* nominal screen width in columns */
330
331 /*
332  * Some variables used and manipulated locally
333  */
334 struct sock_timeval tvout = { DEFTIMEOUT, 0 };  /* time out for reads */
335 struct sock_timeval tvsout = { DEFSTIMEOUT, 0 };/* secondary time out */
336 l_fp delay_time;                                /* delay time */
337 char currenthost[LENHOSTNAME];                  /* current host name */
338 int currenthostisnum;                           /* is prior text from IP? */
339 struct sockaddr_in hostaddr;                    /* host address */
340 int showhostnames = 1;                          /* show host names by default */
341 int wideremote = 0;                             /* show wide remote names? */
342
343 int ai_fam_templ;                               /* address family */
344 int ai_fam_default;                             /* default address family */
345 SOCKET sockfd;                                  /* fd socket is opened on */
346 int havehost = 0;                               /* set to 1 when host open */
347 int s_port = 0;
348 struct servent *server_entry = NULL;            /* server entry for ntp */
349
350
351 /*
352  * Sequence number used for requests.  It is incremented before
353  * it is used.
354  */
355 u_short sequence;
356
357 /*
358  * Holds data returned from queries.  Declare buffer long to be sure of
359  * alignment.
360  */
361 #define DATASIZE        (MAXFRAGS*480)  /* maximum amount of data */
362 long pktdata[DATASIZE/sizeof(long)];
363
364 /*
365  * assoc_cache[] is a dynamic array which allows references to
366  * associations using &1 ... &N for n associations, avoiding manual
367  * lookup of the current association IDs for a given ntpd.  It also
368  * caches the status word for each association, retrieved incidentally.
369  */
370 struct association *    assoc_cache;
371 u_int assoc_cache_slots;/* count of allocated array entries */
372 u_int numassoc;         /* number of cached associations */
373
374 /*
375  * For commands typed on the command line (with the -c option)
376  */
377 int numcmds = 0;
378 const char *ccmds[MAXCMDS];
379 #define ADDCMD(cp)      if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp)
380
381 /*
382  * When multiple hosts are specified.
383  */
384
385 u_int numhosts;
386
387 chost chosts[MAXHOSTS];
388 #define ADDHOST(cp)                                             \
389         do {                                                    \
390                 if (numhosts < MAXHOSTS) {                      \
391                         chosts[numhosts].name = (cp);           \
392                         chosts[numhosts].fam = ai_fam_templ;    \
393                         numhosts++;                             \
394                 }                                               \
395         } while (0)
396
397 /*
398  * Macro definitions we use
399  */
400 #define ISSPACE(c)      ((c) == ' ' || (c) == '\t')
401 #define ISEOL(c)        ((c) == '\n' || (c) == '\r' || (c) == '\0')
402 #define STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
403
404 /*
405  * Jump buffer for longjumping back to the command level
406  */
407 jmp_buf interrupt_buf;
408
409 /*
410  * Points at file being currently printed into
411  */
412 FILE *current_output;
413
414 /*
415  * Command table imported from ntpdc_ops.c
416  */
417 extern struct xcmd opcmds[];
418
419 char const *progname;
420
421 #ifdef NO_MAIN_ALLOWED
422 #ifndef BUILD_AS_LIB
423 CALL(ntpq,"ntpq",ntpqmain);
424
425 void clear_globals(void)
426 {
427         extern int ntp_optind;
428         showhostnames = 0;      /* don'tshow host names by default */
429         ntp_optind = 0;
430         server_entry = NULL;    /* server entry for ntp */
431         havehost = 0;           /* set to 1 when host open */
432         numassoc = 0;           /* number of cached associations */
433         numcmds = 0;
434         numhosts = 0;
435 }
436 #endif /* !BUILD_AS_LIB */
437 #endif /* NO_MAIN_ALLOWED */
438
439 /*
440  * main - parse arguments and handle options
441  */
442 #ifndef NO_MAIN_ALLOWED
443 int
444 main(
445         int argc,
446         char *argv[]
447         )
448 {
449         return ntpqmain(argc, argv);
450 }
451 #endif
452
453 #ifndef BUILD_AS_LIB
454 int
455 ntpqmain(
456         int argc,
457         char *argv[]
458         )
459 {
460         u_int ihost;
461         int icmd;
462
463
464 #ifdef SYS_VXWORKS
465         clear_globals();
466         taskPrioritySet(taskIdSelf(), 100 );
467 #endif
468
469         delay_time.l_ui = 0;
470         delay_time.l_uf = DEFDELAY;
471
472         init_lib();     /* sets up ipv4_works, ipv6_works */
473         ssl_applink();
474         init_auth();
475
476         /* Check to see if we have IPv6. Otherwise default to IPv4 */
477         if (!ipv6_works)
478                 ai_fam_default = AF_INET;
479
480         /* Fixup keytype's help based on available digest names */
481
482         {
483             char *list;
484             char *msg;
485
486             list = list_digest_names();
487             for (icmd = 0; icmd < sizeof(builtins)/sizeof(builtins[0]); icmd++) {
488                 if (strcmp("keytype", builtins[icmd].keyword) == 0)
489                     break;
490             }
491
492             /* CID: 1295478 */
493             /* This should only "trip" if "keytype" is removed from builtins */
494             INSIST(icmd < sizeof(builtins)/sizeof(builtins[0]));
495
496 #ifdef OPENSSL
497             builtins[icmd].desc[0] = "digest-name";
498             my_easprintf(&msg,
499                          "set key type to use for authenticated requests, one of:%s",
500                          list);
501 #else
502             builtins[icmd].desc[0] = "md5";
503             my_easprintf(&msg,
504                          "set key type to use for authenticated requests (%s)",
505                          list);
506 #endif
507             builtins[icmd].comment = msg;
508             free(list);
509         }
510
511         progname = argv[0];
512
513         {
514                 int optct = ntpOptionProcess(&ntpqOptions, argc, argv);
515                 argc -= optct;
516                 argv += optct;
517         }
518
519         /*
520          * Process options other than -c and -p, which are specially
521          * handled by ntpq_custom_opt_handler().
522          */
523
524         debug = OPT_VALUE_SET_DEBUG_LEVEL;
525
526         if (HAVE_OPT(IPV4))
527                 ai_fam_templ = AF_INET;
528         else if (HAVE_OPT(IPV6))
529                 ai_fam_templ = AF_INET6;
530         else
531                 ai_fam_templ = ai_fam_default;
532
533         if (HAVE_OPT(INTERACTIVE))
534                 interactive = 1;
535
536         if (HAVE_OPT(NUMERIC))
537                 showhostnames = 0;
538
539         if (HAVE_OPT(WIDE))
540                 wideremote = 1;
541
542         old_rv = HAVE_OPT(OLD_RV);
543
544         drefid = OPT_VALUE_REFID;
545
546         if (0 == argc) {
547                 ADDHOST(DEFHOST);
548         } else {
549                 for (ihost = 0; ihost < (u_int)argc; ihost++) {
550                         if ('-' == *argv[ihost]) {
551                                 //
552                                 // If I really cared I'd also check:
553                                 // 0 == argv[ihost][2]
554                                 //
555                                 // and there are other cases as well...
556                                 //
557                                 if ('4' == argv[ihost][1]) {
558                                         ai_fam_templ = AF_INET;
559                                         continue;
560                                 } else if ('6' == argv[ihost][1]) {
561                                         ai_fam_templ = AF_INET6;
562                                         continue;
563                                 } else {
564                                         // XXX Throw a usage error
565                                 }
566                         }
567                         ADDHOST(argv[ihost]);
568                 }
569         }
570
571         if (numcmds == 0 && interactive == 0
572             && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
573                 interactive = 1;
574         }
575
576         set_ctrl_c_hook(on_ctrlc);
577 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
578         if (interactive)
579                 push_ctrl_c_handler(abortcmd);
580 #endif /* SYS_WINNT */
581
582         if (numcmds == 0) {
583                 (void) openhost(chosts[0].name, chosts[0].fam);
584                 getcmds();
585         } else {
586                 for (ihost = 0; ihost < numhosts; ihost++) {
587                         if (openhost(chosts[ihost].name, chosts[ihost].fam))
588                                 for (icmd = 0; icmd < numcmds; icmd++)
589                                         docmd(ccmds[icmd]);
590                 }
591         }
592 #ifdef SYS_WINNT
593         WSACleanup();
594 #endif /* SYS_WINNT */
595         return 0;
596 }
597 #endif /* !BUILD_AS_LIB */
598
599 /*
600  * openhost - open a socket to a host
601  */
602 static  int
603 openhost(
604         const char *hname,
605         int         fam
606         )
607 {
608         const char svc[] = "ntp";
609         char temphost[LENHOSTNAME];
610         int a_info, i;
611         struct addrinfo hints, *ai;
612         sockaddr_u addr;
613         size_t octets;
614         register const char *cp;
615         char name[LENHOSTNAME];
616
617         /*
618          * We need to get by the [] if they were entered
619          */
620
621         cp = hname;
622
623         if (*cp == '[') {
624                 cp++;
625                 for (i = 0; *cp && *cp != ']'; cp++, i++)
626                         name[i] = *cp;
627                 if (*cp == ']') {
628                         name[i] = '\0';
629                         hname = name;
630                 } else {
631                         return 0;
632                 }
633         }
634
635         /*
636          * First try to resolve it as an ip address and if that fails,
637          * do a fullblown (dns) lookup. That way we only use the dns
638          * when it is needed and work around some implementations that
639          * will return an "IPv4-mapped IPv6 address" address if you
640          * give it an IPv4 address to lookup.
641          */
642         ZERO(hints);
643         hints.ai_family = fam;
644         hints.ai_protocol = IPPROTO_UDP;
645         hints.ai_socktype = SOCK_DGRAM;
646         hints.ai_flags = Z_AI_NUMERICHOST;
647         ai = NULL;
648
649         a_info = getaddrinfo(hname, svc, &hints, &ai);
650         if (a_info == EAI_NONAME
651 #ifdef EAI_NODATA
652             || a_info == EAI_NODATA
653 #endif
654            ) {
655                 hints.ai_flags = AI_CANONNAME;
656 #ifdef AI_ADDRCONFIG
657                 hints.ai_flags |= AI_ADDRCONFIG;
658 #endif
659                 a_info = getaddrinfo(hname, svc, &hints, &ai);
660         }
661 #ifdef AI_ADDRCONFIG
662         /* Some older implementations don't like AI_ADDRCONFIG. */
663         if (a_info == EAI_BADFLAGS) {
664                 hints.ai_flags &= ~AI_ADDRCONFIG;
665                 a_info = getaddrinfo(hname, svc, &hints, &ai);
666         }
667 #endif
668         if (a_info != 0) {
669                 fprintf(stderr, "%s\n", gai_strerror(a_info));
670                 return 0;
671         }
672
673         INSIST(ai != NULL);
674         ZERO(addr);
675         octets = min(sizeof(addr), ai->ai_addrlen);
676         memcpy(&addr, ai->ai_addr, octets);
677
678         if (ai->ai_canonname == NULL) {
679                 strlcpy(temphost, stoa(&addr), sizeof(temphost));
680                 currenthostisnum = TRUE;
681         } else {
682                 strlcpy(temphost, ai->ai_canonname, sizeof(temphost));
683                 currenthostisnum = FALSE;
684         }
685
686         if (debug > 2)
687                 printf("Opening host %s (%s)\n",
688                         temphost,
689                         (ai->ai_family == AF_INET)
690                         ? "AF_INET"
691                         : (ai->ai_family == AF_INET6)
692                           ? "AF_INET6"
693                           : "AF-???"
694                         );
695
696         if (havehost == 1) {
697                 if (debug > 2)
698                         printf("Closing old host %s\n", currenthost);
699                 closesocket(sockfd);
700                 havehost = 0;
701         }
702         strlcpy(currenthost, temphost, sizeof(currenthost));
703
704         /* port maps to the same location in both families */
705         s_port = NSRCPORT(&addr);
706 #ifdef SYS_VXWORKS
707         ((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
708         if (ai->ai_family == AF_INET)
709                 *(struct sockaddr_in *)&hostaddr=
710                         *((struct sockaddr_in *)ai->ai_addr);
711         else
712                 *(struct sockaddr_in6 *)&hostaddr=
713                         *((struct sockaddr_in6 *)ai->ai_addr);
714 #endif /* SYS_VXWORKS */
715
716 #ifdef SYS_WINNT
717         {
718                 int optionValue = SO_SYNCHRONOUS_NONALERT;
719                 int err;
720
721                 err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
722                                  (char *)&optionValue, sizeof(optionValue));
723                 if (err) {
724                         mfprintf(stderr,
725                                  "setsockopt(SO_SYNCHRONOUS_NONALERT)"
726                                  " error: %m\n");
727                         freeaddrinfo(ai);
728                         exit(1);
729                 }
730         }
731 #endif /* SYS_WINNT */
732
733         sockfd = socket(ai->ai_family, ai->ai_socktype,
734                         ai->ai_protocol);
735         if (sockfd == INVALID_SOCKET) {
736                 error("socket");
737                 freeaddrinfo(ai);
738                 return 0;
739         }
740
741
742 #ifdef NEED_RCVBUF_SLOP
743 # ifdef SO_RCVBUF
744         { int rbufsize = DATASIZE + 2048;       /* 2K for slop */
745         if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
746                        &rbufsize, sizeof(int)) == -1)
747                 error("setsockopt");
748         }
749 # endif
750 #endif
751
752         if
753 #ifdef SYS_VXWORKS
754            (connect(sockfd, (struct sockaddr *)&hostaddr,
755                     sizeof(hostaddr)) == -1)
756 #else
757            (connect(sockfd, (struct sockaddr *)ai->ai_addr,
758                 ai->ai_addrlen) == -1)
759 #endif /* SYS_VXWORKS */
760         {
761                 error("connect");
762                 freeaddrinfo(ai);
763                 return 0;
764         }
765         freeaddrinfo(ai);
766         havehost = 1;
767         numassoc = 0;
768
769         return 1;
770 }
771
772
773 static void
774 dump_hex_printable(
775         const void *    data,
776         size_t          len
777         )
778 {
779         const char *    cdata;
780         const char *    rowstart;
781         size_t          idx;
782         size_t          rowlen;
783         u_char          uch;
784
785         cdata = data;
786         while (len > 0) {
787                 rowstart = cdata;
788                 rowlen = min(16, len);
789                 for (idx = 0; idx < rowlen; idx++) {
790                         uch = *(cdata++);
791                         printf("%02x ", uch);
792                 }
793                 for ( ; idx < 16 ; idx++)
794                         printf("   ");
795                 cdata = rowstart;
796                 for (idx = 0; idx < rowlen; idx++) {
797                         uch = *(cdata++);
798                         printf("%c", (isprint(uch))
799                                          ? uch
800                                          : '.');
801                 }
802                 printf("\n");
803                 len -= rowlen;
804         }
805 }
806
807
808 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
809 /*
810  * sendpkt - send a packet to the remote host
811  */
812 static int
813 sendpkt(
814         void *  xdata,
815         size_t  xdatalen
816         )
817 {
818         if (debug >= 3)
819                 printf("Sending %zu octets\n", xdatalen);
820
821         if (send(sockfd, xdata, xdatalen, 0) == -1) {
822                 warning("write to %s failed", currenthost);
823                 return -1;
824         }
825
826         if (debug >= 4) {
827                 printf("Request packet:\n");
828                 dump_hex_printable(xdata, xdatalen);
829         }
830         return 0;
831 }
832
833 /*
834  * getresponse - get a (series of) response packet(s) and return the data
835  */
836 static int
837 getresponse(
838         int opcode,
839         int associd,
840         u_short *rstatus,
841         size_t *rsize,
842         const char **rdata,
843         int timeo
844         )
845 {
846         struct ntp_control rpkt;
847         struct sock_timeval tvo;
848         u_short offsets[MAXFRAGS+1];
849         u_short counts[MAXFRAGS+1];
850         u_short offset;
851         u_short count;
852         size_t numfrags;
853         size_t f;
854         size_t ff;
855         int seenlastfrag;
856         int shouldbesize;
857         fd_set fds;
858         int n;
859         int errcode;
860         /* absolute timeout checks. Not 'time_t' by intention! */
861         uint32_t tobase;        /* base value for timeout */
862         uint32_t tospan;        /* timeout span (max delay) */
863         uint32_t todiff;        /* current delay */
864
865         /*
866          * This is pretty tricky.  We may get between 1 and MAXFRAG packets
867          * back in response to the request.  We peel the data out of
868          * each packet and collect it in one long block.  When the last
869          * packet in the sequence is received we'll know how much data we
870          * should have had.  Note we use one long time out, should reconsider.
871          */
872         *rsize = 0;
873         if (rstatus)
874                 *rstatus = 0;
875         *rdata = (char *)pktdata;
876
877         numfrags = 0;
878         seenlastfrag = 0;
879
880         tobase = (uint32_t)time(NULL);
881         
882         FD_ZERO(&fds);
883
884         /*
885          * Loop until we have an error or a complete response.  Nearly all
886          * code paths to loop again use continue.
887          */
888         for (;;) {
889
890                 if (numfrags == 0)
891                         tvo = tvout;
892                 else
893                         tvo = tvsout;
894                 tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
895
896                 FD_SET(sockfd, &fds);
897                 n = select(sockfd+1, &fds, NULL, NULL, &tvo);
898                 if (n == -1) {
899 #if !defined(SYS_WINNT) && defined(EINTR)
900                         /* Windows does not know about EINTR (until very
901                          * recently) and the handling of console events
902                          * is *very* different from POSIX/UNIX signal
903                          * handling anyway.
904                          *
905                          * Under non-windows targets we map EINTR as
906                          * 'last packet was received' and try to exit
907                          * the receive sequence.
908                          */
909                         if (errno == EINTR) {
910                                 seenlastfrag = 1;
911                                 goto maybe_final;
912                         }
913 #endif
914                         warning("select fails");
915                         return -1;
916                 }
917
918                 /*
919                  * Check if this is already too late. Trash the data and
920                  * fake a timeout if this is so.
921                  */
922                 todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
923                 if ((n > 0) && (todiff > tospan)) {
924                         n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
925                         n = 0; /* faked timeout return from 'select()'*/
926                 }
927                 
928                 if (n == 0) {
929                         /*
930                          * Timed out.  Return what we have
931                          */
932                         if (numfrags == 0) {
933                                 if (timeo)
934                                         fprintf(stderr,
935                                                 "%s: timed out, nothing received\n",
936                                                 currenthost);
937                                 return ERR_TIMEOUT;
938                         }
939                         if (timeo)
940                                 fprintf(stderr,
941                                         "%s: timed out with incomplete data\n",
942                                         currenthost);
943                         if (debug) {
944                                 fprintf(stderr,
945                                         "ERR_INCOMPLETE: Received fragments:\n");
946                                 for (f = 0; f < numfrags; f++)
947                                         fprintf(stderr,
948                                                 "%2u: %5d %5d\t%3d octets\n",
949                                                 (u_int)f, offsets[f],
950                                                 offsets[f] +
951                                                 counts[f],
952                                                 counts[f]);
953                                 fprintf(stderr,
954                                         "last fragment %sreceived\n",
955                                         (seenlastfrag)
956                                             ? ""
957                                             : "not ");
958                         }
959                         return ERR_INCOMPLETE;
960                 }
961
962                 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
963                 if (n == -1) {
964                         warning("read");
965                         return -1;
966                 }
967
968                 if (debug >= 4) {
969                         printf("Response packet:\n");
970                         dump_hex_printable(&rpkt, n);
971                 }
972
973                 /*
974                  * Check for format errors.  Bug proofing.
975                  */
976                 if (n < (int)CTL_HEADER_LEN) {
977                         if (debug)
978                                 printf("Short (%d byte) packet received\n", n);
979                         continue;
980                 }
981                 if (PKT_VERSION(rpkt.li_vn_mode) > NTP_VERSION
982                     || PKT_VERSION(rpkt.li_vn_mode) < NTP_OLDVERSION) {
983                         if (debug)
984                                 printf("Packet received with version %d\n",
985                                        PKT_VERSION(rpkt.li_vn_mode));
986                         continue;
987                 }
988                 if (PKT_MODE(rpkt.li_vn_mode) != MODE_CONTROL) {
989                         if (debug)
990                                 printf("Packet received with mode %d\n",
991                                        PKT_MODE(rpkt.li_vn_mode));
992                         continue;
993                 }
994                 if (!CTL_ISRESPONSE(rpkt.r_m_e_op)) {
995                         if (debug)
996                                 printf("Received request packet, wanted response\n");
997                         continue;
998                 }
999
1000                 /*
1001                  * Check opcode and sequence number for a match.
1002                  * Could be old data getting to us.
1003                  */
1004                 if (ntohs(rpkt.sequence) != sequence) {
1005                         if (debug)
1006                                 printf("Received sequnce number %d, wanted %d\n",
1007                                        ntohs(rpkt.sequence), sequence);
1008                         continue;
1009                 }
1010                 if (CTL_OP(rpkt.r_m_e_op) != opcode) {
1011                         if (debug)
1012                             printf(
1013                                     "Received opcode %d, wanted %d (sequence number okay)\n",
1014                                     CTL_OP(rpkt.r_m_e_op), opcode);
1015                         continue;
1016                 }
1017
1018                 /*
1019                  * Check the error code.  If non-zero, return it.
1020                  */
1021                 if (CTL_ISERROR(rpkt.r_m_e_op)) {
1022                         errcode = (ntohs(rpkt.status) >> 8) & 0xff;
1023                         if (CTL_ISMORE(rpkt.r_m_e_op))
1024                                 TRACE(1, ("Error code %d received on not-final packet\n",
1025                                           errcode));
1026                         if (errcode == CERR_UNSPEC)
1027                                 return ERR_UNSPEC;
1028                         return errcode;
1029                 }
1030
1031                 /*
1032                  * Check the association ID to make sure it matches what
1033                  * we sent.
1034                  */
1035                 if (ntohs(rpkt.associd) != associd) {
1036                         TRACE(1, ("Association ID %d doesn't match expected %d\n",
1037                                   ntohs(rpkt.associd), associd));
1038                         /*
1039                          * Hack for silly fuzzballs which, at the time of writing,
1040                          * return an assID of sys.peer when queried for system variables.
1041                          */
1042 #ifdef notdef
1043                         continue;
1044 #endif
1045                 }
1046
1047                 /*
1048                  * Collect offset and count.  Make sure they make sense.
1049                  */
1050                 offset = ntohs(rpkt.offset);
1051                 count = ntohs(rpkt.count);
1052
1053                 /*
1054                  * validate received payload size is padded to next 32-bit
1055                  * boundary and no smaller than claimed by rpkt.count
1056                  */
1057                 if (n & 0x3) {
1058                         TRACE(1, ("Response packet not padded, size = %d\n",
1059                                   n));
1060                         continue;
1061                 }
1062
1063                 shouldbesize = (CTL_HEADER_LEN + count + 3) & ~3;
1064
1065                 if (n < shouldbesize) {
1066                         printf("Response packet claims %u octets payload, above %ld received\n",
1067                                count, (long)(n - CTL_HEADER_LEN));
1068                         return ERR_INCOMPLETE;
1069                 }
1070
1071                 if (debug >= 3 && shouldbesize > n) {
1072                         u_int32 key;
1073                         u_int32 *lpkt;
1074                         int maclen;
1075
1076                         /*
1077                          * Usually we ignore authentication, but for debugging purposes
1078                          * we watch it here.
1079                          */
1080                         /* round to 8 octet boundary */
1081                         shouldbesize = (shouldbesize + 7) & ~7;
1082
1083                         maclen = n - shouldbesize;
1084                         if (maclen >= (int)MIN_MAC_LEN) {
1085                                 printf(
1086                                         "Packet shows signs of authentication (total %d, data %d, mac %d)\n",
1087                                         n, shouldbesize, maclen);
1088                                 lpkt = (u_int32 *)&rpkt;
1089                                 printf("%08lx %08lx %08lx %08lx %08lx %08lx\n",
1090                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 3]),
1091                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 2]),
1092                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 1]),
1093                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32)]),
1094                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 1]),
1095                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 2]));
1096                                 key = ntohl(lpkt[(n - maclen) / sizeof(u_int32)]);
1097                                 printf("Authenticated with keyid %lu\n", (u_long)key);
1098                                 if (key != 0 && key != info_auth_keyid) {
1099                                         printf("We don't know that key\n");
1100                                 } else {
1101                                         if (authdecrypt(key, (u_int32 *)&rpkt,
1102                                             n - maclen, maclen)) {
1103                                                 printf("Auth okay!\n");
1104                                         } else {
1105                                                 printf("Auth failed!\n");
1106                                         }
1107                                 }
1108                         }
1109                 }
1110
1111                 TRACE(2, ("Got packet, size = %d\n", n));
1112                 if (count > (n - CTL_HEADER_LEN)) {
1113                         TRACE(1, ("Received count of %u octets, data in packet is %ld\n",
1114                                   count, (long)n - CTL_HEADER_LEN));
1115                         continue;
1116                 }
1117                 if (count == 0 && CTL_ISMORE(rpkt.r_m_e_op)) {
1118                         TRACE(1, ("Received count of 0 in non-final fragment\n"));
1119                         continue;
1120                 }
1121                 if (offset + count > sizeof(pktdata)) {
1122                         TRACE(1, ("Offset %u, count %u, too big for buffer\n",
1123                                   offset, count));
1124                         return ERR_TOOMUCH;
1125                 }
1126                 if (seenlastfrag && !CTL_ISMORE(rpkt.r_m_e_op)) {
1127                         TRACE(1, ("Received second last fragment packet\n"));
1128                         continue;
1129                 }
1130
1131                 /*
1132                  * So far, so good.  Record this fragment, making sure it doesn't
1133                  * overlap anything.
1134                  */
1135                 TRACE(2, ("Packet okay\n"));
1136
1137                 if (numfrags > (MAXFRAGS - 1)) {
1138                         TRACE(2, ("Number of fragments exceeds maximum %d\n",
1139                                   MAXFRAGS - 1));
1140                         return ERR_TOOMUCH;
1141                 }
1142
1143                 /*
1144                  * Find the position for the fragment relative to any
1145                  * previously received.
1146                  */
1147                 for (f = 0;
1148                      f < numfrags && offsets[f] < offset;
1149                      f++) {
1150                         /* empty body */ ;
1151                 }
1152
1153                 if (f < numfrags && offset == offsets[f]) {
1154                         TRACE(1, ("duplicate %u octets at %u ignored, prior %u at %u\n",
1155                                   count, offset, counts[f], offsets[f]));
1156                         continue;
1157                 }
1158
1159                 if (f > 0 && (offsets[f-1] + counts[f-1]) > offset) {
1160                         TRACE(1, ("received frag at %u overlaps with %u octet frag at %u\n",
1161                                   offset, counts[f-1], offsets[f-1]));
1162                         continue;
1163                 }
1164
1165                 if (f < numfrags && (offset + count) > offsets[f]) {
1166                         TRACE(1, ("received %u octet frag at %u overlaps with frag at %u\n",
1167                                   count, offset, offsets[f]));
1168                         continue;
1169                 }
1170
1171                 for (ff = numfrags; ff > f; ff--) {
1172                         offsets[ff] = offsets[ff-1];
1173                         counts[ff] = counts[ff-1];
1174                 }
1175                 offsets[f] = offset;
1176                 counts[f] = count;
1177                 numfrags++;
1178
1179                 /*
1180                  * Got that stuffed in right.  Figure out if this was the last.
1181                  * Record status info out of the last packet.
1182                  */
1183                 if (!CTL_ISMORE(rpkt.r_m_e_op)) {
1184                         seenlastfrag = 1;
1185                         if (rstatus != 0)
1186                                 *rstatus = ntohs(rpkt.status);
1187                 }
1188
1189                 /*
1190                  * Copy the data into the data buffer, and bump the
1191                  * timout base in case we need more.
1192                  */
1193                 memcpy((char *)pktdata + offset, &rpkt.u, count);
1194                 tobase = (uint32_t)time(NULL);
1195                 
1196                 /*
1197                  * If we've seen the last fragment, look for holes in the sequence.
1198                  * If there aren't any, we're done.
1199                  */
1200 #if !defined(SYS_WINNT) && defined(EINTR)
1201                 maybe_final:
1202 #endif
1203
1204                 if (seenlastfrag && offsets[0] == 0) {
1205                         for (f = 1; f < numfrags; f++)
1206                                 if (offsets[f-1] + counts[f-1] !=
1207                                     offsets[f])
1208                                         break;
1209                         if (f == numfrags) {
1210                                 *rsize = offsets[f-1] + counts[f-1];
1211                                 TRACE(1, ("%lu packets reassembled into response\n",
1212                                           (u_long)numfrags));
1213                                 return 0;
1214                         }
1215                 }
1216         }  /* giant for (;;) collecting response packets */
1217 }  /* getresponse() */
1218
1219
1220 /*
1221  * sendrequest - format and send a request packet
1222  */
1223 static int
1224 sendrequest(
1225         int opcode,
1226         associd_t associd,
1227         int auth,
1228         size_t qsize,
1229         const char *qdata
1230         )
1231 {
1232         struct ntp_control qpkt;
1233         size_t  pktsize;
1234         u_long  key_id;
1235         char *  pass;
1236         size_t  maclen;
1237
1238         /*
1239          * Check to make sure the data will fit in one packet
1240          */
1241         if (qsize > CTL_MAX_DATA_LEN) {
1242                 fprintf(stderr,
1243                         "***Internal error!  qsize (%zu) too large\n",
1244                         qsize);
1245                 return 1;
1246         }
1247
1248         /*
1249          * Fill in the packet
1250          */
1251         qpkt.li_vn_mode = PKT_LI_VN_MODE(0, pktversion, MODE_CONTROL);
1252         qpkt.r_m_e_op = (u_char)(opcode & CTL_OP_MASK);
1253         qpkt.sequence = htons(sequence);
1254         qpkt.status = 0;
1255         qpkt.associd = htons((u_short)associd);
1256         qpkt.offset = 0;
1257         qpkt.count = htons((u_short)qsize);
1258
1259         pktsize = CTL_HEADER_LEN;
1260
1261         /*
1262          * If we have data, copy and pad it out to a 32-bit boundary.
1263          */
1264         if (qsize > 0) {
1265                 memcpy(&qpkt.u, qdata, (size_t)qsize);
1266                 pktsize += qsize;
1267                 while (pktsize & (sizeof(u_int32) - 1)) {
1268                         qpkt.u.data[qsize++] = 0;
1269                         pktsize++;
1270                 }
1271         }
1272
1273         /*
1274          * If it isn't authenticated we can just send it.  Otherwise
1275          * we're going to have to think about it a little.
1276          */
1277         if (!auth && !always_auth) {
1278                 return sendpkt(&qpkt, pktsize);
1279         }
1280
1281         /*
1282          * Pad out packet to a multiple of 8 octets to be sure
1283          * receiver can handle it.
1284          */
1285         while (pktsize & 7) {
1286                 qpkt.u.data[qsize++] = 0;
1287                 pktsize++;
1288         }
1289
1290         /*
1291          * Get the keyid and the password if we don't have one.
1292          */
1293         if (info_auth_keyid == 0) {
1294                 key_id = getkeyid("Keyid: ");
1295                 if (key_id == 0 || key_id > NTP_MAXKEY) {
1296                         fprintf(stderr,
1297                                 "Invalid key identifier\n");
1298                         return 1;
1299                 }
1300                 info_auth_keyid = key_id;
1301         }
1302         if (!authistrusted(info_auth_keyid)) {
1303                 pass = getpass_keytype(info_auth_keytype);
1304                 if ('\0' == pass[0]) {
1305                         fprintf(stderr, "Invalid password\n");
1306                         return 1;
1307                 }
1308                 authusekey(info_auth_keyid, info_auth_keytype,
1309                            (u_char *)pass);
1310                 authtrust(info_auth_keyid, 1);
1311         }
1312
1313         /*
1314          * Do the encryption.
1315          */
1316         maclen = authencrypt(info_auth_keyid, (void *)&qpkt, pktsize);
1317         if (!maclen) {
1318                 fprintf(stderr, "Key not found\n");
1319                 return 1;
1320         } else if ((size_t)maclen != (info_auth_hashlen + sizeof(keyid_t))) {
1321                 fprintf(stderr,
1322                         "%zu octet MAC, %zu expected with %zu octet digest\n",
1323                         maclen, (info_auth_hashlen + sizeof(keyid_t)),
1324                         info_auth_hashlen);
1325                 return 1;
1326         }
1327
1328         return sendpkt((char *)&qpkt, pktsize + maclen);
1329 }
1330
1331
1332 /*
1333  * show_error_msg - display the error text for a mode 6 error response.
1334  */
1335 void
1336 show_error_msg(
1337         int             m6resp,
1338         associd_t       associd
1339         )
1340 {
1341         if (numhosts > 1)
1342                 fprintf(stderr, "server=%s ", currenthost);
1343
1344         switch (m6resp) {
1345
1346         case CERR_BADFMT:
1347                 fprintf(stderr,
1348                     "***Server reports a bad format request packet\n");
1349                 break;
1350
1351         case CERR_PERMISSION:
1352                 fprintf(stderr,
1353                     "***Server disallowed request (authentication?)\n");
1354                 break;
1355
1356         case CERR_BADOP:
1357                 fprintf(stderr,
1358                     "***Server reports a bad opcode in request\n");
1359                 break;
1360
1361         case CERR_BADASSOC:
1362                 fprintf(stderr,
1363                     "***Association ID %d unknown to server\n",
1364                     associd);
1365                 break;
1366
1367         case CERR_UNKNOWNVAR:
1368                 fprintf(stderr,
1369                     "***A request variable unknown to the server\n");
1370                 break;
1371
1372         case CERR_BADVALUE:
1373                 fprintf(stderr,
1374                     "***Server indicates a request variable was bad\n");
1375                 break;
1376
1377         case ERR_UNSPEC:
1378                 fprintf(stderr,
1379                     "***Server returned an unspecified error\n");
1380                 break;
1381
1382         case ERR_TIMEOUT:
1383                 fprintf(stderr, "***Request timed out\n");
1384                 break;
1385
1386         case ERR_INCOMPLETE:
1387                 fprintf(stderr,
1388                     "***Response from server was incomplete\n");
1389                 break;
1390
1391         case ERR_TOOMUCH:
1392                 fprintf(stderr,
1393                     "***Buffer size exceeded for returned data\n");
1394                 break;
1395
1396         default:
1397                 fprintf(stderr,
1398                     "***Server returns unknown error code %d\n",
1399                     m6resp);
1400         }
1401 }
1402
1403 /*
1404  * doquery - send a request and process the response, displaying
1405  *           error messages for any error responses.
1406  */
1407 int
1408 doquery(
1409         int opcode,
1410         associd_t associd,
1411         int auth,
1412         size_t qsize,
1413         const char *qdata,
1414         u_short *rstatus,
1415         size_t *rsize,
1416         const char **rdata
1417         )
1418 {
1419         return doqueryex(opcode, associd, auth, qsize, qdata, rstatus,
1420                          rsize, rdata, FALSE);
1421 }
1422
1423
1424 /*
1425  * doqueryex - send a request and process the response, optionally
1426  *             displaying error messages for any error responses.
1427  */
1428 int
1429 doqueryex(
1430         int opcode,
1431         associd_t associd,
1432         int auth,
1433         size_t qsize,
1434         const char *qdata,
1435         u_short *rstatus,
1436         size_t *rsize,
1437         const char **rdata,
1438         int quiet
1439         )
1440 {
1441         int res;
1442         int done;
1443
1444         /*
1445          * Check to make sure host is open
1446          */
1447         if (!havehost) {
1448                 fprintf(stderr, "***No host open, use `host' command\n");
1449                 return -1;
1450         }
1451
1452         done = 0;
1453         sequence++;
1454
1455     again:
1456         /*
1457          * send a request
1458          */
1459         res = sendrequest(opcode, associd, auth, qsize, qdata);
1460         if (res != 0)
1461                 return res;
1462
1463         /*
1464          * Get the response.  If we got a standard error, print a message
1465          */
1466         res = getresponse(opcode, associd, rstatus, rsize, rdata, done);
1467
1468         if (res > 0) {
1469                 if (!done && (res == ERR_TIMEOUT || res == ERR_INCOMPLETE)) {
1470                         if (res == ERR_INCOMPLETE) {
1471                                 /*
1472                                  * better bump the sequence so we don't
1473                                  * get confused about differing fragments.
1474                                  */
1475                                 sequence++;
1476                         }
1477                         done = 1;
1478                         goto again;
1479                 }
1480                 if (!quiet)
1481                         show_error_msg(res, associd);
1482
1483         }
1484         return res;
1485 }
1486
1487
1488 #ifndef BUILD_AS_LIB
1489 /*
1490  * getcmds - read commands from the standard input and execute them
1491  */
1492 static void
1493 getcmds(void)
1494 {
1495         char *  line;
1496         int     count;
1497
1498         ntp_readline_init(interactive ? prompt : NULL);
1499
1500         for (;;) {
1501                 line = ntp_readline(&count);
1502                 if (NULL == line)
1503                         break;
1504                 docmd(line);
1505                 free(line);
1506         }
1507
1508         ntp_readline_uninit();
1509 }
1510 #endif /* !BUILD_AS_LIB */
1511
1512
1513 #if !defined(SYS_WINNT) && !defined(BUILD_AS_LIB)
1514 /*
1515  * abortcmd - catch interrupts and abort the current command
1516  */
1517 static int
1518 abortcmd(void)
1519 {
1520         if (current_output == stdout)
1521                 (void) fflush(stdout);
1522         putc('\n', stderr);
1523         (void) fflush(stderr);
1524         if (jump) {
1525                 jump = 0;
1526                 longjmp(interrupt_buf, 1);
1527         }
1528         return TRUE;
1529 }
1530 #endif  /* !SYS_WINNT && !BUILD_AS_LIB */
1531
1532
1533 #ifndef BUILD_AS_LIB
1534 /*
1535  * docmd - decode the command line and execute a command
1536  */
1537 static void
1538 docmd(
1539         const char *cmdline
1540         )
1541 {
1542         char *tokens[1+MAXARGS+2];
1543         struct parse pcmd;
1544         int ntok;
1545         static int i;
1546         struct xcmd *xcmd;
1547
1548         /*
1549          * Tokenize the command line.  If nothing on it, return.
1550          */
1551         tokenize(cmdline, tokens, &ntok);
1552         if (ntok == 0)
1553             return;
1554
1555         /*
1556          * Find the appropriate command description.
1557          */
1558         i = findcmd(tokens[0], builtins, opcmds, &xcmd);
1559         if (i == 0) {
1560                 (void) fprintf(stderr, "***Command `%s' unknown\n",
1561                                tokens[0]);
1562                 return;
1563         } else if (i >= 2) {
1564                 (void) fprintf(stderr, "***Command `%s' ambiguous\n",
1565                                tokens[0]);
1566                 return;
1567         }
1568
1569         /* Warn about ignored extra args */
1570         for (i = MAXARGS + 1; i < ntok ; ++i) {
1571                 fprintf(stderr, "***Extra arg `%s' ignored\n", tokens[i]);
1572         }
1573
1574         /*
1575          * Save the keyword, then walk through the arguments, interpreting
1576          * as we go.
1577          */
1578         pcmd.keyword = tokens[0];
1579         pcmd.nargs = 0;
1580         for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) {
1581                 if ((i+1) >= ntok) {
1582                         if (!(xcmd->arg[i] & OPT)) {
1583                                 printusage(xcmd, stderr);
1584                                 return;
1585                         }
1586                         break;
1587                 }
1588                 if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>'))
1589                         break;
1590                 if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i]))
1591                         return;
1592                 pcmd.nargs++;
1593         }
1594
1595         i++;
1596         if (i < ntok && *tokens[i] == '>') {
1597                 char *fname;
1598
1599                 if (*(tokens[i]+1) != '\0')
1600                         fname = tokens[i]+1;
1601                 else if ((i+1) < ntok)
1602                         fname = tokens[i+1];
1603                 else {
1604                         (void) fprintf(stderr, "***No file for redirect\n");
1605                         return;
1606                 }
1607
1608                 current_output = fopen(fname, "w");
1609                 if (current_output == NULL) {
1610                         (void) fprintf(stderr, "***Error opening %s: ", fname);
1611                         perror("");
1612                         return;
1613                 }
1614                 i = 1;          /* flag we need a close */
1615         } else {
1616                 current_output = stdout;
1617                 i = 0;          /* flag no close */
1618         }
1619
1620         if (interactive && setjmp(interrupt_buf)) {
1621                 jump = 0;
1622                 return;
1623         } else {
1624                 jump++;
1625                 (xcmd->handler)(&pcmd, current_output);
1626                 jump = 0;       /* HMS: 961106: was after fclose() */
1627                 if (i) (void) fclose(current_output);
1628         }
1629
1630         return;
1631 }
1632
1633
1634 /*
1635  * tokenize - turn a command line into tokens
1636  *
1637  * SK: Modified to allow a quoted string
1638  *
1639  * HMS: If the first character of the first token is a ':' then (after
1640  * eating inter-token whitespace) the 2nd token is the rest of the line.
1641  */
1642
1643 static void
1644 tokenize(
1645         const char *line,
1646         char **tokens,
1647         int *ntok
1648         )
1649 {
1650         register const char *cp;
1651         register char *sp;
1652         static char tspace[MAXLINE];
1653
1654         sp = tspace;
1655         cp = line;
1656         for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
1657                 tokens[*ntok] = sp;
1658
1659                 /* Skip inter-token whitespace */
1660                 while (ISSPACE(*cp))
1661                     cp++;
1662
1663                 /* If we're at EOL we're done */
1664                 if (ISEOL(*cp))
1665                     break;
1666
1667                 /* If this is the 2nd token and the first token begins
1668                  * with a ':', then just grab to EOL.
1669                  */
1670
1671                 if (*ntok == 1 && tokens[0][0] == ':') {
1672                         do {
1673                                 if (sp - tspace >= MAXLINE)
1674                                         goto toobig;
1675                                 *sp++ = *cp++;
1676                         } while (!ISEOL(*cp));
1677                 }
1678
1679                 /* Check if this token begins with a double quote.
1680                  * If yes, continue reading till the next double quote
1681                  */
1682                 else if (*cp == '\"') {
1683                         ++cp;
1684                         do {
1685                                 if (sp - tspace >= MAXLINE)
1686                                         goto toobig;
1687                                 *sp++ = *cp++;
1688                         } while ((*cp != '\"') && !ISEOL(*cp));
1689                         /* HMS: a missing closing " should be an error */
1690                 }
1691                 else {
1692                         do {
1693                                 if (sp - tspace >= MAXLINE)
1694                                         goto toobig;
1695                                 *sp++ = *cp++;
1696                         } while ((*cp != '\"') && !ISSPACE(*cp) && !ISEOL(*cp));
1697                         /* HMS: Why check for a " in the previous line? */
1698                 }
1699
1700                 if (sp - tspace >= MAXLINE)
1701                         goto toobig;
1702                 *sp++ = '\0';
1703         }
1704         return;
1705
1706   toobig:
1707         *ntok = 0;
1708         fprintf(stderr,
1709                 "***Line `%s' is too big\n",
1710                 line);
1711         return;
1712 }
1713
1714
1715 /*
1716  * getarg - interpret an argument token
1717  */
1718 static int
1719 getarg(
1720         const char *str,
1721         int code,
1722         arg_v *argp
1723         )
1724 {
1725         u_long ul;
1726
1727         switch (code & ~OPT) {
1728         case NTP_STR:
1729                 argp->string = str;
1730                 break;
1731
1732         case NTP_ADD:
1733                 if (!getnetnum(str, &argp->netnum, NULL, 0))
1734                         return 0;
1735                 break;
1736
1737         case NTP_UINT:
1738                 if ('&' == str[0]) {
1739                         if (!atouint(&str[1], &ul)) {
1740                                 fprintf(stderr,
1741                                         "***Association index `%s' invalid/undecodable\n",
1742                                         str);
1743                                 return 0;
1744                         }
1745                         if (0 == numassoc) {
1746                                 dogetassoc(stdout);
1747                                 if (0 == numassoc) {
1748                                         fprintf(stderr,
1749                                                 "***No associations found, `%s' unknown\n",
1750                                                 str);
1751                                         return 0;
1752                                 }
1753                         }
1754                         ul = min(ul, numassoc);
1755                         argp->uval = assoc_cache[ul - 1].assid;
1756                         break;
1757                 }
1758                 if (!atouint(str, &argp->uval)) {
1759                         fprintf(stderr, "***Illegal unsigned value %s\n",
1760                                 str);
1761                         return 0;
1762                 }
1763                 break;
1764
1765         case NTP_INT:
1766                 if (!atoint(str, &argp->ival)) {
1767                         fprintf(stderr, "***Illegal integer value %s\n",
1768                                 str);
1769                         return 0;
1770                 }
1771                 break;
1772
1773         case IP_VERSION:
1774                 if (!strcmp("-6", str)) {
1775                         argp->ival = 6;
1776                 } else if (!strcmp("-4", str)) {
1777                         argp->ival = 4;
1778                 } else {
1779                         fprintf(stderr, "***Version must be either 4 or 6\n");
1780                         return 0;
1781                 }
1782                 break;
1783         }
1784
1785         return 1;
1786 }
1787 #endif  /* !BUILD_AS_LIB */
1788
1789
1790 /*
1791  * findcmd - find a command in a command description table
1792  */
1793 static int
1794 findcmd(
1795         const char *    str,
1796         struct xcmd *   clist1,
1797         struct xcmd *   clist2,
1798         struct xcmd **  cmd
1799         )
1800 {
1801         struct xcmd *cl;
1802         size_t clen;
1803         int nmatch;
1804         struct xcmd *nearmatch = NULL;
1805         struct xcmd *clist;
1806
1807         clen = strlen(str);
1808         nmatch = 0;
1809         if (clist1 != 0)
1810             clist = clist1;
1811         else if (clist2 != 0)
1812             clist = clist2;
1813         else
1814             return 0;
1815
1816     again:
1817         for (cl = clist; cl->keyword != 0; cl++) {
1818                 /* do a first character check, for efficiency */
1819                 if (*str != *(cl->keyword))
1820                     continue;
1821                 if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
1822                         /*
1823                          * Could be extact match, could be approximate.
1824                          * Is exact if the length of the keyword is the
1825                          * same as the str.
1826                          */
1827                         if (*((cl->keyword) + clen) == '\0') {
1828                                 *cmd = cl;
1829                                 return 1;
1830                         }
1831                         nmatch++;
1832                         nearmatch = cl;
1833                 }
1834         }
1835
1836         /*
1837          * See if there is more to do.  If so, go again.  Sorry about the
1838          * goto, too much looking at BSD sources...
1839          */
1840         if (clist == clist1 && clist2 != 0) {
1841                 clist = clist2;
1842                 goto again;
1843         }
1844
1845         /*
1846          * If we got extactly 1 near match, use it, else return number
1847          * of matches.
1848          */
1849         if (nmatch == 1) {
1850                 *cmd = nearmatch;
1851                 return 1;
1852         }
1853         return nmatch;
1854 }
1855
1856
1857 /*
1858  * getnetnum - given a host name, return its net number
1859  *             and (optional) full name
1860  */
1861 int
1862 getnetnum(
1863         const char *hname,
1864         sockaddr_u *num,
1865         char *fullhost,
1866         int af
1867         )
1868 {
1869         struct addrinfo hints, *ai = NULL;
1870
1871         ZERO(hints);
1872         hints.ai_flags = AI_CANONNAME;
1873 #ifdef AI_ADDRCONFIG
1874         hints.ai_flags |= AI_ADDRCONFIG;
1875 #endif
1876
1877         /*
1878          * decodenetnum only works with addresses, but handles syntax
1879          * that getaddrinfo doesn't:  [2001::1]:1234
1880          */
1881         if (decodenetnum(hname, num)) {
1882                 if (fullhost != NULL)
1883                         getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1884                                     LENHOSTNAME, NULL, 0, 0);
1885                 return 1;
1886         } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1887                 INSIST(sizeof(*num) >= ai->ai_addrlen);
1888                 memcpy(num, ai->ai_addr, ai->ai_addrlen);
1889                 if (fullhost != NULL) {
1890                         if (ai->ai_canonname != NULL)
1891                                 strlcpy(fullhost, ai->ai_canonname,
1892                                         LENHOSTNAME);
1893                         else
1894                                 getnameinfo(&num->sa, SOCKLEN(num),
1895                                             fullhost, LENHOSTNAME, NULL,
1896                                             0, 0);
1897                 }
1898                 freeaddrinfo(ai);
1899                 return 1;
1900         }
1901         fprintf(stderr, "***Can't find host %s\n", hname);
1902
1903         return 0;
1904 }
1905
1906
1907 /*
1908  * nntohost - convert network number to host name.  This routine enforces
1909  *             the showhostnames setting.
1910  */
1911 const char *
1912 nntohost(
1913         sockaddr_u *netnum
1914         )
1915 {
1916         return nntohost_col(netnum, LIB_BUFLENGTH - 1, FALSE);
1917 }
1918
1919
1920 /*
1921  * nntohost_col - convert network number to host name in fixed width.
1922  *                This routine enforces the showhostnames setting.
1923  *                When displaying hostnames longer than the width,
1924  *                the first part of the hostname is displayed.  When
1925  *                displaying numeric addresses longer than the width,
1926  *                Such as IPv6 addresses, the caller decides whether
1927  *                the first or last of the numeric address is used.
1928  */
1929 const char *
1930 nntohost_col(
1931         sockaddr_u *    addr,
1932         size_t          width,
1933         int             preserve_lowaddrbits
1934         )
1935 {
1936         const char *    out;
1937
1938         if (!showhostnames || SOCK_UNSPEC(addr)) {
1939                 if (preserve_lowaddrbits)
1940                         out = trunc_left(stoa(addr), width);
1941                 else
1942                         out = trunc_right(stoa(addr), width);
1943         } else if (ISREFCLOCKADR(addr)) {
1944                 out = refnumtoa(addr);
1945         } else {
1946                 out = trunc_right(socktohost(addr), width);
1947         }
1948         return out;
1949 }
1950
1951
1952 /*
1953  * nntohostp() is the same as nntohost() plus a :port suffix
1954  */
1955 const char *
1956 nntohostp(
1957         sockaddr_u *netnum
1958         )
1959 {
1960         const char *    hostn;
1961         char *          buf;
1962
1963         if (!showhostnames || SOCK_UNSPEC(netnum))
1964                 return sptoa(netnum);
1965         else if (ISREFCLOCKADR(netnum))
1966                 return refnumtoa(netnum);
1967
1968         hostn = socktohost(netnum);
1969         LIB_GETBUF(buf);
1970         snprintf(buf, LIB_BUFLENGTH, "%s:%u", hostn, SRCPORT(netnum));
1971
1972         return buf;
1973 }
1974
1975 /*
1976  * rtdatetolfp - decode an RT-11 date into an l_fp
1977  */
1978 static int
1979 rtdatetolfp(
1980         char *str,
1981         l_fp *lfp
1982         )
1983 {
1984         register char *cp;
1985         register int i;
1986         struct calendar cal;
1987         char buf[4];
1988
1989         cal.yearday = 0;
1990
1991         /*
1992          * An RT-11 date looks like:
1993          *
1994          * d[d]-Mth-y[y] hh:mm:ss
1995          *
1996          * (No docs, but assume 4-digit years are also legal...)
1997          *
1998          * d[d]-Mth-y[y[y[y]]] hh:mm:ss
1999          */
2000         cp = str;
2001         if (!isdigit((int)*cp)) {
2002                 if (*cp == '-') {
2003                         /*
2004                          * Catch special case
2005                          */
2006                         L_CLR(lfp);
2007                         return 1;
2008                 }
2009                 return 0;
2010         }
2011
2012         cal.monthday = (u_char) (*cp++ - '0');  /* ascii dependent */
2013         if (isdigit((int)*cp)) {
2014                 cal.monthday = (u_char)((cal.monthday << 3) + (cal.monthday << 1));
2015                 cal.monthday = (u_char)(cal.monthday + *cp++ - '0');
2016         }
2017
2018         if (*cp++ != '-')
2019             return 0;
2020
2021         for (i = 0; i < 3; i++)
2022             buf[i] = *cp++;
2023         buf[3] = '\0';
2024
2025         for (i = 0; i < 12; i++)
2026             if (STREQ(buf, months[i]))
2027                 break;
2028         if (i == 12)
2029             return 0;
2030         cal.month = (u_char)(i + 1);
2031
2032         if (*cp++ != '-')
2033             return 0;
2034
2035         if (!isdigit((int)*cp))
2036             return 0;
2037         cal.year = (u_short)(*cp++ - '0');
2038         if (isdigit((int)*cp)) {
2039                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2040                 cal.year = (u_short)(*cp++ - '0');
2041         }
2042         if (isdigit((int)*cp)) {
2043                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2044                 cal.year = (u_short)(cal.year + *cp++ - '0');
2045         }
2046         if (isdigit((int)*cp)) {
2047                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2048                 cal.year = (u_short)(cal.year + *cp++ - '0');
2049         }
2050
2051         /*
2052          * Catch special case.  If cal.year == 0 this is a zero timestamp.
2053          */
2054         if (cal.year == 0) {
2055                 L_CLR(lfp);
2056                 return 1;
2057         }
2058
2059         if (*cp++ != ' ' || !isdigit((int)*cp))
2060             return 0;
2061         cal.hour = (u_char)(*cp++ - '0');
2062         if (isdigit((int)*cp)) {
2063                 cal.hour = (u_char)((cal.hour << 3) + (cal.hour << 1));
2064                 cal.hour = (u_char)(cal.hour + *cp++ - '0');
2065         }
2066
2067         if (*cp++ != ':' || !isdigit((int)*cp))
2068             return 0;
2069         cal.minute = (u_char)(*cp++ - '0');
2070         if (isdigit((int)*cp)) {
2071                 cal.minute = (u_char)((cal.minute << 3) + (cal.minute << 1));
2072                 cal.minute = (u_char)(cal.minute + *cp++ - '0');
2073         }
2074
2075         if (*cp++ != ':' || !isdigit((int)*cp))
2076             return 0;
2077         cal.second = (u_char)(*cp++ - '0');
2078         if (isdigit((int)*cp)) {
2079                 cal.second = (u_char)((cal.second << 3) + (cal.second << 1));
2080                 cal.second = (u_char)(cal.second + *cp++ - '0');
2081         }
2082
2083         /*
2084          * For RT-11, 1972 seems to be the pivot year
2085          */
2086         if (cal.year < 72)
2087                 cal.year += 2000;
2088         if (cal.year < 100)
2089                 cal.year += 1900;
2090
2091         lfp->l_ui = caltontp(&cal);
2092         lfp->l_uf = 0;
2093         return 1;
2094 }
2095
2096
2097 /*
2098  * decodets - decode a timestamp into an l_fp format number, with
2099  *            consideration of fuzzball formats.
2100  */
2101 int
2102 decodets(
2103         char *str,
2104         l_fp *lfp
2105         )
2106 {
2107         char *cp;
2108         char buf[30];
2109         size_t b;
2110
2111         /*
2112          * If it starts with a 0x, decode as hex.
2113          */
2114         if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
2115                 return hextolfp(str+2, lfp);
2116
2117         /*
2118          * If it starts with a '"', try it as an RT-11 date.
2119          */
2120         if (*str == '"') {
2121                 cp = str + 1;
2122                 b = 0;
2123                 while ('"' != *cp && '\0' != *cp &&
2124                        b < COUNTOF(buf) - 1)
2125                         buf[b++] = *cp++;
2126                 buf[b] = '\0';
2127                 return rtdatetolfp(buf, lfp);
2128         }
2129
2130         /*
2131          * Might still be hex.  Check out the first character.  Talk
2132          * about heuristics!
2133          */
2134         if ((*str >= 'A' && *str <= 'F') || (*str >= 'a' && *str <= 'f'))
2135                 return hextolfp(str, lfp);
2136
2137         /*
2138          * Try it as a decimal.  If this fails, try as an unquoted
2139          * RT-11 date.  This code should go away eventually.
2140          */
2141         if (atolfp(str, lfp))
2142                 return 1;
2143
2144         return rtdatetolfp(str, lfp);
2145 }
2146
2147
2148 /*
2149  * decodetime - decode a time value.  It should be in milliseconds
2150  */
2151 int
2152 decodetime(
2153         char *str,
2154         l_fp *lfp
2155         )
2156 {
2157         return mstolfp(str, lfp);
2158 }
2159
2160
2161 /*
2162  * decodeint - decode an integer
2163  */
2164 int
2165 decodeint(
2166         char *str,
2167         long *val
2168         )
2169 {
2170         if (*str == '0') {
2171                 if (*(str+1) == 'x' || *(str+1) == 'X')
2172                     return hextoint(str+2, (u_long *)val);
2173                 return octtoint(str, (u_long *)val);
2174         }
2175         return atoint(str, val);
2176 }
2177
2178
2179 /*
2180  * decodeuint - decode an unsigned integer
2181  */
2182 int
2183 decodeuint(
2184         char *str,
2185         u_long *val
2186         )
2187 {
2188         if (*str == '0') {
2189                 if (*(str + 1) == 'x' || *(str + 1) == 'X')
2190                         return (hextoint(str + 2, val));
2191                 return (octtoint(str, val));
2192         }
2193         return (atouint(str, val));
2194 }
2195
2196
2197 /*
2198  * decodearr - decode an array of time values
2199  */
2200 static int
2201 decodearr(
2202         char *str,
2203         int *narr,
2204         l_fp *lfparr
2205         )
2206 {
2207         register char *cp, *bp;
2208         register l_fp *lfp;
2209         char buf[60];
2210
2211         lfp = lfparr;
2212         cp = str;
2213         *narr = 0;
2214
2215         while (*narr < 8) {
2216                 while (isspace((int)*cp))
2217                     cp++;
2218                 if (*cp == '\0')
2219                     break;
2220
2221                 bp = buf;
2222                 while (!isspace((int)*cp) && *cp != '\0')
2223                     *bp++ = *cp++;
2224                 *bp++ = '\0';
2225
2226                 if (!decodetime(buf, lfp))
2227                     return 0;
2228                 (*narr)++;
2229                 lfp++;
2230         }
2231         return 1;
2232 }
2233
2234
2235 /*
2236  * Finally, the built in command handlers
2237  */
2238
2239 /*
2240  * help - tell about commands, or details of a particular command
2241  */
2242 static void
2243 help(
2244         struct parse *pcmd,
2245         FILE *fp
2246         )
2247 {
2248         struct xcmd *xcp = NULL;        /* quiet warning */
2249         const char *cmd;
2250         const char *list[100];
2251         size_t word, words;
2252         size_t row, rows;
2253         size_t col, cols;
2254         size_t length;
2255
2256         if (pcmd->nargs == 0) {
2257                 words = 0;
2258                 for (xcp = builtins; xcp->keyword != NULL; xcp++) {
2259                         if (*(xcp->keyword) != '?' &&
2260                             words < COUNTOF(list))
2261                                 list[words++] = xcp->keyword;
2262                 }
2263                 for (xcp = opcmds; xcp->keyword != NULL; xcp++)
2264                         if (words < COUNTOF(list))
2265                                 list[words++] = xcp->keyword;
2266
2267                 qsort((void *)list, words, sizeof(list[0]), helpsort);
2268                 col = 0;
2269                 for (word = 0; word < words; word++) {
2270                         length = strlen(list[word]);
2271                         col = max(col, length);
2272                 }
2273
2274                 cols = SCREENWIDTH / ++col;
2275                 rows = (words + cols - 1) / cols;
2276
2277                 fprintf(fp, "ntpq commands:\n");
2278
2279                 for (row = 0; row < rows; row++) {
2280                         for (word = row; word < words; word += rows)
2281                                 fprintf(fp, "%-*.*s", (int)col,
2282                                         (int)col - 1, list[word]);
2283                         fprintf(fp, "\n");
2284                 }
2285         } else {
2286                 cmd = pcmd->argval[0].string;
2287                 words = findcmd(cmd, builtins, opcmds, &xcp);
2288                 if (words == 0) {
2289                         fprintf(stderr,
2290                                 "Command `%s' is unknown\n", cmd);
2291                         return;
2292                 } else if (words >= 2) {
2293                         fprintf(stderr,
2294                                 "Command `%s' is ambiguous\n", cmd);
2295                         return;
2296                 }
2297                 fprintf(fp, "function: %s\n", xcp->comment);
2298                 printusage(xcp, fp);
2299         }
2300 }
2301
2302
2303 /*
2304  * helpsort - do hostname qsort comparisons
2305  */
2306 static int
2307 helpsort(
2308         const void *t1,
2309         const void *t2
2310         )
2311 {
2312         const char * const *    name1 = t1;
2313         const char * const *    name2 = t2;
2314
2315         return strcmp(*name1, *name2);
2316 }
2317
2318
2319 /*
2320  * printusage - print usage information for a command
2321  */
2322 static void
2323 printusage(
2324         struct xcmd *xcp,
2325         FILE *fp
2326         )
2327 {
2328         register int i;
2329
2330         /* XXX: Do we need to warn about extra args here too? */
2331
2332         (void) fprintf(fp, "usage: %s", xcp->keyword);
2333         for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
2334                 if (xcp->arg[i] & OPT)
2335                     (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
2336                 else
2337                     (void) fprintf(fp, " %s", xcp->desc[i]);
2338         }
2339         (void) fprintf(fp, "\n");
2340 }
2341
2342
2343 /*
2344  * timeout - set time out time
2345  */
2346 static void
2347 timeout(
2348         struct parse *pcmd,
2349         FILE *fp
2350         )
2351 {
2352         int val;
2353
2354         if (pcmd->nargs == 0) {
2355                 val = (int)tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
2356                 (void) fprintf(fp, "primary timeout %d ms\n", val);
2357         } else {
2358                 tvout.tv_sec = pcmd->argval[0].uval / 1000;
2359                 tvout.tv_usec = (pcmd->argval[0].uval - ((long)tvout.tv_sec * 1000))
2360                         * 1000;
2361         }
2362 }
2363
2364
2365 /*
2366  * auth_delay - set delay for auth requests
2367  */
2368 static void
2369 auth_delay(
2370         struct parse *pcmd,
2371         FILE *fp
2372         )
2373 {
2374         int isneg;
2375         u_long val;
2376
2377         if (pcmd->nargs == 0) {
2378                 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
2379                 (void) fprintf(fp, "delay %lu ms\n", val);
2380         } else {
2381                 if (pcmd->argval[0].ival < 0) {
2382                         isneg = 1;
2383                         val = (u_long)(-pcmd->argval[0].ival);
2384                 } else {
2385                         isneg = 0;
2386                         val = (u_long)pcmd->argval[0].ival;
2387                 }
2388
2389                 delay_time.l_ui = val / 1000;
2390                 val %= 1000;
2391                 delay_time.l_uf = val * 4294967;        /* 2**32/1000 */
2392
2393                 if (isneg)
2394                     L_NEG(&delay_time);
2395         }
2396 }
2397
2398
2399 /*
2400  * host - set the host we are dealing with.
2401  */
2402 static void
2403 host(
2404         struct parse *pcmd,
2405         FILE *fp
2406         )
2407 {
2408         int i;
2409
2410         if (pcmd->nargs == 0) {
2411                 if (havehost)
2412                         (void) fprintf(fp, "current host is %s\n",
2413                                            currenthost);
2414                 else
2415                         (void) fprintf(fp, "no current host\n");
2416                 return;
2417         }
2418
2419         i = 0;
2420         ai_fam_templ = ai_fam_default;
2421         if (pcmd->nargs == 2) {
2422                 if (!strcmp("-4", pcmd->argval[i].string))
2423                         ai_fam_templ = AF_INET;
2424                 else if (!strcmp("-6", pcmd->argval[i].string))
2425                         ai_fam_templ = AF_INET6;
2426                 else
2427                         goto no_change;
2428                 i = 1;
2429         }
2430         if (openhost(pcmd->argval[i].string, ai_fam_templ)) {
2431                 fprintf(fp, "current host set to %s\n", currenthost);
2432         } else {
2433     no_change:
2434                 if (havehost)
2435                         fprintf(fp, "current host remains %s\n",
2436                                 currenthost);
2437                 else
2438                         fprintf(fp, "still no current host\n");
2439         }
2440 }
2441
2442
2443 /*
2444  * poll - do one (or more) polls of the host via NTP
2445  */
2446 /*ARGSUSED*/
2447 static void
2448 ntp_poll(
2449         struct parse *pcmd,
2450         FILE *fp
2451         )
2452 {
2453         (void) fprintf(fp, "poll not implemented yet\n");
2454 }
2455
2456
2457 /*
2458  * showdrefid2str - return a string explanation of the value of drefid
2459  */
2460 static char *
2461 showdrefid2str(void)
2462 {
2463         switch (drefid) {
2464             case REFID_HASH:
2465                 return "hash";
2466             case REFID_IPV4:
2467                 return "ipv4";
2468             default:
2469                 return "Unknown";
2470         }
2471 }
2472
2473
2474 /*
2475  * drefid - display/change "display hash" 
2476  */
2477 static void
2478 showdrefid(
2479         struct parse *pcmd,
2480         FILE *fp
2481         )
2482 {
2483         if (pcmd->nargs == 0) {
2484                 (void) fprintf(fp, "drefid value is %s\n", showdrefid2str());
2485                 return;
2486         } else if (STREQ(pcmd->argval[0].string, "hash")) {
2487                 drefid = REFID_HASH;
2488         } else if (STREQ(pcmd->argval[0].string, "ipv4")) {
2489                 drefid = REFID_IPV4;
2490         } else {
2491                 (void) fprintf(fp, "What?\n");
2492                 return;
2493         }
2494         (void) fprintf(fp, "drefid value set to %s\n", showdrefid2str());
2495 }
2496
2497
2498 /*
2499  * keyid - get a keyid to use for authenticating requests
2500  */
2501 static void
2502 keyid(
2503         struct parse *pcmd,
2504         FILE *fp
2505         )
2506 {
2507         if (pcmd->nargs == 0) {
2508                 if (info_auth_keyid == 0)
2509                     (void) fprintf(fp, "no keyid defined\n");
2510                 else
2511                     (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
2512         } else {
2513                 /* allow zero so that keyid can be cleared. */
2514                 if(pcmd->argval[0].uval > NTP_MAXKEY)
2515                     (void) fprintf(fp, "Invalid key identifier\n");
2516                 info_auth_keyid = pcmd->argval[0].uval;
2517         }
2518 }
2519
2520 /*
2521  * keytype - get type of key to use for authenticating requests
2522  */
2523 static void
2524 keytype(
2525         struct parse *pcmd,
2526         FILE *fp
2527         )
2528 {
2529         const char *    digest_name;
2530         size_t          digest_len;
2531         int             key_type;
2532
2533         if (!pcmd->nargs) {
2534                 fprintf(fp, "keytype is %s with %lu octet digests\n",
2535                         keytype_name(info_auth_keytype),
2536                         (u_long)info_auth_hashlen);
2537                 return;
2538         }
2539
2540         digest_name = pcmd->argval[0].string;
2541         digest_len = 0;
2542         key_type = keytype_from_text(digest_name, &digest_len);
2543
2544         if (!key_type) {
2545                 fprintf(fp, "keytype is not valid. "
2546 #ifdef OPENSSL
2547                         "Type \"help keytype\" for the available digest types.\n");
2548 #else
2549                         "Only \"md5\" is available.\n");
2550 #endif
2551                 return;
2552         }
2553
2554         info_auth_keytype = key_type;
2555         info_auth_hashlen = digest_len;
2556 }
2557
2558
2559 /*
2560  * passwd - get an authentication key
2561  */
2562 /*ARGSUSED*/
2563 static void
2564 passwd(
2565         struct parse *pcmd,
2566         FILE *fp
2567         )
2568 {
2569         const char *pass;
2570
2571         if (info_auth_keyid == 0) {
2572                 info_auth_keyid = getkeyid("Keyid: ");
2573                 if (info_auth_keyid == 0) {
2574                         (void)fprintf(fp, "Keyid must be defined\n");
2575                         return;
2576                 }
2577         }
2578         if (pcmd->nargs >= 1)
2579                 pass = pcmd->argval[0].string;
2580         else {
2581                 pass = getpass_keytype(info_auth_keytype);
2582                 if ('\0' == pass[0]) {
2583                         fprintf(fp, "Password unchanged\n");
2584                         return;
2585                 }
2586         }
2587         authusekey(info_auth_keyid, info_auth_keytype,
2588                    (const u_char *)pass);
2589         authtrust(info_auth_keyid, 1);
2590 }
2591
2592
2593 /*
2594  * hostnames - set the showhostnames flag
2595  */
2596 static void
2597 hostnames(
2598         struct parse *pcmd,
2599         FILE *fp
2600         )
2601 {
2602         if (pcmd->nargs == 0) {
2603                 if (showhostnames)
2604                     (void) fprintf(fp, "hostnames being shown\n");
2605                 else
2606                     (void) fprintf(fp, "hostnames not being shown\n");
2607         } else {
2608                 if (STREQ(pcmd->argval[0].string, "yes"))
2609                     showhostnames = 1;
2610                 else if (STREQ(pcmd->argval[0].string, "no"))
2611                     showhostnames = 0;
2612                 else
2613                     (void)fprintf(stderr, "What?\n");
2614         }
2615 }
2616
2617
2618
2619 /*
2620  * setdebug - set/change debugging level
2621  */
2622 static void
2623 setdebug(
2624         struct parse *pcmd,
2625         FILE *fp
2626         )
2627 {
2628         if (pcmd->nargs == 0) {
2629                 (void) fprintf(fp, "debug level is %d\n", debug);
2630                 return;
2631         } else if (STREQ(pcmd->argval[0].string, "no")) {
2632                 debug = 0;
2633         } else if (STREQ(pcmd->argval[0].string, "more")) {
2634                 debug++;
2635         } else if (STREQ(pcmd->argval[0].string, "less")) {
2636                 debug--;
2637         } else {
2638                 (void) fprintf(fp, "What?\n");
2639                 return;
2640         }
2641         (void) fprintf(fp, "debug level set to %d\n", debug);
2642 }
2643
2644
2645 /*
2646  * quit - stop this nonsense
2647  */
2648 /*ARGSUSED*/
2649 static void
2650 quit(
2651         struct parse *pcmd,
2652         FILE *fp
2653         )
2654 {
2655         if (havehost)
2656             closesocket(sockfd);        /* cleanliness next to godliness */
2657         exit(0);
2658 }
2659
2660
2661 /*
2662  * version - print the current version number
2663  */
2664 /*ARGSUSED*/
2665 static void
2666 version(
2667         struct parse *pcmd,
2668         FILE *fp
2669         )
2670 {
2671
2672         (void) fprintf(fp, "%s\n", Version);
2673         return;
2674 }
2675
2676
2677 /*
2678  * raw - set raw mode output
2679  */
2680 /*ARGSUSED*/
2681 static void
2682 raw(
2683         struct parse *pcmd,
2684         FILE *fp
2685         )
2686 {
2687         rawmode = 1;
2688         (void) fprintf(fp, "Output set to raw\n");
2689 }
2690
2691
2692 /*
2693  * cooked - set cooked mode output
2694  */
2695 /*ARGSUSED*/
2696 static void
2697 cooked(
2698         struct parse *pcmd,
2699         FILE *fp
2700         )
2701 {
2702         rawmode = 0;
2703         (void) fprintf(fp, "Output set to cooked\n");
2704         return;
2705 }
2706
2707
2708 /*
2709  * authenticate - always authenticate requests to this host
2710  */
2711 static void
2712 authenticate(
2713         struct parse *pcmd,
2714         FILE *fp
2715         )
2716 {
2717         if (pcmd->nargs == 0) {
2718                 if (always_auth) {
2719                         (void) fprintf(fp,
2720                                        "authenticated requests being sent\n");
2721                 } else
2722                     (void) fprintf(fp,
2723                                    "unauthenticated requests being sent\n");
2724         } else {
2725                 if (STREQ(pcmd->argval[0].string, "yes")) {
2726                         always_auth = 1;
2727                 } else if (STREQ(pcmd->argval[0].string, "no")) {
2728                         always_auth = 0;
2729                 } else
2730                     (void)fprintf(stderr, "What?\n");
2731         }
2732 }
2733
2734
2735 /*
2736  * ntpversion - choose the NTP version to use
2737  */
2738 static void
2739 ntpversion(
2740         struct parse *pcmd,
2741         FILE *fp
2742         )
2743 {
2744         if (pcmd->nargs == 0) {
2745                 (void) fprintf(fp,
2746                                "NTP version being claimed is %d\n", pktversion);
2747         } else {
2748                 if (pcmd->argval[0].uval < NTP_OLDVERSION
2749                     || pcmd->argval[0].uval > NTP_VERSION) {
2750                         (void) fprintf(stderr, "versions %d to %d, please\n",
2751                                        NTP_OLDVERSION, NTP_VERSION);
2752                 } else {
2753                         pktversion = (u_char) pcmd->argval[0].uval;
2754                 }
2755         }
2756 }
2757
2758
2759 static void __attribute__((__format__(__printf__, 1, 0)))
2760 vwarning(const char *fmt, va_list ap)
2761 {
2762         int serrno = errno;
2763         (void) fprintf(stderr, "%s: ", progname);
2764         vfprintf(stderr, fmt, ap);
2765         (void) fprintf(stderr, ": %s\n", strerror(serrno));
2766 }
2767
2768 /*
2769  * warning - print a warning message
2770  */
2771 static void __attribute__((__format__(__printf__, 1, 2)))
2772 warning(
2773         const char *fmt,
2774         ...
2775         )
2776 {
2777         va_list ap;
2778         va_start(ap, fmt);
2779         vwarning(fmt, ap);
2780         va_end(ap);
2781 }
2782
2783
2784 /*
2785  * error - print a message and exit
2786  */
2787 static void __attribute__((__format__(__printf__, 1, 2)))
2788 error(
2789         const char *fmt,
2790         ...
2791         )
2792 {
2793         va_list ap;
2794         va_start(ap, fmt);
2795         vwarning(fmt, ap);
2796         va_end(ap);
2797         exit(1);
2798 }
2799 /*
2800  * getkeyid - prompt the user for a keyid to use
2801  */
2802 static u_long
2803 getkeyid(
2804         const char *keyprompt
2805         )
2806 {
2807         int c;
2808         FILE *fi;
2809         char pbuf[20];
2810         size_t i;
2811         size_t ilim;
2812
2813 #ifndef SYS_WINNT
2814         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
2815 #else
2816         if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
2817 #endif /* SYS_WINNT */
2818                 fi = stdin;
2819         else
2820                 setbuf(fi, (char *)NULL);
2821         fprintf(stderr, "%s", keyprompt); fflush(stderr);
2822         for (i = 0, ilim = COUNTOF(pbuf) - 1;
2823              i < ilim && (c = getc(fi)) != '\n' && c != EOF;
2824              )
2825                 pbuf[i++] = (char)c;
2826         pbuf[i] = '\0';
2827         if (fi != stdin)
2828                 fclose(fi);
2829
2830         return (u_long) atoi(pbuf);
2831 }
2832
2833
2834 /*
2835  * atoascii - printable-ize possibly ascii data using the character
2836  *            transformations cat -v uses.
2837  */
2838 static void
2839 atoascii(
2840         const char *in,
2841         size_t in_octets,
2842         char *out,
2843         size_t out_octets
2844         )
2845 {
2846         const u_char *  pchIn;
2847         const u_char *  pchInLimit;
2848         u_char *        pchOut;
2849         u_char          c;
2850
2851         pchIn = (const u_char *)in;
2852         pchInLimit = pchIn + in_octets;
2853         pchOut = (u_char *)out;
2854
2855         if (NULL == pchIn) {
2856                 if (0 < out_octets)
2857                         *pchOut = '\0';
2858                 return;
2859         }
2860
2861 #define ONEOUT(c)                                       \
2862 do {                                                    \
2863         if (0 == --out_octets) {                        \
2864                 *pchOut = '\0';                         \
2865                 return;                                 \
2866         }                                               \
2867         *pchOut++ = (c);                                \
2868 } while (0)
2869
2870         for (   ; pchIn < pchInLimit; pchIn++) {
2871                 c = *pchIn;
2872                 if ('\0' == c)
2873                         break;
2874                 if (c & 0x80) {
2875                         ONEOUT('M');
2876                         ONEOUT('-');
2877                         c &= 0x7f;
2878                 }
2879                 if (c < ' ') {
2880                         ONEOUT('^');
2881                         ONEOUT((u_char)(c + '@'));
2882                 } else if (0x7f == c) {
2883                         ONEOUT('^');
2884                         ONEOUT('?');
2885                 } else
2886                         ONEOUT(c);
2887         }
2888         ONEOUT('\0');
2889
2890 #undef ONEOUT
2891 }
2892
2893
2894 /*
2895  * makeascii - print possibly ascii data using the character
2896  *             transformations that cat -v uses.
2897  */
2898 void
2899 makeascii(
2900         size_t length,
2901         const char *data,
2902         FILE *fp
2903         )
2904 {
2905         const u_char *data_u_char;
2906         const u_char *cp;
2907         int c;
2908
2909         data_u_char = (const u_char *)data;
2910
2911         for (cp = data_u_char; cp < data_u_char + length; cp++) {
2912                 c = (int)*cp;
2913                 if (c & 0x80) {
2914                         putc('M', fp);
2915                         putc('-', fp);
2916                         c &= 0x7f;
2917                 }
2918
2919                 if (c < ' ') {
2920                         putc('^', fp);
2921                         putc(c + '@', fp);
2922                 } else if (0x7f == c) {
2923                         putc('^', fp);
2924                         putc('?', fp);
2925                 } else
2926                         putc(c, fp);
2927         }
2928 }
2929
2930
2931 /*
2932  * asciize - same thing as makeascii except add a newline
2933  */
2934 void
2935 asciize(
2936         int length,
2937         char *data,
2938         FILE *fp
2939         )
2940 {
2941         makeascii(length, data, fp);
2942         putc('\n', fp);
2943 }
2944
2945
2946 /*
2947  * truncate string to fit clipping excess at end.
2948  *      "too long"      ->      "too l"
2949  * Used for hostnames.
2950  */
2951 const char *
2952 trunc_right(
2953         const char *    src,
2954         size_t          width
2955         )
2956 {
2957         size_t  sl;
2958         char *  out;
2959
2960
2961         sl = strlen(src);
2962         if (sl > width && LIB_BUFLENGTH - 1 > width && width > 0) {
2963                 LIB_GETBUF(out);
2964                 memcpy(out, src, width);
2965                 out[width] = '\0';
2966
2967                 return out;
2968         }
2969
2970         return src;
2971 }
2972
2973
2974 /*
2975  * truncate string to fit by preserving right side and using '_' to hint
2976  *      "too long"      ->      "_long"
2977  * Used for local IPv6 addresses, where low bits differentiate.
2978  */
2979 const char *
2980 trunc_left(
2981         const char *    src,
2982         size_t          width
2983         )
2984 {
2985         size_t  sl;
2986         char *  out;
2987
2988
2989         sl = strlen(src);
2990         if (sl > width && LIB_BUFLENGTH - 1 > width && width > 1) {
2991                 LIB_GETBUF(out);
2992                 out[0] = '_';
2993                 memcpy(&out[1], &src[sl + 1 - width], width);
2994
2995                 return out;
2996         }
2997
2998         return src;
2999 }
3000
3001
3002 /*
3003  * Some circular buffer space
3004  */
3005 #define CBLEN   80
3006 #define NUMCB   6
3007
3008 char circ_buf[NUMCB][CBLEN];
3009 int nextcb = 0;
3010
3011 /*
3012  * nextvar - find the next variable in the buffer
3013  */
3014 int
3015 nextvar(
3016         size_t *datalen,
3017         const char **datap,
3018         char **vname,
3019         char **vvalue
3020         )
3021 {
3022         const char *cp;
3023         const char *np;
3024         const char *cpend;
3025         size_t srclen;
3026         size_t len;
3027         static char name[MAXVARLEN];
3028         static char value[MAXVALLEN];
3029
3030         cp = *datap;
3031         cpend = cp + *datalen;
3032
3033         /*
3034          * Space past commas and white space
3035          */
3036         while (cp < cpend && (*cp == ',' || isspace((int)*cp)))
3037                 cp++;
3038         if (cp >= cpend)
3039                 return 0;
3040
3041         /*
3042          * Copy name until we hit a ',', an '=', a '\r' or a '\n'.  Backspace
3043          * over any white space and terminate it.
3044          */
3045         srclen = strcspn(cp, ",=\r\n");
3046         srclen = min(srclen, (size_t)(cpend - cp));
3047         len = srclen;
3048         while (len > 0 && isspace((unsigned char)cp[len - 1]))
3049                 len--;
3050         if (len >= sizeof(name))
3051             return 0;
3052         if (len > 0)
3053                 memcpy(name, cp, len);
3054         name[len] = '\0';
3055         *vname = name;
3056         cp += srclen;
3057
3058         /*
3059          * Check if we hit the end of the buffer or a ','.  If so we are done.
3060          */
3061         if (cp >= cpend || *cp == ',' || *cp == '\r' || *cp == '\n') {
3062                 if (cp < cpend)
3063                         cp++;
3064                 *datap = cp;
3065                 *datalen = size2int_sat(cpend - cp);
3066                 *vvalue = NULL;
3067                 return 1;
3068         }
3069
3070         /*
3071          * So far, so good.  Copy out the value
3072          */
3073         cp++;   /* past '=' */
3074         while (cp < cpend && (isspace((unsigned char)*cp) && *cp != '\r' && *cp != '\n'))
3075                 cp++;
3076         np = cp;
3077         if ('"' == *np) {
3078                 do {
3079                         np++;
3080                 } while (np < cpend && '"' != *np);
3081                 if (np < cpend && '"' == *np)
3082                         np++;
3083         } else {
3084                 while (np < cpend && ',' != *np && '\r' != *np)
3085                         np++;
3086         }
3087         len = np - cp;
3088         if (np > cpend || len >= sizeof(value) ||
3089             (np < cpend && ',' != *np && '\r' != *np))
3090                 return 0;
3091         memcpy(value, cp, len);
3092         /*
3093          * Trim off any trailing whitespace
3094          */
3095         while (len > 0 && isspace((unsigned char)value[len - 1]))
3096                 len--;
3097         value[len] = '\0';
3098
3099         /*
3100          * Return this.  All done.
3101          */
3102         if (np < cpend && ',' == *np)
3103                 np++;
3104         *datap = np;
3105         *datalen = size2int_sat(cpend - np);
3106         *vvalue = value;
3107         return 1;
3108 }
3109
3110
3111 u_short
3112 varfmt(const char * varname)
3113 {
3114         u_int n;
3115
3116         for (n = 0; n < COUNTOF(cookedvars); n++)
3117                 if (!strcmp(varname, cookedvars[n].varname))
3118                         return cookedvars[n].fmt;
3119
3120         return PADDING;
3121 }
3122
3123
3124 /*
3125  * printvars - print variables returned in response packet
3126  */
3127 void
3128 printvars(
3129         size_t length,
3130         const char *data,
3131         int status,
3132         int sttype,
3133         int quiet,
3134         FILE *fp
3135         )
3136 {
3137         if (rawmode)
3138             rawprint(sttype, length, data, status, quiet, fp);
3139         else
3140             cookedprint(sttype, length, data, status, quiet, fp);
3141 }
3142
3143
3144 /*
3145  * rawprint - do a printout of the data in raw mode
3146  */
3147 static void
3148 rawprint(
3149         int datatype,
3150         size_t length,
3151         const char *data,
3152         int status,
3153         int quiet,
3154         FILE *fp
3155         )
3156 {
3157         const char *cp;
3158         const char *cpend;
3159
3160         /*
3161          * Essentially print the data as is.  We reformat unprintables, though.
3162          */
3163         cp = data;
3164         cpend = data + length;
3165
3166         if (!quiet)
3167                 (void) fprintf(fp, "status=0x%04x,\n", status);
3168
3169         while (cp < cpend) {
3170                 if (*cp == '\r') {
3171                         /*
3172                          * If this is a \r and the next character is a
3173                          * \n, supress this, else pretty print it.  Otherwise
3174                          * just output the character.
3175                          */
3176                         if (cp == (cpend - 1) || *(cp + 1) != '\n')
3177                             makeascii(1, cp, fp);
3178                 } else if (isspace((unsigned char)*cp) || isprint((unsigned char)*cp))
3179                         putc(*cp, fp);
3180                 else
3181                         makeascii(1, cp, fp);
3182                 cp++;
3183         }
3184 }
3185
3186
3187 /*
3188  * Global data used by the cooked output routines
3189  */
3190 int out_chars;          /* number of characters output */
3191 int out_linecount;      /* number of characters output on this line */
3192
3193
3194 /*
3195  * startoutput - get ready to do cooked output
3196  */
3197 static void
3198 startoutput(void)
3199 {
3200         out_chars = 0;
3201         out_linecount = 0;
3202 }
3203
3204
3205 /*
3206  * output - output a variable=value combination
3207  */
3208 static void
3209 output(
3210         FILE *fp,
3211         const char *name,
3212         const char *value
3213         )
3214 {
3215         int len;
3216
3217         /* strlen of "name=value" */
3218         len = size2int_sat(strlen(name) + 1 + strlen(value));
3219
3220         if (out_chars != 0) {
3221                 out_chars += 2;
3222                 if ((out_linecount + len + 2) > MAXOUTLINE) {
3223                         fputs(",\n", fp);
3224                         out_linecount = 0;
3225                 } else {
3226                         fputs(", ", fp);
3227                         out_linecount += 2;
3228                 }
3229         }
3230
3231         fputs(name, fp);
3232         putc('=', fp);
3233         fputs(value, fp);
3234         out_chars += len;
3235         out_linecount += len;
3236 }
3237
3238
3239 /*
3240  * endoutput - terminate a block of cooked output
3241  */
3242 static void
3243 endoutput(
3244         FILE *fp
3245         )
3246 {
3247         if (out_chars != 0)
3248                 putc('\n', fp);
3249 }
3250
3251
3252 /*
3253  * outputarr - output an array of values
3254  */
3255 static void
3256 outputarr(
3257         FILE *fp,
3258         char *name,
3259         int narr,
3260         l_fp *lfp
3261         )
3262 {
3263         char *bp;
3264         char *cp;
3265         size_t i;
3266         size_t len;
3267         char buf[256];
3268
3269         bp = buf;
3270         /*
3271          * Hack to align delay and offset values
3272          */
3273         for (i = (int)strlen(name); i < 11; i++)
3274             *bp++ = ' ';
3275
3276         for (i = narr; i > 0; i--) {
3277                 if (i != narr)
3278                     *bp++ = ' ';
3279                 cp = lfptoms(lfp, 2);
3280                 len = strlen(cp);
3281                 if (len > 7) {
3282                         cp[7] = '\0';
3283                         len = 7;
3284                 }
3285                 while (len < 7) {
3286                         *bp++ = ' ';
3287                         len++;
3288                 }
3289                 while (*cp != '\0')
3290                     *bp++ = *cp++;
3291                 lfp++;
3292         }
3293         *bp = '\0';
3294         output(fp, name, buf);
3295 }
3296
3297 static char *
3298 tstflags(
3299         u_long val
3300         )
3301 {
3302         register char *cp, *s;
3303         size_t cb;
3304         register int i;
3305         register const char *sep;
3306
3307         sep = "";
3308         s = cp = circ_buf[nextcb];
3309         if (++nextcb >= NUMCB)
3310                 nextcb = 0;
3311         cb = sizeof(circ_buf[0]);
3312
3313         snprintf(cp, cb, "%02lx", val);
3314         cp += strlen(cp);
3315         cb -= strlen(cp);
3316         if (!val) {
3317                 strlcat(cp, " ok", cb);
3318                 cp += strlen(cp);
3319                 cb -= strlen(cp);
3320         } else {
3321                 if (cb) {
3322                         *cp++ = ' ';
3323                         cb--;
3324                 }
3325                 for (i = 0; i < (int)COUNTOF(tstflagnames); i++) {
3326                         if (val & 0x1) {
3327                                 snprintf(cp, cb, "%s%s", sep,
3328                                          tstflagnames[i]);
3329                                 sep = ", ";
3330                                 cp += strlen(cp);
3331                                 cb -= strlen(cp);
3332                         }
3333                         val >>= 1;
3334                 }
3335         }
3336         if (cb)
3337                 *cp = '\0';
3338
3339         return s;
3340 }
3341
3342 /*
3343  * cookedprint - output variables in cooked mode
3344  */
3345 static void
3346 cookedprint(
3347         int datatype,
3348         size_t length,
3349         const char *data,
3350         int status,
3351         int quiet,
3352         FILE *fp
3353         )
3354 {
3355         char *name;
3356         char *value;
3357         char output_raw;
3358         int fmt;
3359         l_fp lfp;
3360         sockaddr_u hval;
3361         u_long uval;
3362         int narr;
3363         size_t len;
3364         l_fp lfparr[8];
3365         char b[12];
3366         char bn[2 * MAXVARLEN];
3367         char bv[2 * MAXVALLEN];
3368
3369         UNUSED_ARG(datatype);
3370
3371         if (!quiet)
3372                 fprintf(fp, "status=%04x %s,\n", status,
3373                         statustoa(datatype, status));
3374
3375         startoutput();
3376         while (nextvar(&length, &data, &name, &value)) {
3377                 fmt = varfmt(name);
3378                 output_raw = 0;
3379                 switch (fmt) {
3380
3381                 case PADDING:
3382                         output_raw = '*';
3383                         break;
3384
3385                 case TS:
3386                         if (!decodets(value, &lfp))
3387                                 output_raw = '?';
3388                         else
3389                                 output(fp, name, prettydate(&lfp));
3390                         break;
3391
3392                 case HA:        /* fallthru */
3393                 case NA:
3394                         if (!decodenetnum(value, &hval)) {
3395                                 output_raw = '?';
3396                         } else if (fmt == HA){
3397                                 output(fp, name, nntohost(&hval));
3398                         } else {
3399                                 output(fp, name, stoa(&hval));
3400                         }
3401                         break;
3402
3403                 case RF:
3404                         if (decodenetnum(value, &hval)) {
3405                                 if (ISREFCLOCKADR(&hval))
3406                                         output(fp, name,
3407                                                refnumtoa(&hval));
3408                                 else
3409                                         output(fp, name, stoa(&hval));
3410                         } else if (strlen(value) <= 4) {
3411                                 output(fp, name, value);
3412                         } else {
3413                                 output_raw = '?';
3414                         }
3415                         break;
3416
3417                 case LP:
3418                         if (!decodeuint(value, &uval) || uval > 3) {
3419                                 output_raw = '?';
3420                         } else {
3421                                 b[0] = (0x2 & uval)
3422                                            ? '1'
3423                                            : '0';
3424                                 b[1] = (0x1 & uval)
3425                                            ? '1'
3426                                            : '0';
3427                                 b[2] = '\0';
3428                                 output(fp, name, b);
3429                         }
3430                         break;
3431
3432                 case OC:
3433                         if (!decodeuint(value, &uval)) {
3434                                 output_raw = '?';
3435                         } else {
3436                                 snprintf(b, sizeof(b), "%03lo", uval);
3437                                 output(fp, name, b);
3438                         }
3439                         break;
3440
3441                 case AR:
3442                         if (!decodearr(value, &narr, lfparr))
3443                                 output_raw = '?';
3444                         else
3445                                 outputarr(fp, name, narr, lfparr);
3446                         break;
3447
3448                 case FX:
3449                         if (!decodeuint(value, &uval))
3450                                 output_raw = '?';
3451                         else
3452                                 output(fp, name, tstflags(uval));
3453                         break;
3454
3455                 default:
3456                         fprintf(stderr, "Internal error in cookedprint, %s=%s, fmt %d\n",
3457                                 name, value, fmt);
3458                         output_raw = '?';
3459                         break;
3460                 }
3461
3462                 if (output_raw != 0) {
3463                         /* TALOS-CAN-0063: avoid buffer overrun */
3464                         atoascii(name, MAXVARLEN, bn, sizeof(bn));
3465                         if (output_raw != '*') {
3466                                 atoascii(value, MAXVALLEN,
3467                                          bv, sizeof(bv) - 1);
3468                                 len = strlen(bv);
3469                                 bv[len] = output_raw;
3470                                 bv[len+1] = '\0';
3471                         } else {
3472                                 atoascii(value, MAXVALLEN,
3473                                          bv, sizeof(bv));
3474                         }
3475                         output(fp, bn, bv);
3476                 }
3477         }
3478         endoutput(fp);
3479 }
3480
3481
3482 /*
3483  * sortassoc - sort associations in the cache into ascending order
3484  */
3485 void
3486 sortassoc(void)
3487 {
3488         if (numassoc > 1)
3489                 qsort(assoc_cache, (size_t)numassoc,
3490                       sizeof(assoc_cache[0]), &assoccmp);
3491 }
3492
3493
3494 /*
3495  * assoccmp - compare two associations
3496  */
3497 static int
3498 assoccmp(
3499         const void *t1,
3500         const void *t2
3501         )
3502 {
3503         const struct association *ass1 = t1;
3504         const struct association *ass2 = t2;
3505
3506         if (ass1->assid < ass2->assid)
3507                 return -1;
3508         if (ass1->assid > ass2->assid)
3509                 return 1;
3510         return 0;
3511 }
3512
3513
3514 /*
3515  * grow_assoc_cache() - enlarge dynamic assoc_cache array
3516  *
3517  * The strategy is to add an assumed 4k page size at a time, leaving
3518  * room for malloc() bookkeeping overhead equivalent to 4 pointers.
3519  */
3520 void
3521 grow_assoc_cache(void)
3522 {
3523         static size_t   prior_sz;
3524         size_t          new_sz;
3525
3526         new_sz = prior_sz + 4 * 1024;
3527         if (0 == prior_sz) {
3528                 new_sz -= 4 * sizeof(void *);
3529         }
3530         assoc_cache = erealloc_zero(assoc_cache, new_sz, prior_sz); 
3531         prior_sz = new_sz;
3532         assoc_cache_slots = (u_int)(new_sz / sizeof(assoc_cache[0]));
3533 }
3534
3535
3536 /*
3537  * ntpq_custom_opt_handler - autoopts handler for -c and -p
3538  *
3539  * By default, autoopts loses the relative order of -c and -p options
3540  * on the command line.  This routine replaces the default handler for
3541  * those routines and builds a list of commands to execute preserving
3542  * the order.
3543  */
3544 void
3545 ntpq_custom_opt_handler(
3546         tOptions *pOptions,
3547         tOptDesc *pOptDesc
3548         )
3549 {
3550         switch (pOptDesc->optValue) {
3551
3552         default:
3553                 fprintf(stderr,
3554                         "ntpq_custom_opt_handler unexpected option '%c' (%d)\n",
3555                         pOptDesc->optValue, pOptDesc->optValue);
3556                 exit(1);
3557
3558         case 'c':
3559                 ADDCMD(pOptDesc->pzLastArg);
3560                 break;
3561
3562         case 'p':
3563                 ADDCMD("peers");
3564                 break;
3565         }
3566 }
3567 /*
3568  * Obtain list of digest names
3569  */
3570
3571 #ifdef OPENSSL
3572 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3573 struct hstate {
3574    char *list;
3575    const char **seen;
3576    int idx;
3577 };
3578 #define K_PER_LINE 8
3579 #define K_NL_PFX_STR "\n    "
3580 #define K_DELIM_STR ", "
3581 static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg )
3582 {
3583     size_t len, n;
3584     const char *name, *cp, **seen;
3585     struct hstate *hstate = arg;
3586     EVP_MD_CTX *ctx;
3587     u_int digest_len;
3588     u_char digest[EVP_MAX_MD_SIZE];
3589
3590     if (!m)
3591         return; /* Ignore aliases */
3592
3593     name = EVP_MD_name(m);
3594
3595     /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */
3596
3597     for( cp = name; *cp; cp++ ) {
3598         if( islower(*cp) )
3599             return;
3600     }
3601     len = (cp - name) + 1;
3602
3603     /* There are duplicates.  Discard if name has been seen. */
3604
3605     for (seen = hstate->seen; *seen; seen++)
3606         if (!strcmp(*seen, name))
3607             return;
3608     n = (seen - hstate->seen) + 2;
3609     hstate->seen = erealloc(hstate->seen, n * sizeof(*seen));
3610     hstate->seen[n-2] = name;
3611     hstate->seen[n-1] = NULL;
3612
3613     /* Discard MACs that NTP won't accept.
3614      * Keep this consistent with keytype_from_text() in ssl_init.c.
3615      */
3616
3617     ctx = EVP_MD_CTX_new();
3618     EVP_DigestInit(ctx, EVP_get_digestbyname(name));
3619     EVP_DigestFinal(ctx, digest, &digest_len);
3620     EVP_MD_CTX_free(ctx);
3621     if (digest_len > (MAX_MAC_LEN - sizeof(keyid_t)))
3622         return;
3623
3624     if (hstate->list != NULL)
3625         len += strlen(hstate->list);
3626     len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR);
3627
3628     if (hstate->list == NULL) {
3629         hstate->list = (char *)emalloc(len);
3630         hstate->list[0] = '\0';
3631     } else
3632         hstate->list = (char *)erealloc(hstate->list, len);
3633
3634     sprintf(hstate->list + strlen(hstate->list), "%s%s",
3635             ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR),
3636             name);
3637     if (hstate->idx >= K_PER_LINE)
3638         hstate->idx = 1;
3639     else
3640         hstate->idx++;
3641 }
3642 # endif
3643 #endif
3644
3645 static char *list_digest_names(void)
3646 {
3647     char *list = NULL;
3648
3649 #ifdef OPENSSL
3650 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3651     struct hstate hstate = { NULL, NULL, K_PER_LINE+1 };
3652
3653     hstate.seen = (const char **) emalloc_zero(1*sizeof( const char * )); // replaces -> calloc(1, sizeof( const char * ));
3654
3655     INIT_SSL();
3656     EVP_MD_do_all_sorted(list_md_fn, &hstate);
3657     list = hstate.list;
3658     free(hstate.seen);
3659 # else
3660     list = (char *)emalloc(sizeof("md5, others (upgrade to OpenSSL-1.0 for full list)"));
3661     strcpy(list, "md5, others (upgrade to OpenSSL-1.0 for full list)");
3662 # endif
3663 #else
3664     list = (char *)emalloc(sizeof("md5"));
3665     strcpy(list, "md5");
3666 #endif
3667
3668     return list;
3669 }
3670
3671 #define CTRLC_STACK_MAX 4
3672 static volatile size_t          ctrlc_stack_len = 0;
3673 static volatile Ctrl_C_Handler  ctrlc_stack[CTRLC_STACK_MAX];
3674
3675
3676
3677 int/*BOOL*/
3678 push_ctrl_c_handler(
3679         Ctrl_C_Handler func
3680         )
3681 {
3682         size_t size = ctrlc_stack_len;
3683         if (func && (size < CTRLC_STACK_MAX)) {
3684                 ctrlc_stack[size] = func;
3685                 ctrlc_stack_len = size + 1;
3686                 return TRUE;
3687         }
3688         return FALSE;   
3689 }
3690
3691 int/*BOOL*/
3692 pop_ctrl_c_handler(
3693         Ctrl_C_Handler func
3694         )
3695 {
3696         size_t size = ctrlc_stack_len;
3697         if (size) {
3698                 --size;
3699                 if (func == NULL || func == ctrlc_stack[size]) {
3700                         ctrlc_stack_len = size;
3701                         return TRUE;
3702                 }
3703         }
3704         return FALSE;
3705 }
3706
3707 static void
3708 on_ctrlc(void)
3709 {
3710         size_t size = ctrlc_stack_len;
3711         while (size)
3712                 if ((*ctrlc_stack[--size])())
3713                         break;
3714 }
3715
3716 static int
3717 my_easprintf(
3718         char **         ppinto,
3719         const char *    fmt   ,
3720         ...
3721         )
3722 {
3723         va_list va;
3724         int     prc;
3725         size_t  len = 128;
3726         char *  buf = emalloc(len);
3727
3728   again:
3729         /* Note: we expect the memory allocation to fail long before the
3730          * increment in buffer size actually overflows.
3731          */
3732         buf = (buf) ? erealloc(buf, len) : emalloc(len);
3733
3734         va_start(va, fmt);
3735         prc = vsnprintf(buf, len, fmt, va);
3736         va_end(va);
3737
3738         if (prc < 0) {
3739                 /* might be very old vsnprintf. Or actually MSVC... */
3740                 len += len >> 1;
3741                 goto again;
3742         }
3743         if ((size_t)prc >= len) {
3744                 /* at least we have the proper size now... */
3745                 len = (size_t)prc + 1;
3746                 goto again;
3747         }
3748         if ((size_t)prc < (len - 32))
3749                 buf = erealloc(buf, (size_t)prc + 1);
3750         *ppinto = buf;
3751         return prc;
3752 }