]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/ntp/ntpq/ntpq.c
Fix multiple vulnerabilities of ntp. [SA-17:03]
[FreeBSD/releng/10.3.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 size_t 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         size_t 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         /* every line shows at most 16 bytes, so we need a buffer of
780          *   4 * 16 (2 xdigits, 1 char, one sep for xdigits)
781          * + 2 * 1  (block separators)
782          * + <LF> + <NUL>
783          *---------------
784          *  68 bytes
785          */
786         static const char s_xdig[16] = "0123456789ABCDEF";
787
788         char lbuf[68];
789         int  ch, rowlen;
790         const u_char * cdata = data;
791         char *xptr, *pptr;
792
793         while (len) {
794                 memset(lbuf, ' ', sizeof(lbuf));
795                 xptr = lbuf;
796                 pptr = lbuf + 3*16 + 2;
797
798                 rowlen = (len > 16) ? 16 : (int)len;
799                 len -= rowlen;
800                 
801                 do {
802                         ch = *cdata++;
803                         
804                         *xptr++ = s_xdig[ch >> 4  ];
805                         *xptr++ = s_xdig[ch & 0x0F];
806                         if (++xptr == lbuf + 3*8)
807                                 ++xptr;
808
809                         *pptr++ = isprint(ch) ? (char)ch : '.';
810                 } while (--rowlen);
811
812                 *pptr++ = '\n';
813                 *pptr   = '\0';
814                 fputs(lbuf, stdout);
815         }
816 }
817
818
819 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
820 /*
821  * sendpkt - send a packet to the remote host
822  */
823 static int
824 sendpkt(
825         void *  xdata,
826         size_t  xdatalen
827         )
828 {
829         if (debug >= 3)
830                 printf("Sending %zu octets\n", xdatalen);
831
832         if (send(sockfd, xdata, xdatalen, 0) == -1) {
833                 warning("write to %s failed", currenthost);
834                 return -1;
835         }
836
837         if (debug >= 4) {
838                 printf("Request packet:\n");
839                 dump_hex_printable(xdata, xdatalen);
840         }
841         return 0;
842 }
843
844 /*
845  * getresponse - get a (series of) response packet(s) and return the data
846  */
847 static int
848 getresponse(
849         int opcode,
850         int associd,
851         u_short *rstatus,
852         size_t *rsize,
853         const char **rdata,
854         int timeo
855         )
856 {
857         struct ntp_control rpkt;
858         struct sock_timeval tvo;
859         u_short offsets[MAXFRAGS+1];
860         u_short counts[MAXFRAGS+1];
861         u_short offset;
862         u_short count;
863         size_t numfrags;
864         size_t f;
865         size_t ff;
866         int seenlastfrag;
867         int shouldbesize;
868         fd_set fds;
869         int n;
870         int errcode;
871         /* absolute timeout checks. Not 'time_t' by intention! */
872         uint32_t tobase;        /* base value for timeout */
873         uint32_t tospan;        /* timeout span (max delay) */
874         uint32_t todiff;        /* current delay */
875
876         memset(offsets, 0, sizeof(offsets));
877         memset(counts , 0, sizeof(counts ));
878         
879         /*
880          * This is pretty tricky.  We may get between 1 and MAXFRAG packets
881          * back in response to the request.  We peel the data out of
882          * each packet and collect it in one long block.  When the last
883          * packet in the sequence is received we'll know how much data we
884          * should have had.  Note we use one long time out, should reconsider.
885          */
886         *rsize = 0;
887         if (rstatus)
888                 *rstatus = 0;
889         *rdata = (char *)pktdata;
890
891         numfrags = 0;
892         seenlastfrag = 0;
893
894         tobase = (uint32_t)time(NULL);
895         
896         FD_ZERO(&fds);
897
898         /*
899          * Loop until we have an error or a complete response.  Nearly all
900          * code paths to loop again use continue.
901          */
902         for (;;) {
903
904                 if (numfrags == 0)
905                         tvo = tvout;
906                 else
907                         tvo = tvsout;
908                 tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
909
910                 FD_SET(sockfd, &fds);
911                 n = select(sockfd+1, &fds, NULL, NULL, &tvo);
912                 if (n == -1) {
913 #if !defined(SYS_WINNT) && defined(EINTR)
914                         /* Windows does not know about EINTR (until very
915                          * recently) and the handling of console events
916                          * is *very* different from POSIX/UNIX signal
917                          * handling anyway.
918                          *
919                          * Under non-windows targets we map EINTR as
920                          * 'last packet was received' and try to exit
921                          * the receive sequence.
922                          */
923                         if (errno == EINTR) {
924                                 seenlastfrag = 1;
925                                 goto maybe_final;
926                         }
927 #endif
928                         warning("select fails");
929                         return -1;
930                 }
931
932                 /*
933                  * Check if this is already too late. Trash the data and
934                  * fake a timeout if this is so.
935                  */
936                 todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
937                 if ((n > 0) && (todiff > tospan)) {
938                         n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
939                         n -= n; /* faked timeout return from 'select()',
940                                  * execute RMW cycle on 'n'
941                                  */
942                 }
943                 
944                 if (n <= 0) {
945                         /*
946                          * Timed out.  Return what we have
947                          */
948                         if (numfrags == 0) {
949                                 if (timeo)
950                                         fprintf(stderr,
951                                                 "%s: timed out, nothing received\n",
952                                                 currenthost);
953                                 return ERR_TIMEOUT;
954                         }
955                         if (timeo)
956                                 fprintf(stderr,
957                                         "%s: timed out with incomplete data\n",
958                                         currenthost);
959                         if (debug) {
960                                 fprintf(stderr,
961                                         "ERR_INCOMPLETE: Received fragments:\n");
962                                 for (f = 0; f < numfrags; f++)
963                                         fprintf(stderr,
964                                                 "%2u: %5d %5d\t%3d octets\n",
965                                                 (u_int)f, offsets[f],
966                                                 offsets[f] +
967                                                 counts[f],
968                                                 counts[f]);
969                                 fprintf(stderr,
970                                         "last fragment %sreceived\n",
971                                         (seenlastfrag)
972                                             ? ""
973                                             : "not ");
974                         }
975                         return ERR_INCOMPLETE;
976                 }
977
978                 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
979                 if (n < 0) {
980                         warning("read");
981                         return -1;
982                 }
983
984                 if (debug >= 4) {
985                         printf("Response packet:\n");
986                         dump_hex_printable(&rpkt, n);
987                 }
988
989                 /*
990                  * Check for format errors.  Bug proofing.
991                  */
992                 if (n < (int)CTL_HEADER_LEN) {
993                         if (debug)
994                                 printf("Short (%d byte) packet received\n", n);
995                         continue;
996                 }
997                 if (PKT_VERSION(rpkt.li_vn_mode) > NTP_VERSION
998                     || PKT_VERSION(rpkt.li_vn_mode) < NTP_OLDVERSION) {
999                         if (debug)
1000                                 printf("Packet received with version %d\n",
1001                                        PKT_VERSION(rpkt.li_vn_mode));
1002                         continue;
1003                 }
1004                 if (PKT_MODE(rpkt.li_vn_mode) != MODE_CONTROL) {
1005                         if (debug)
1006                                 printf("Packet received with mode %d\n",
1007                                        PKT_MODE(rpkt.li_vn_mode));
1008                         continue;
1009                 }
1010                 if (!CTL_ISRESPONSE(rpkt.r_m_e_op)) {
1011                         if (debug)
1012                                 printf("Received request packet, wanted response\n");
1013                         continue;
1014                 }
1015
1016                 /*
1017                  * Check opcode and sequence number for a match.
1018                  * Could be old data getting to us.
1019                  */
1020                 if (ntohs(rpkt.sequence) != sequence) {
1021                         if (debug)
1022                                 printf("Received sequnce number %d, wanted %d\n",
1023                                        ntohs(rpkt.sequence), sequence);
1024                         continue;
1025                 }
1026                 if (CTL_OP(rpkt.r_m_e_op) != opcode) {
1027                         if (debug)
1028                             printf(
1029                                     "Received opcode %d, wanted %d (sequence number okay)\n",
1030                                     CTL_OP(rpkt.r_m_e_op), opcode);
1031                         continue;
1032                 }
1033
1034                 /*
1035                  * Check the error code.  If non-zero, return it.
1036                  */
1037                 if (CTL_ISERROR(rpkt.r_m_e_op)) {
1038                         errcode = (ntohs(rpkt.status) >> 8) & 0xff;
1039                         if (CTL_ISMORE(rpkt.r_m_e_op))
1040                                 TRACE(1, ("Error code %d received on not-final packet\n",
1041                                           errcode));
1042                         if (errcode == CERR_UNSPEC)
1043                                 return ERR_UNSPEC;
1044                         return errcode;
1045                 }
1046
1047                 /*
1048                  * Check the association ID to make sure it matches what
1049                  * we sent.
1050                  */
1051                 if (ntohs(rpkt.associd) != associd) {
1052                         TRACE(1, ("Association ID %d doesn't match expected %d\n",
1053                                   ntohs(rpkt.associd), associd));
1054                         /*
1055                          * Hack for silly fuzzballs which, at the time of writing,
1056                          * return an assID of sys.peer when queried for system variables.
1057                          */
1058 #ifdef notdef
1059                         continue;
1060 #endif
1061                 }
1062
1063                 /*
1064                  * Collect offset and count.  Make sure they make sense.
1065                  */
1066                 offset = ntohs(rpkt.offset);
1067                 count = ntohs(rpkt.count);
1068
1069                 /*
1070                  * validate received payload size is padded to next 32-bit
1071                  * boundary and no smaller than claimed by rpkt.count
1072                  */
1073                 if (n & 0x3) {
1074                         TRACE(1, ("Response packet not padded, size = %d\n",
1075                                   n));
1076                         continue;
1077                 }
1078
1079                 shouldbesize = (CTL_HEADER_LEN + count + 3) & ~3;
1080
1081                 if (n < shouldbesize) {
1082                         printf("Response packet claims %u octets payload, above %ld received\n",
1083                                count, (long)(n - CTL_HEADER_LEN));
1084                         return ERR_INCOMPLETE;
1085                 }
1086
1087                 if (debug >= 3 && shouldbesize > n) {
1088                         u_int32 key;
1089                         u_int32 *lpkt;
1090                         int maclen;
1091
1092                         /*
1093                          * Usually we ignore authentication, but for debugging purposes
1094                          * we watch it here.
1095                          */
1096                         /* round to 8 octet boundary */
1097                         shouldbesize = (shouldbesize + 7) & ~7;
1098
1099                         maclen = n - shouldbesize;
1100                         if (maclen >= (int)MIN_MAC_LEN) {
1101                                 printf(
1102                                         "Packet shows signs of authentication (total %d, data %d, mac %d)\n",
1103                                         n, shouldbesize, maclen);
1104                                 lpkt = (u_int32 *)&rpkt;
1105                                 printf("%08lx %08lx %08lx %08lx %08lx %08lx\n",
1106                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 3]),
1107                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 2]),
1108                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 1]),
1109                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32)]),
1110                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 1]),
1111                                        (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 2]));
1112                                 key = ntohl(lpkt[(n - maclen) / sizeof(u_int32)]);
1113                                 printf("Authenticated with keyid %lu\n", (u_long)key);
1114                                 if (key != 0 && key != info_auth_keyid) {
1115                                         printf("We don't know that key\n");
1116                                 } else {
1117                                         if (authdecrypt(key, (u_int32 *)&rpkt,
1118                                             n - maclen, maclen)) {
1119                                                 printf("Auth okay!\n");
1120                                         } else {
1121                                                 printf("Auth failed!\n");
1122                                         }
1123                                 }
1124                         }
1125                 }
1126
1127                 TRACE(2, ("Got packet, size = %d\n", n));
1128                 if (count > (n - CTL_HEADER_LEN)) {
1129                         TRACE(1, ("Received count of %u octets, data in packet is %ld\n",
1130                                   count, (long)n - CTL_HEADER_LEN));
1131                         continue;
1132                 }
1133                 if (count == 0 && CTL_ISMORE(rpkt.r_m_e_op)) {
1134                         TRACE(1, ("Received count of 0 in non-final fragment\n"));
1135                         continue;
1136                 }
1137                 if (offset + count > sizeof(pktdata)) {
1138                         TRACE(1, ("Offset %u, count %u, too big for buffer\n",
1139                                   offset, count));
1140                         return ERR_TOOMUCH;
1141                 }
1142                 if (seenlastfrag && !CTL_ISMORE(rpkt.r_m_e_op)) {
1143                         TRACE(1, ("Received second last fragment packet\n"));
1144                         continue;
1145                 }
1146
1147                 /*
1148                  * So far, so good.  Record this fragment, making sure it doesn't
1149                  * overlap anything.
1150                  */
1151                 TRACE(2, ("Packet okay\n"));
1152
1153                 if (numfrags > (MAXFRAGS - 1)) {
1154                         TRACE(2, ("Number of fragments exceeds maximum %d\n",
1155                                   MAXFRAGS - 1));
1156                         return ERR_TOOMUCH;
1157                 }
1158
1159                 /*
1160                  * Find the position for the fragment relative to any
1161                  * previously received.
1162                  */
1163                 for (f = 0;
1164                      f < numfrags && offsets[f] < offset;
1165                      f++) {
1166                         /* empty body */ ;
1167                 }
1168
1169                 if (f < numfrags && offset == offsets[f]) {
1170                         TRACE(1, ("duplicate %u octets at %u ignored, prior %u at %u\n",
1171                                   count, offset, counts[f], offsets[f]));
1172                         continue;
1173                 }
1174
1175                 if (f > 0 && (offsets[f-1] + counts[f-1]) > offset) {
1176                         TRACE(1, ("received frag at %u overlaps with %u octet frag at %u\n",
1177                                   offset, counts[f-1], offsets[f-1]));
1178                         continue;
1179                 }
1180
1181                 if (f < numfrags && (offset + count) > offsets[f]) {
1182                         TRACE(1, ("received %u octet frag at %u overlaps with frag at %u\n",
1183                                   count, offset, offsets[f]));
1184                         continue;
1185                 }
1186
1187                 for (ff = numfrags; ff > f; ff--) {
1188                         offsets[ff] = offsets[ff-1];
1189                         counts[ff] = counts[ff-1];
1190                 }
1191                 offsets[f] = offset;
1192                 counts[f] = count;
1193                 numfrags++;
1194
1195                 /*
1196                  * Got that stuffed in right.  Figure out if this was the last.
1197                  * Record status info out of the last packet.
1198                  */
1199                 if (!CTL_ISMORE(rpkt.r_m_e_op)) {
1200                         seenlastfrag = 1;
1201                         if (rstatus != 0)
1202                                 *rstatus = ntohs(rpkt.status);
1203                 }
1204
1205                 /*
1206                  * Copy the data into the data buffer, and bump the
1207                  * timout base in case we need more.
1208                  */
1209                 memcpy((char *)pktdata + offset, &rpkt.u, count);
1210                 tobase = (uint32_t)time(NULL);
1211                 
1212                 /*
1213                  * If we've seen the last fragment, look for holes in the sequence.
1214                  * If there aren't any, we're done.
1215                  */
1216 #if !defined(SYS_WINNT) && defined(EINTR)
1217                 maybe_final:
1218 #endif
1219
1220                 if (seenlastfrag && offsets[0] == 0) {
1221                         for (f = 1; f < numfrags; f++)
1222                                 if (offsets[f-1] + counts[f-1] !=
1223                                     offsets[f])
1224                                         break;
1225                         if (f == numfrags) {
1226                                 *rsize = offsets[f-1] + counts[f-1];
1227                                 TRACE(1, ("%lu packets reassembled into response\n",
1228                                           (u_long)numfrags));
1229                                 return 0;
1230                         }
1231                 }
1232         }  /* giant for (;;) collecting response packets */
1233 }  /* getresponse() */
1234
1235
1236 /*
1237  * sendrequest - format and send a request packet
1238  */
1239 static int
1240 sendrequest(
1241         int opcode,
1242         associd_t associd,
1243         int auth,
1244         size_t qsize,
1245         const char *qdata
1246         )
1247 {
1248         struct ntp_control qpkt;
1249         size_t  pktsize;
1250         u_long  key_id;
1251         char *  pass;
1252         size_t  maclen;
1253
1254         /*
1255          * Check to make sure the data will fit in one packet
1256          */
1257         if (qsize > CTL_MAX_DATA_LEN) {
1258                 fprintf(stderr,
1259                         "***Internal error!  qsize (%zu) too large\n",
1260                         qsize);
1261                 return 1;
1262         }
1263
1264         /*
1265          * Fill in the packet
1266          */
1267         qpkt.li_vn_mode = PKT_LI_VN_MODE(0, pktversion, MODE_CONTROL);
1268         qpkt.r_m_e_op = (u_char)(opcode & CTL_OP_MASK);
1269         qpkt.sequence = htons(sequence);
1270         qpkt.status = 0;
1271         qpkt.associd = htons((u_short)associd);
1272         qpkt.offset = 0;
1273         qpkt.count = htons((u_short)qsize);
1274
1275         pktsize = CTL_HEADER_LEN;
1276
1277         /*
1278          * If we have data, copy and pad it out to a 32-bit boundary.
1279          */
1280         if (qsize > 0) {
1281                 memcpy(&qpkt.u, qdata, (size_t)qsize);
1282                 pktsize += qsize;
1283                 while (pktsize & (sizeof(u_int32) - 1)) {
1284                         qpkt.u.data[qsize++] = 0;
1285                         pktsize++;
1286                 }
1287         }
1288
1289         /*
1290          * If it isn't authenticated we can just send it.  Otherwise
1291          * we're going to have to think about it a little.
1292          */
1293         if (!auth && !always_auth) {
1294                 return sendpkt(&qpkt, pktsize);
1295         }
1296
1297         /*
1298          * Pad out packet to a multiple of 8 octets to be sure
1299          * receiver can handle it.
1300          */
1301         while (pktsize & 7) {
1302                 qpkt.u.data[qsize++] = 0;
1303                 pktsize++;
1304         }
1305
1306         /*
1307          * Get the keyid and the password if we don't have one.
1308          */
1309         if (info_auth_keyid == 0) {
1310                 key_id = getkeyid("Keyid: ");
1311                 if (key_id == 0 || key_id > NTP_MAXKEY) {
1312                         fprintf(stderr,
1313                                 "Invalid key identifier\n");
1314                         return 1;
1315                 }
1316                 info_auth_keyid = key_id;
1317         }
1318         if (!authistrusted(info_auth_keyid)) {
1319                 pass = getpass_keytype(info_auth_keytype);
1320                 if ('\0' == pass[0]) {
1321                         fprintf(stderr, "Invalid password\n");
1322                         return 1;
1323                 }
1324                 authusekey(info_auth_keyid, info_auth_keytype,
1325                            (u_char *)pass);
1326                 authtrust(info_auth_keyid, 1);
1327         }
1328
1329         /*
1330          * Do the encryption.
1331          */
1332         maclen = authencrypt(info_auth_keyid, (void *)&qpkt, pktsize);
1333         if (!maclen) {
1334                 fprintf(stderr, "Key not found\n");
1335                 return 1;
1336         } else if ((size_t)maclen != (info_auth_hashlen + sizeof(keyid_t))) {
1337                 fprintf(stderr,
1338                         "%zu octet MAC, %zu expected with %zu octet digest\n",
1339                         maclen, (info_auth_hashlen + sizeof(keyid_t)),
1340                         info_auth_hashlen);
1341                 return 1;
1342         }
1343
1344         return sendpkt((char *)&qpkt, pktsize + maclen);
1345 }
1346
1347
1348 /*
1349  * show_error_msg - display the error text for a mode 6 error response.
1350  */
1351 void
1352 show_error_msg(
1353         int             m6resp,
1354         associd_t       associd
1355         )
1356 {
1357         if (numhosts > 1)
1358                 fprintf(stderr, "server=%s ", currenthost);
1359
1360         switch (m6resp) {
1361
1362         case CERR_BADFMT:
1363                 fprintf(stderr,
1364                     "***Server reports a bad format request packet\n");
1365                 break;
1366
1367         case CERR_PERMISSION:
1368                 fprintf(stderr,
1369                     "***Server disallowed request (authentication?)\n");
1370                 break;
1371
1372         case CERR_BADOP:
1373                 fprintf(stderr,
1374                     "***Server reports a bad opcode in request\n");
1375                 break;
1376
1377         case CERR_BADASSOC:
1378                 fprintf(stderr,
1379                     "***Association ID %d unknown to server\n",
1380                     associd);
1381                 break;
1382
1383         case CERR_UNKNOWNVAR:
1384                 fprintf(stderr,
1385                     "***A request variable unknown to the server\n");
1386                 break;
1387
1388         case CERR_BADVALUE:
1389                 fprintf(stderr,
1390                     "***Server indicates a request variable was bad\n");
1391                 break;
1392
1393         case ERR_UNSPEC:
1394                 fprintf(stderr,
1395                     "***Server returned an unspecified error\n");
1396                 break;
1397
1398         case ERR_TIMEOUT:
1399                 fprintf(stderr, "***Request timed out\n");
1400                 break;
1401
1402         case ERR_INCOMPLETE:
1403                 fprintf(stderr,
1404                     "***Response from server was incomplete\n");
1405                 break;
1406
1407         case ERR_TOOMUCH:
1408                 fprintf(stderr,
1409                     "***Buffer size exceeded for returned data\n");
1410                 break;
1411
1412         default:
1413                 fprintf(stderr,
1414                     "***Server returns unknown error code %d\n",
1415                     m6resp);
1416         }
1417 }
1418
1419 /*
1420  * doquery - send a request and process the response, displaying
1421  *           error messages for any error responses.
1422  */
1423 int
1424 doquery(
1425         int opcode,
1426         associd_t associd,
1427         int auth,
1428         size_t qsize,
1429         const char *qdata,
1430         u_short *rstatus,
1431         size_t *rsize,
1432         const char **rdata
1433         )
1434 {
1435         return doqueryex(opcode, associd, auth, qsize, qdata, rstatus,
1436                          rsize, rdata, FALSE);
1437 }
1438
1439
1440 /*
1441  * doqueryex - send a request and process the response, optionally
1442  *             displaying error messages for any error responses.
1443  */
1444 int
1445 doqueryex(
1446         int opcode,
1447         associd_t associd,
1448         int auth,
1449         size_t qsize,
1450         const char *qdata,
1451         u_short *rstatus,
1452         size_t *rsize,
1453         const char **rdata,
1454         int quiet
1455         )
1456 {
1457         int res;
1458         int done;
1459
1460         /*
1461          * Check to make sure host is open
1462          */
1463         if (!havehost) {
1464                 fprintf(stderr, "***No host open, use `host' command\n");
1465                 return -1;
1466         }
1467
1468         done = 0;
1469         sequence++;
1470
1471     again:
1472         /*
1473          * send a request
1474          */
1475         res = sendrequest(opcode, associd, auth, qsize, qdata);
1476         if (res != 0)
1477                 return res;
1478
1479         /*
1480          * Get the response.  If we got a standard error, print a message
1481          */
1482         res = getresponse(opcode, associd, rstatus, rsize, rdata, done);
1483
1484         if (res > 0) {
1485                 if (!done && (res == ERR_TIMEOUT || res == ERR_INCOMPLETE)) {
1486                         if (res == ERR_INCOMPLETE) {
1487                                 /*
1488                                  * better bump the sequence so we don't
1489                                  * get confused about differing fragments.
1490                                  */
1491                                 sequence++;
1492                         }
1493                         done = 1;
1494                         goto again;
1495                 }
1496                 if (!quiet)
1497                         show_error_msg(res, associd);
1498
1499         }
1500         return res;
1501 }
1502
1503
1504 #ifndef BUILD_AS_LIB
1505 /*
1506  * getcmds - read commands from the standard input and execute them
1507  */
1508 static void
1509 getcmds(void)
1510 {
1511         char *  line;
1512         int     count;
1513
1514         ntp_readline_init(interactive ? prompt : NULL);
1515
1516         for (;;) {
1517                 line = ntp_readline(&count);
1518                 if (NULL == line)
1519                         break;
1520                 docmd(line);
1521                 free(line);
1522         }
1523
1524         ntp_readline_uninit();
1525 }
1526 #endif /* !BUILD_AS_LIB */
1527
1528
1529 #if !defined(SYS_WINNT) && !defined(BUILD_AS_LIB)
1530 /*
1531  * abortcmd - catch interrupts and abort the current command
1532  */
1533 static int
1534 abortcmd(void)
1535 {
1536         if (current_output == stdout)
1537                 (void) fflush(stdout);
1538         putc('\n', stderr);
1539         (void) fflush(stderr);
1540         if (jump) {
1541                 jump = 0;
1542                 longjmp(interrupt_buf, 1);
1543         }
1544         return TRUE;
1545 }
1546 #endif  /* !SYS_WINNT && !BUILD_AS_LIB */
1547
1548
1549 #ifndef BUILD_AS_LIB
1550 /*
1551  * docmd - decode the command line and execute a command
1552  */
1553 static void
1554 docmd(
1555         const char *cmdline
1556         )
1557 {
1558         char *tokens[1+MAXARGS+2];
1559         struct parse pcmd;
1560         int ntok;
1561         static int i;
1562         struct xcmd *xcmd;
1563
1564         /*
1565          * Tokenize the command line.  If nothing on it, return.
1566          */
1567         tokenize(cmdline, tokens, &ntok);
1568         if (ntok == 0)
1569             return;
1570
1571         /*
1572          * Find the appropriate command description.
1573          */
1574         i = findcmd(tokens[0], builtins, opcmds, &xcmd);
1575         if (i == 0) {
1576                 (void) fprintf(stderr, "***Command `%s' unknown\n",
1577                                tokens[0]);
1578                 return;
1579         } else if (i >= 2) {
1580                 (void) fprintf(stderr, "***Command `%s' ambiguous\n",
1581                                tokens[0]);
1582                 return;
1583         }
1584
1585         /* Warn about ignored extra args */
1586         for (i = MAXARGS + 1; i < ntok ; ++i) {
1587                 fprintf(stderr, "***Extra arg `%s' ignored\n", tokens[i]);
1588         }
1589
1590         /*
1591          * Save the keyword, then walk through the arguments, interpreting
1592          * as we go.
1593          */
1594         pcmd.keyword = tokens[0];
1595         pcmd.nargs = 0;
1596         for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) {
1597                 if ((i+1) >= ntok) {
1598                         if (!(xcmd->arg[i] & OPT)) {
1599                                 printusage(xcmd, stderr);
1600                                 return;
1601                         }
1602                         break;
1603                 }
1604                 if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>'))
1605                         break;
1606                 if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i]))
1607                         return;
1608                 pcmd.nargs++;
1609         }
1610
1611         i++;
1612         if (i < ntok && *tokens[i] == '>') {
1613                 char *fname;
1614
1615                 if (*(tokens[i]+1) != '\0')
1616                         fname = tokens[i]+1;
1617                 else if ((i+1) < ntok)
1618                         fname = tokens[i+1];
1619                 else {
1620                         (void) fprintf(stderr, "***No file for redirect\n");
1621                         return;
1622                 }
1623
1624                 current_output = fopen(fname, "w");
1625                 if (current_output == NULL) {
1626                         (void) fprintf(stderr, "***Error opening %s: ", fname);
1627                         perror("");
1628                         return;
1629                 }
1630                 i = 1;          /* flag we need a close */
1631         } else {
1632                 current_output = stdout;
1633                 i = 0;          /* flag no close */
1634         }
1635
1636         if (interactive && setjmp(interrupt_buf)) {
1637                 jump = 0;
1638                 return;
1639         } else {
1640                 jump++;
1641                 (xcmd->handler)(&pcmd, current_output);
1642                 jump = 0;       /* HMS: 961106: was after fclose() */
1643                 if (i) (void) fclose(current_output);
1644         }
1645
1646         return;
1647 }
1648
1649
1650 /*
1651  * tokenize - turn a command line into tokens
1652  *
1653  * SK: Modified to allow a quoted string
1654  *
1655  * HMS: If the first character of the first token is a ':' then (after
1656  * eating inter-token whitespace) the 2nd token is the rest of the line.
1657  */
1658
1659 static void
1660 tokenize(
1661         const char *line,
1662         char **tokens,
1663         int *ntok
1664         )
1665 {
1666         register const char *cp;
1667         register char *sp;
1668         static char tspace[MAXLINE];
1669
1670         sp = tspace;
1671         cp = line;
1672         for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
1673                 tokens[*ntok] = sp;
1674
1675                 /* Skip inter-token whitespace */
1676                 while (ISSPACE(*cp))
1677                     cp++;
1678
1679                 /* If we're at EOL we're done */
1680                 if (ISEOL(*cp))
1681                     break;
1682
1683                 /* If this is the 2nd token and the first token begins
1684                  * with a ':', then just grab to EOL.
1685                  */
1686
1687                 if (*ntok == 1 && tokens[0][0] == ':') {
1688                         do {
1689                                 if (sp - tspace >= MAXLINE)
1690                                         goto toobig;
1691                                 *sp++ = *cp++;
1692                         } while (!ISEOL(*cp));
1693                 }
1694
1695                 /* Check if this token begins with a double quote.
1696                  * If yes, continue reading till the next double quote
1697                  */
1698                 else if (*cp == '\"') {
1699                         ++cp;
1700                         do {
1701                                 if (sp - tspace >= MAXLINE)
1702                                         goto toobig;
1703                                 *sp++ = *cp++;
1704                         } while ((*cp != '\"') && !ISEOL(*cp));
1705                         /* HMS: a missing closing " should be an error */
1706                 }
1707                 else {
1708                         do {
1709                                 if (sp - tspace >= MAXLINE)
1710                                         goto toobig;
1711                                 *sp++ = *cp++;
1712                         } while ((*cp != '\"') && !ISSPACE(*cp) && !ISEOL(*cp));
1713                         /* HMS: Why check for a " in the previous line? */
1714                 }
1715
1716                 if (sp - tspace >= MAXLINE)
1717                         goto toobig;
1718                 *sp++ = '\0';
1719         }
1720         return;
1721
1722   toobig:
1723         *ntok = 0;
1724         fprintf(stderr,
1725                 "***Line `%s' is too big\n",
1726                 line);
1727         return;
1728 }
1729
1730
1731 /*
1732  * getarg - interpret an argument token
1733  */
1734 static int
1735 getarg(
1736         const char *str,
1737         int code,
1738         arg_v *argp
1739         )
1740 {
1741         u_long ul;
1742
1743         switch (code & ~OPT) {
1744         case NTP_STR:
1745                 argp->string = str;
1746                 break;
1747
1748         case NTP_ADD:
1749                 if (!getnetnum(str, &argp->netnum, NULL, 0))
1750                         return 0;
1751                 break;
1752
1753         case NTP_UINT:
1754                 if ('&' == str[0]) {
1755                         if (!atouint(&str[1], &ul)) {
1756                                 fprintf(stderr,
1757                                         "***Association index `%s' invalid/undecodable\n",
1758                                         str);
1759                                 return 0;
1760                         }
1761                         if (0 == numassoc) {
1762                                 dogetassoc(stdout);
1763                                 if (0 == numassoc) {
1764                                         fprintf(stderr,
1765                                                 "***No associations found, `%s' unknown\n",
1766                                                 str);
1767                                         return 0;
1768                                 }
1769                         }
1770                         ul = min(ul, numassoc);
1771                         argp->uval = assoc_cache[ul - 1].assid;
1772                         break;
1773                 }
1774                 if (!atouint(str, &argp->uval)) {
1775                         fprintf(stderr, "***Illegal unsigned value %s\n",
1776                                 str);
1777                         return 0;
1778                 }
1779                 break;
1780
1781         case NTP_INT:
1782                 if (!atoint(str, &argp->ival)) {
1783                         fprintf(stderr, "***Illegal integer value %s\n",
1784                                 str);
1785                         return 0;
1786                 }
1787                 break;
1788
1789         case IP_VERSION:
1790                 if (!strcmp("-6", str)) {
1791                         argp->ival = 6;
1792                 } else if (!strcmp("-4", str)) {
1793                         argp->ival = 4;
1794                 } else {
1795                         fprintf(stderr, "***Version must be either 4 or 6\n");
1796                         return 0;
1797                 }
1798                 break;
1799         }
1800
1801         return 1;
1802 }
1803 #endif  /* !BUILD_AS_LIB */
1804
1805
1806 /*
1807  * findcmd - find a command in a command description table
1808  */
1809 static int
1810 findcmd(
1811         const char *    str,
1812         struct xcmd *   clist1,
1813         struct xcmd *   clist2,
1814         struct xcmd **  cmd
1815         )
1816 {
1817         struct xcmd *cl;
1818         size_t clen;
1819         int nmatch;
1820         struct xcmd *nearmatch = NULL;
1821         struct xcmd *clist;
1822
1823         clen = strlen(str);
1824         nmatch = 0;
1825         if (clist1 != 0)
1826             clist = clist1;
1827         else if (clist2 != 0)
1828             clist = clist2;
1829         else
1830             return 0;
1831
1832     again:
1833         for (cl = clist; cl->keyword != 0; cl++) {
1834                 /* do a first character check, for efficiency */
1835                 if (*str != *(cl->keyword))
1836                     continue;
1837                 if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
1838                         /*
1839                          * Could be extact match, could be approximate.
1840                          * Is exact if the length of the keyword is the
1841                          * same as the str.
1842                          */
1843                         if (*((cl->keyword) + clen) == '\0') {
1844                                 *cmd = cl;
1845                                 return 1;
1846                         }
1847                         nmatch++;
1848                         nearmatch = cl;
1849                 }
1850         }
1851
1852         /*
1853          * See if there is more to do.  If so, go again.  Sorry about the
1854          * goto, too much looking at BSD sources...
1855          */
1856         if (clist == clist1 && clist2 != 0) {
1857                 clist = clist2;
1858                 goto again;
1859         }
1860
1861         /*
1862          * If we got extactly 1 near match, use it, else return number
1863          * of matches.
1864          */
1865         if (nmatch == 1) {
1866                 *cmd = nearmatch;
1867                 return 1;
1868         }
1869         return nmatch;
1870 }
1871
1872
1873 /*
1874  * getnetnum - given a host name, return its net number
1875  *             and (optional) full name
1876  */
1877 int
1878 getnetnum(
1879         const char *hname,
1880         sockaddr_u *num,
1881         char *fullhost,
1882         int af
1883         )
1884 {
1885         struct addrinfo hints, *ai = NULL;
1886
1887         ZERO(hints);
1888         hints.ai_flags = AI_CANONNAME;
1889 #ifdef AI_ADDRCONFIG
1890         hints.ai_flags |= AI_ADDRCONFIG;
1891 #endif
1892
1893         /*
1894          * decodenetnum only works with addresses, but handles syntax
1895          * that getaddrinfo doesn't:  [2001::1]:1234
1896          */
1897         if (decodenetnum(hname, num)) {
1898                 if (fullhost != NULL)
1899                         getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1900                                     LENHOSTNAME, NULL, 0, 0);
1901                 return 1;
1902         } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1903                 INSIST(sizeof(*num) >= ai->ai_addrlen);
1904                 memcpy(num, ai->ai_addr, ai->ai_addrlen);
1905                 if (fullhost != NULL) {
1906                         if (ai->ai_canonname != NULL)
1907                                 strlcpy(fullhost, ai->ai_canonname,
1908                                         LENHOSTNAME);
1909                         else
1910                                 getnameinfo(&num->sa, SOCKLEN(num),
1911                                             fullhost, LENHOSTNAME, NULL,
1912                                             0, 0);
1913                 }
1914                 freeaddrinfo(ai);
1915                 return 1;
1916         }
1917         fprintf(stderr, "***Can't find host %s\n", hname);
1918
1919         return 0;
1920 }
1921
1922
1923 /*
1924  * nntohost - convert network number to host name.  This routine enforces
1925  *             the showhostnames setting.
1926  */
1927 const char *
1928 nntohost(
1929         sockaddr_u *netnum
1930         )
1931 {
1932         return nntohost_col(netnum, LIB_BUFLENGTH - 1, FALSE);
1933 }
1934
1935
1936 /*
1937  * nntohost_col - convert network number to host name in fixed width.
1938  *                This routine enforces the showhostnames setting.
1939  *                When displaying hostnames longer than the width,
1940  *                the first part of the hostname is displayed.  When
1941  *                displaying numeric addresses longer than the width,
1942  *                Such as IPv6 addresses, the caller decides whether
1943  *                the first or last of the numeric address is used.
1944  */
1945 const char *
1946 nntohost_col(
1947         sockaddr_u *    addr,
1948         size_t          width,
1949         int             preserve_lowaddrbits
1950         )
1951 {
1952         const char *    out;
1953
1954         if (!showhostnames || SOCK_UNSPEC(addr)) {
1955                 if (preserve_lowaddrbits)
1956                         out = trunc_left(stoa(addr), width);
1957                 else
1958                         out = trunc_right(stoa(addr), width);
1959         } else if (ISREFCLOCKADR(addr)) {
1960                 out = refnumtoa(addr);
1961         } else {
1962                 out = trunc_right(socktohost(addr), width);
1963         }
1964         return out;
1965 }
1966
1967
1968 /*
1969  * nntohostp() is the same as nntohost() plus a :port suffix
1970  */
1971 const char *
1972 nntohostp(
1973         sockaddr_u *netnum
1974         )
1975 {
1976         const char *    hostn;
1977         char *          buf;
1978
1979         if (!showhostnames || SOCK_UNSPEC(netnum))
1980                 return sptoa(netnum);
1981         else if (ISREFCLOCKADR(netnum))
1982                 return refnumtoa(netnum);
1983
1984         hostn = socktohost(netnum);
1985         LIB_GETBUF(buf);
1986         snprintf(buf, LIB_BUFLENGTH, "%s:%u", hostn, SRCPORT(netnum));
1987
1988         return buf;
1989 }
1990
1991 /*
1992  * rtdatetolfp - decode an RT-11 date into an l_fp
1993  */
1994 static int
1995 rtdatetolfp(
1996         char *str,
1997         l_fp *lfp
1998         )
1999 {
2000         register char *cp;
2001         register int i;
2002         struct calendar cal;
2003         char buf[4];
2004
2005         cal.yearday = 0;
2006
2007         /*
2008          * An RT-11 date looks like:
2009          *
2010          * d[d]-Mth-y[y] hh:mm:ss
2011          *
2012          * (No docs, but assume 4-digit years are also legal...)
2013          *
2014          * d[d]-Mth-y[y[y[y]]] hh:mm:ss
2015          */
2016         cp = str;
2017         if (!isdigit((int)*cp)) {
2018                 if (*cp == '-') {
2019                         /*
2020                          * Catch special case
2021                          */
2022                         L_CLR(lfp);
2023                         return 1;
2024                 }
2025                 return 0;
2026         }
2027
2028         cal.monthday = (u_char) (*cp++ - '0');  /* ascii dependent */
2029         if (isdigit((int)*cp)) {
2030                 cal.monthday = (u_char)((cal.monthday << 3) + (cal.monthday << 1));
2031                 cal.monthday = (u_char)(cal.monthday + *cp++ - '0');
2032         }
2033
2034         if (*cp++ != '-')
2035             return 0;
2036
2037         for (i = 0; i < 3; i++)
2038             buf[i] = *cp++;
2039         buf[3] = '\0';
2040
2041         for (i = 0; i < 12; i++)
2042             if (STREQ(buf, months[i]))
2043                 break;
2044         if (i == 12)
2045             return 0;
2046         cal.month = (u_char)(i + 1);
2047
2048         if (*cp++ != '-')
2049             return 0;
2050
2051         if (!isdigit((int)*cp))
2052             return 0;
2053         cal.year = (u_short)(*cp++ - '0');
2054         if (isdigit((int)*cp)) {
2055                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2056                 cal.year = (u_short)(*cp++ - '0');
2057         }
2058         if (isdigit((int)*cp)) {
2059                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2060                 cal.year = (u_short)(cal.year + *cp++ - '0');
2061         }
2062         if (isdigit((int)*cp)) {
2063                 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2064                 cal.year = (u_short)(cal.year + *cp++ - '0');
2065         }
2066
2067         /*
2068          * Catch special case.  If cal.year == 0 this is a zero timestamp.
2069          */
2070         if (cal.year == 0) {
2071                 L_CLR(lfp);
2072                 return 1;
2073         }
2074
2075         if (*cp++ != ' ' || !isdigit((int)*cp))
2076             return 0;
2077         cal.hour = (u_char)(*cp++ - '0');
2078         if (isdigit((int)*cp)) {
2079                 cal.hour = (u_char)((cal.hour << 3) + (cal.hour << 1));
2080                 cal.hour = (u_char)(cal.hour + *cp++ - '0');
2081         }
2082
2083         if (*cp++ != ':' || !isdigit((int)*cp))
2084             return 0;
2085         cal.minute = (u_char)(*cp++ - '0');
2086         if (isdigit((int)*cp)) {
2087                 cal.minute = (u_char)((cal.minute << 3) + (cal.minute << 1));
2088                 cal.minute = (u_char)(cal.minute + *cp++ - '0');
2089         }
2090
2091         if (*cp++ != ':' || !isdigit((int)*cp))
2092             return 0;
2093         cal.second = (u_char)(*cp++ - '0');
2094         if (isdigit((int)*cp)) {
2095                 cal.second = (u_char)((cal.second << 3) + (cal.second << 1));
2096                 cal.second = (u_char)(cal.second + *cp++ - '0');
2097         }
2098
2099         /*
2100          * For RT-11, 1972 seems to be the pivot year
2101          */
2102         if (cal.year < 72)
2103                 cal.year += 2000;
2104         if (cal.year < 100)
2105                 cal.year += 1900;
2106
2107         lfp->l_ui = caltontp(&cal);
2108         lfp->l_uf = 0;
2109         return 1;
2110 }
2111
2112
2113 /*
2114  * decodets - decode a timestamp into an l_fp format number, with
2115  *            consideration of fuzzball formats.
2116  */
2117 int
2118 decodets(
2119         char *str,
2120         l_fp *lfp
2121         )
2122 {
2123         char *cp;
2124         char buf[30];
2125         size_t b;
2126
2127         /*
2128          * If it starts with a 0x, decode as hex.
2129          */
2130         if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
2131                 return hextolfp(str+2, lfp);
2132
2133         /*
2134          * If it starts with a '"', try it as an RT-11 date.
2135          */
2136         if (*str == '"') {
2137                 cp = str + 1;
2138                 b = 0;
2139                 while ('"' != *cp && '\0' != *cp &&
2140                        b < COUNTOF(buf) - 1)
2141                         buf[b++] = *cp++;
2142                 buf[b] = '\0';
2143                 return rtdatetolfp(buf, lfp);
2144         }
2145
2146         /*
2147          * Might still be hex.  Check out the first character.  Talk
2148          * about heuristics!
2149          */
2150         if ((*str >= 'A' && *str <= 'F') || (*str >= 'a' && *str <= 'f'))
2151                 return hextolfp(str, lfp);
2152
2153         /*
2154          * Try it as a decimal.  If this fails, try as an unquoted
2155          * RT-11 date.  This code should go away eventually.
2156          */
2157         if (atolfp(str, lfp))
2158                 return 1;
2159
2160         return rtdatetolfp(str, lfp);
2161 }
2162
2163
2164 /*
2165  * decodetime - decode a time value.  It should be in milliseconds
2166  */
2167 int
2168 decodetime(
2169         char *str,
2170         l_fp *lfp
2171         )
2172 {
2173         return mstolfp(str, lfp);
2174 }
2175
2176
2177 /*
2178  * decodeint - decode an integer
2179  */
2180 int
2181 decodeint(
2182         char *str,
2183         long *val
2184         )
2185 {
2186         if (*str == '0') {
2187                 if (*(str+1) == 'x' || *(str+1) == 'X')
2188                     return hextoint(str+2, (u_long *)val);
2189                 return octtoint(str, (u_long *)val);
2190         }
2191         return atoint(str, val);
2192 }
2193
2194
2195 /*
2196  * decodeuint - decode an unsigned integer
2197  */
2198 int
2199 decodeuint(
2200         char *str,
2201         u_long *val
2202         )
2203 {
2204         if (*str == '0') {
2205                 if (*(str + 1) == 'x' || *(str + 1) == 'X')
2206                         return (hextoint(str + 2, val));
2207                 return (octtoint(str, val));
2208         }
2209         return (atouint(str, val));
2210 }
2211
2212
2213 /*
2214  * decodearr - decode an array of time values
2215  */
2216 static int
2217 decodearr(
2218         char *str,
2219         int *narr,
2220         l_fp *lfparr
2221         )
2222 {
2223         register char *cp, *bp;
2224         register l_fp *lfp;
2225         char buf[60];
2226
2227         lfp = lfparr;
2228         cp = str;
2229         *narr = 0;
2230
2231         while (*narr < 8) {
2232                 while (isspace((int)*cp))
2233                     cp++;
2234                 if (*cp == '\0')
2235                     break;
2236
2237                 bp = buf;
2238                 while (!isspace((int)*cp) && *cp != '\0')
2239                     *bp++ = *cp++;
2240                 *bp++ = '\0';
2241
2242                 if (!decodetime(buf, lfp))
2243                     return 0;
2244                 (*narr)++;
2245                 lfp++;
2246         }
2247         return 1;
2248 }
2249
2250
2251 /*
2252  * Finally, the built in command handlers
2253  */
2254
2255 /*
2256  * help - tell about commands, or details of a particular command
2257  */
2258 static void
2259 help(
2260         struct parse *pcmd,
2261         FILE *fp
2262         )
2263 {
2264         struct xcmd *xcp = NULL;        /* quiet warning */
2265         const char *cmd;
2266         const char *list[100];
2267         size_t word, words;
2268         size_t row, rows;
2269         size_t col, cols;
2270         size_t length;
2271
2272         if (pcmd->nargs == 0) {
2273                 words = 0;
2274                 for (xcp = builtins; xcp->keyword != NULL; xcp++) {
2275                         if (*(xcp->keyword) != '?' &&
2276                             words < COUNTOF(list))
2277                                 list[words++] = xcp->keyword;
2278                 }
2279                 for (xcp = opcmds; xcp->keyword != NULL; xcp++)
2280                         if (words < COUNTOF(list))
2281                                 list[words++] = xcp->keyword;
2282
2283                 qsort((void *)list, words, sizeof(list[0]), helpsort);
2284                 col = 0;
2285                 for (word = 0; word < words; word++) {
2286                         length = strlen(list[word]);
2287                         col = max(col, length);
2288                 }
2289
2290                 cols = SCREENWIDTH / ++col;
2291                 rows = (words + cols - 1) / cols;
2292
2293                 fprintf(fp, "ntpq commands:\n");
2294
2295                 for (row = 0; row < rows; row++) {
2296                         for (word = row; word < words; word += rows)
2297                                 fprintf(fp, "%-*.*s", (int)col,
2298                                         (int)col - 1, list[word]);
2299                         fprintf(fp, "\n");
2300                 }
2301         } else {
2302                 cmd = pcmd->argval[0].string;
2303                 words = findcmd(cmd, builtins, opcmds, &xcp);
2304                 if (words == 0) {
2305                         fprintf(stderr,
2306                                 "Command `%s' is unknown\n", cmd);
2307                         return;
2308                 } else if (words >= 2) {
2309                         fprintf(stderr,
2310                                 "Command `%s' is ambiguous\n", cmd);
2311                         return;
2312                 }
2313                 fprintf(fp, "function: %s\n", xcp->comment);
2314                 printusage(xcp, fp);
2315         }
2316 }
2317
2318
2319 /*
2320  * helpsort - do hostname qsort comparisons
2321  */
2322 static int
2323 helpsort(
2324         const void *t1,
2325         const void *t2
2326         )
2327 {
2328         const char * const *    name1 = t1;
2329         const char * const *    name2 = t2;
2330
2331         return strcmp(*name1, *name2);
2332 }
2333
2334
2335 /*
2336  * printusage - print usage information for a command
2337  */
2338 static void
2339 printusage(
2340         struct xcmd *xcp,
2341         FILE *fp
2342         )
2343 {
2344         register int i;
2345
2346         /* XXX: Do we need to warn about extra args here too? */
2347
2348         (void) fprintf(fp, "usage: %s", xcp->keyword);
2349         for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
2350                 if (xcp->arg[i] & OPT)
2351                     (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
2352                 else
2353                     (void) fprintf(fp, " %s", xcp->desc[i]);
2354         }
2355         (void) fprintf(fp, "\n");
2356 }
2357
2358
2359 /*
2360  * timeout - set time out time
2361  */
2362 static void
2363 timeout(
2364         struct parse *pcmd,
2365         FILE *fp
2366         )
2367 {
2368         int val;
2369
2370         if (pcmd->nargs == 0) {
2371                 val = (int)tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
2372                 (void) fprintf(fp, "primary timeout %d ms\n", val);
2373         } else {
2374                 tvout.tv_sec = pcmd->argval[0].uval / 1000;
2375                 tvout.tv_usec = (pcmd->argval[0].uval - ((long)tvout.tv_sec * 1000))
2376                         * 1000;
2377         }
2378 }
2379
2380
2381 /*
2382  * auth_delay - set delay for auth requests
2383  */
2384 static void
2385 auth_delay(
2386         struct parse *pcmd,
2387         FILE *fp
2388         )
2389 {
2390         int isneg;
2391         u_long val;
2392
2393         if (pcmd->nargs == 0) {
2394                 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
2395                 (void) fprintf(fp, "delay %lu ms\n", val);
2396         } else {
2397                 if (pcmd->argval[0].ival < 0) {
2398                         isneg = 1;
2399                         val = (u_long)(-pcmd->argval[0].ival);
2400                 } else {
2401                         isneg = 0;
2402                         val = (u_long)pcmd->argval[0].ival;
2403                 }
2404
2405                 delay_time.l_ui = val / 1000;
2406                 val %= 1000;
2407                 delay_time.l_uf = val * 4294967;        /* 2**32/1000 */
2408
2409                 if (isneg)
2410                     L_NEG(&delay_time);
2411         }
2412 }
2413
2414
2415 /*
2416  * host - set the host we are dealing with.
2417  */
2418 static void
2419 host(
2420         struct parse *pcmd,
2421         FILE *fp
2422         )
2423 {
2424         int i;
2425
2426         if (pcmd->nargs == 0) {
2427                 if (havehost)
2428                         (void) fprintf(fp, "current host is %s\n",
2429                                            currenthost);
2430                 else
2431                         (void) fprintf(fp, "no current host\n");
2432                 return;
2433         }
2434
2435         i = 0;
2436         ai_fam_templ = ai_fam_default;
2437         if (pcmd->nargs == 2) {
2438                 if (!strcmp("-4", pcmd->argval[i].string))
2439                         ai_fam_templ = AF_INET;
2440                 else if (!strcmp("-6", pcmd->argval[i].string))
2441                         ai_fam_templ = AF_INET6;
2442                 else
2443                         goto no_change;
2444                 i = 1;
2445         }
2446         if (openhost(pcmd->argval[i].string, ai_fam_templ)) {
2447                 fprintf(fp, "current host set to %s\n", currenthost);
2448         } else {
2449     no_change:
2450                 if (havehost)
2451                         fprintf(fp, "current host remains %s\n",
2452                                 currenthost);
2453                 else
2454                         fprintf(fp, "still no current host\n");
2455         }
2456 }
2457
2458
2459 /*
2460  * poll - do one (or more) polls of the host via NTP
2461  */
2462 /*ARGSUSED*/
2463 static void
2464 ntp_poll(
2465         struct parse *pcmd,
2466         FILE *fp
2467         )
2468 {
2469         (void) fprintf(fp, "poll not implemented yet\n");
2470 }
2471
2472
2473 /*
2474  * showdrefid2str - return a string explanation of the value of drefid
2475  */
2476 static char *
2477 showdrefid2str(void)
2478 {
2479         switch (drefid) {
2480             case REFID_HASH:
2481                 return "hash";
2482             case REFID_IPV4:
2483                 return "ipv4";
2484             default:
2485                 return "Unknown";
2486         }
2487 }
2488
2489
2490 /*
2491  * drefid - display/change "display hash" 
2492  */
2493 static void
2494 showdrefid(
2495         struct parse *pcmd,
2496         FILE *fp
2497         )
2498 {
2499         if (pcmd->nargs == 0) {
2500                 (void) fprintf(fp, "drefid value is %s\n", showdrefid2str());
2501                 return;
2502         } else if (STREQ(pcmd->argval[0].string, "hash")) {
2503                 drefid = REFID_HASH;
2504         } else if (STREQ(pcmd->argval[0].string, "ipv4")) {
2505                 drefid = REFID_IPV4;
2506         } else {
2507                 (void) fprintf(fp, "What?\n");
2508                 return;
2509         }
2510         (void) fprintf(fp, "drefid value set to %s\n", showdrefid2str());
2511 }
2512
2513
2514 /*
2515  * keyid - get a keyid to use for authenticating requests
2516  */
2517 static void
2518 keyid(
2519         struct parse *pcmd,
2520         FILE *fp
2521         )
2522 {
2523         if (pcmd->nargs == 0) {
2524                 if (info_auth_keyid == 0)
2525                     (void) fprintf(fp, "no keyid defined\n");
2526                 else
2527                     (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
2528         } else {
2529                 /* allow zero so that keyid can be cleared. */
2530                 if(pcmd->argval[0].uval > NTP_MAXKEY)
2531                     (void) fprintf(fp, "Invalid key identifier\n");
2532                 info_auth_keyid = pcmd->argval[0].uval;
2533         }
2534 }
2535
2536 /*
2537  * keytype - get type of key to use for authenticating requests
2538  */
2539 static void
2540 keytype(
2541         struct parse *pcmd,
2542         FILE *fp
2543         )
2544 {
2545         const char *    digest_name;
2546         size_t          digest_len;
2547         int             key_type;
2548
2549         if (!pcmd->nargs) {
2550                 fprintf(fp, "keytype is %s with %lu octet digests\n",
2551                         keytype_name(info_auth_keytype),
2552                         (u_long)info_auth_hashlen);
2553                 return;
2554         }
2555
2556         digest_name = pcmd->argval[0].string;
2557         digest_len = 0;
2558         key_type = keytype_from_text(digest_name, &digest_len);
2559
2560         if (!key_type) {
2561                 fprintf(fp, "keytype is not valid. "
2562 #ifdef OPENSSL
2563                         "Type \"help keytype\" for the available digest types.\n");
2564 #else
2565                         "Only \"md5\" is available.\n");
2566 #endif
2567                 return;
2568         }
2569
2570         info_auth_keytype = key_type;
2571         info_auth_hashlen = digest_len;
2572 }
2573
2574
2575 /*
2576  * passwd - get an authentication key
2577  */
2578 /*ARGSUSED*/
2579 static void
2580 passwd(
2581         struct parse *pcmd,
2582         FILE *fp
2583         )
2584 {
2585         const char *pass;
2586
2587         if (info_auth_keyid == 0) {
2588                 info_auth_keyid = getkeyid("Keyid: ");
2589                 if (info_auth_keyid == 0) {
2590                         (void)fprintf(fp, "Keyid must be defined\n");
2591                         return;
2592                 }
2593         }
2594         if (pcmd->nargs >= 1)
2595                 pass = pcmd->argval[0].string;
2596         else {
2597                 pass = getpass_keytype(info_auth_keytype);
2598                 if ('\0' == pass[0]) {
2599                         fprintf(fp, "Password unchanged\n");
2600                         return;
2601                 }
2602         }
2603         authusekey(info_auth_keyid, info_auth_keytype,
2604                    (const u_char *)pass);
2605         authtrust(info_auth_keyid, 1);
2606 }
2607
2608
2609 /*
2610  * hostnames - set the showhostnames flag
2611  */
2612 static void
2613 hostnames(
2614         struct parse *pcmd,
2615         FILE *fp
2616         )
2617 {
2618         if (pcmd->nargs == 0) {
2619                 if (showhostnames)
2620                     (void) fprintf(fp, "hostnames being shown\n");
2621                 else
2622                     (void) fprintf(fp, "hostnames not being shown\n");
2623         } else {
2624                 if (STREQ(pcmd->argval[0].string, "yes"))
2625                     showhostnames = 1;
2626                 else if (STREQ(pcmd->argval[0].string, "no"))
2627                     showhostnames = 0;
2628                 else
2629                     (void)fprintf(stderr, "What?\n");
2630         }
2631 }
2632
2633
2634
2635 /*
2636  * setdebug - set/change debugging level
2637  */
2638 static void
2639 setdebug(
2640         struct parse *pcmd,
2641         FILE *fp
2642         )
2643 {
2644         if (pcmd->nargs == 0) {
2645                 (void) fprintf(fp, "debug level is %d\n", debug);
2646                 return;
2647         } else if (STREQ(pcmd->argval[0].string, "no")) {
2648                 debug = 0;
2649         } else if (STREQ(pcmd->argval[0].string, "more")) {
2650                 debug++;
2651         } else if (STREQ(pcmd->argval[0].string, "less")) {
2652                 debug--;
2653         } else {
2654                 (void) fprintf(fp, "What?\n");
2655                 return;
2656         }
2657         (void) fprintf(fp, "debug level set to %d\n", debug);
2658 }
2659
2660
2661 /*
2662  * quit - stop this nonsense
2663  */
2664 /*ARGSUSED*/
2665 static void
2666 quit(
2667         struct parse *pcmd,
2668         FILE *fp
2669         )
2670 {
2671         if (havehost)
2672             closesocket(sockfd);        /* cleanliness next to godliness */
2673         exit(0);
2674 }
2675
2676
2677 /*
2678  * version - print the current version number
2679  */
2680 /*ARGSUSED*/
2681 static void
2682 version(
2683         struct parse *pcmd,
2684         FILE *fp
2685         )
2686 {
2687
2688         (void) fprintf(fp, "%s\n", Version);
2689         return;
2690 }
2691
2692
2693 /*
2694  * raw - set raw mode output
2695  */
2696 /*ARGSUSED*/
2697 static void
2698 raw(
2699         struct parse *pcmd,
2700         FILE *fp
2701         )
2702 {
2703         rawmode = 1;
2704         (void) fprintf(fp, "Output set to raw\n");
2705 }
2706
2707
2708 /*
2709  * cooked - set cooked mode output
2710  */
2711 /*ARGSUSED*/
2712 static void
2713 cooked(
2714         struct parse *pcmd,
2715         FILE *fp
2716         )
2717 {
2718         rawmode = 0;
2719         (void) fprintf(fp, "Output set to cooked\n");
2720         return;
2721 }
2722
2723
2724 /*
2725  * authenticate - always authenticate requests to this host
2726  */
2727 static void
2728 authenticate(
2729         struct parse *pcmd,
2730         FILE *fp
2731         )
2732 {
2733         if (pcmd->nargs == 0) {
2734                 if (always_auth) {
2735                         (void) fprintf(fp,
2736                                        "authenticated requests being sent\n");
2737                 } else
2738                     (void) fprintf(fp,
2739                                    "unauthenticated requests being sent\n");
2740         } else {
2741                 if (STREQ(pcmd->argval[0].string, "yes")) {
2742                         always_auth = 1;
2743                 } else if (STREQ(pcmd->argval[0].string, "no")) {
2744                         always_auth = 0;
2745                 } else
2746                     (void)fprintf(stderr, "What?\n");
2747         }
2748 }
2749
2750
2751 /*
2752  * ntpversion - choose the NTP version to use
2753  */
2754 static void
2755 ntpversion(
2756         struct parse *pcmd,
2757         FILE *fp
2758         )
2759 {
2760         if (pcmd->nargs == 0) {
2761                 (void) fprintf(fp,
2762                                "NTP version being claimed is %d\n", pktversion);
2763         } else {
2764                 if (pcmd->argval[0].uval < NTP_OLDVERSION
2765                     || pcmd->argval[0].uval > NTP_VERSION) {
2766                         (void) fprintf(stderr, "versions %d to %d, please\n",
2767                                        NTP_OLDVERSION, NTP_VERSION);
2768                 } else {
2769                         pktversion = (u_char) pcmd->argval[0].uval;
2770                 }
2771         }
2772 }
2773
2774
2775 static void __attribute__((__format__(__printf__, 1, 0)))
2776 vwarning(const char *fmt, va_list ap)
2777 {
2778         int serrno = errno;
2779         (void) fprintf(stderr, "%s: ", progname);
2780         vfprintf(stderr, fmt, ap);
2781         (void) fprintf(stderr, ": %s\n", strerror(serrno));
2782 }
2783
2784 /*
2785  * warning - print a warning message
2786  */
2787 static void __attribute__((__format__(__printf__, 1, 2)))
2788 warning(
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 }
2798
2799
2800 /*
2801  * error - print a message and exit
2802  */
2803 static void __attribute__((__format__(__printf__, 1, 2)))
2804 error(
2805         const char *fmt,
2806         ...
2807         )
2808 {
2809         va_list ap;
2810         va_start(ap, fmt);
2811         vwarning(fmt, ap);
2812         va_end(ap);
2813         exit(1);
2814 }
2815 /*
2816  * getkeyid - prompt the user for a keyid to use
2817  */
2818 static u_long
2819 getkeyid(
2820         const char *keyprompt
2821         )
2822 {
2823         int c;
2824         FILE *fi;
2825         char pbuf[20];
2826         size_t i;
2827         size_t ilim;
2828
2829 #ifndef SYS_WINNT
2830         if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
2831 #else
2832         if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
2833 #endif /* SYS_WINNT */
2834                 fi = stdin;
2835         else
2836                 setbuf(fi, (char *)NULL);
2837         fprintf(stderr, "%s", keyprompt); fflush(stderr);
2838         for (i = 0, ilim = COUNTOF(pbuf) - 1;
2839              i < ilim && (c = getc(fi)) != '\n' && c != EOF;
2840              )
2841                 pbuf[i++] = (char)c;
2842         pbuf[i] = '\0';
2843         if (fi != stdin)
2844                 fclose(fi);
2845
2846         return (u_long) atoi(pbuf);
2847 }
2848
2849
2850 /*
2851  * atoascii - printable-ize possibly ascii data using the character
2852  *            transformations cat -v uses.
2853  */
2854 static void
2855 atoascii(
2856         const char *in,
2857         size_t in_octets,
2858         char *out,
2859         size_t out_octets
2860         )
2861 {
2862         const u_char *  pchIn;
2863         const u_char *  pchInLimit;
2864         u_char *        pchOut;
2865         u_char          c;
2866
2867         pchIn = (const u_char *)in;
2868         pchInLimit = pchIn + in_octets;
2869         pchOut = (u_char *)out;
2870
2871         if (NULL == pchIn) {
2872                 if (0 < out_octets)
2873                         *pchOut = '\0';
2874                 return;
2875         }
2876
2877 #define ONEOUT(c)                                       \
2878 do {                                                    \
2879         if (0 == --out_octets) {                        \
2880                 *pchOut = '\0';                         \
2881                 return;                                 \
2882         }                                               \
2883         *pchOut++ = (c);                                \
2884 } while (0)
2885
2886         for (   ; pchIn < pchInLimit; pchIn++) {
2887                 c = *pchIn;
2888                 if ('\0' == c)
2889                         break;
2890                 if (c & 0x80) {
2891                         ONEOUT('M');
2892                         ONEOUT('-');
2893                         c &= 0x7f;
2894                 }
2895                 if (c < ' ') {
2896                         ONEOUT('^');
2897                         ONEOUT((u_char)(c + '@'));
2898                 } else if (0x7f == c) {
2899                         ONEOUT('^');
2900                         ONEOUT('?');
2901                 } else
2902                         ONEOUT(c);
2903         }
2904         ONEOUT('\0');
2905
2906 #undef ONEOUT
2907 }
2908
2909
2910 /*
2911  * makeascii - print possibly ascii data using the character
2912  *             transformations that cat -v uses.
2913  */
2914 void
2915 makeascii(
2916         size_t length,
2917         const char *data,
2918         FILE *fp
2919         )
2920 {
2921         const u_char *data_u_char;
2922         const u_char *cp;
2923         int c;
2924
2925         data_u_char = (const u_char *)data;
2926
2927         for (cp = data_u_char; cp < data_u_char + length; cp++) {
2928                 c = (int)*cp;
2929                 if (c & 0x80) {
2930                         putc('M', fp);
2931                         putc('-', fp);
2932                         c &= 0x7f;
2933                 }
2934
2935                 if (c < ' ') {
2936                         putc('^', fp);
2937                         putc(c + '@', fp);
2938                 } else if (0x7f == c) {
2939                         putc('^', fp);
2940                         putc('?', fp);
2941                 } else
2942                         putc(c, fp);
2943         }
2944 }
2945
2946
2947 /*
2948  * asciize - same thing as makeascii except add a newline
2949  */
2950 void
2951 asciize(
2952         int length,
2953         char *data,
2954         FILE *fp
2955         )
2956 {
2957         makeascii(length, data, fp);
2958         putc('\n', fp);
2959 }
2960
2961
2962 /*
2963  * truncate string to fit clipping excess at end.
2964  *      "too long"      ->      "too l"
2965  * Used for hostnames.
2966  */
2967 const char *
2968 trunc_right(
2969         const char *    src,
2970         size_t          width
2971         )
2972 {
2973         size_t  sl;
2974         char *  out;
2975
2976
2977         sl = strlen(src);
2978         if (sl > width && LIB_BUFLENGTH - 1 > width && width > 0) {
2979                 LIB_GETBUF(out);
2980                 memcpy(out, src, width);
2981                 out[width] = '\0';
2982
2983                 return out;
2984         }
2985
2986         return src;
2987 }
2988
2989
2990 /*
2991  * truncate string to fit by preserving right side and using '_' to hint
2992  *      "too long"      ->      "_long"
2993  * Used for local IPv6 addresses, where low bits differentiate.
2994  */
2995 const char *
2996 trunc_left(
2997         const char *    src,
2998         size_t          width
2999         )
3000 {
3001         size_t  sl;
3002         char *  out;
3003
3004
3005         sl = strlen(src);
3006         if (sl > width && LIB_BUFLENGTH - 1 > width && width > 1) {
3007                 LIB_GETBUF(out);
3008                 out[0] = '_';
3009                 memcpy(&out[1], &src[sl + 1 - width], width);
3010
3011                 return out;
3012         }
3013
3014         return src;
3015 }
3016
3017
3018 /*
3019  * Some circular buffer space
3020  */
3021 #define CBLEN   80
3022 #define NUMCB   6
3023
3024 char circ_buf[NUMCB][CBLEN];
3025 int nextcb = 0;
3026
3027 /*
3028  * nextvar - find the next variable in the buffer
3029  */
3030 int
3031 nextvar(
3032         size_t *datalen,
3033         const char **datap,
3034         char **vname,
3035         char **vvalue
3036         )
3037 {
3038         const char *cp;
3039         const char *np;
3040         const char *cpend;
3041         size_t srclen;
3042         size_t len;
3043         static char name[MAXVARLEN];
3044         static char value[MAXVALLEN];
3045
3046         cp = *datap;
3047         cpend = cp + *datalen;
3048
3049         /*
3050          * Space past commas and white space
3051          */
3052         while (cp < cpend && (*cp == ',' || isspace((int)*cp)))
3053                 cp++;
3054         if (cp >= cpend)
3055                 return 0;
3056
3057         /*
3058          * Copy name until we hit a ',', an '=', a '\r' or a '\n'.  Backspace
3059          * over any white space and terminate it.
3060          */
3061         srclen = strcspn(cp, ",=\r\n");
3062         srclen = min(srclen, (size_t)(cpend - cp));
3063         len = srclen;
3064         while (len > 0 && isspace((unsigned char)cp[len - 1]))
3065                 len--;
3066         if (len >= sizeof(name))
3067             return 0;
3068         if (len > 0)
3069                 memcpy(name, cp, len);
3070         name[len] = '\0';
3071         *vname = name;
3072         cp += srclen;
3073
3074         /*
3075          * Check if we hit the end of the buffer or a ','.  If so we are done.
3076          */
3077         if (cp >= cpend || *cp == ',' || *cp == '\r' || *cp == '\n') {
3078                 if (cp < cpend)
3079                         cp++;
3080                 *datap = cp;
3081                 *datalen = size2int_sat(cpend - cp);
3082                 *vvalue = NULL;
3083                 return 1;
3084         }
3085
3086         /*
3087          * So far, so good.  Copy out the value
3088          */
3089         cp++;   /* past '=' */
3090         while (cp < cpend && (isspace((unsigned char)*cp) && *cp != '\r' && *cp != '\n'))
3091                 cp++;
3092         np = cp;
3093         if ('"' == *np) {
3094                 do {
3095                         np++;
3096                 } while (np < cpend && '"' != *np);
3097                 if (np < cpend && '"' == *np)
3098                         np++;
3099         } else {
3100                 while (np < cpend && ',' != *np && '\r' != *np)
3101                         np++;
3102         }
3103         len = np - cp;
3104         if (np > cpend || len >= sizeof(value) ||
3105             (np < cpend && ',' != *np && '\r' != *np))
3106                 return 0;
3107         memcpy(value, cp, len);
3108         /*
3109          * Trim off any trailing whitespace
3110          */
3111         while (len > 0 && isspace((unsigned char)value[len - 1]))
3112                 len--;
3113         value[len] = '\0';
3114
3115         /*
3116          * Return this.  All done.
3117          */
3118         if (np < cpend && ',' == *np)
3119                 np++;
3120         *datap = np;
3121         *datalen = size2int_sat(cpend - np);
3122         *vvalue = value;
3123         return 1;
3124 }
3125
3126
3127 u_short
3128 varfmt(const char * varname)
3129 {
3130         u_int n;
3131
3132         for (n = 0; n < COUNTOF(cookedvars); n++)
3133                 if (!strcmp(varname, cookedvars[n].varname))
3134                         return cookedvars[n].fmt;
3135
3136         return PADDING;
3137 }
3138
3139
3140 /*
3141  * printvars - print variables returned in response packet
3142  */
3143 void
3144 printvars(
3145         size_t length,
3146         const char *data,
3147         int status,
3148         int sttype,
3149         int quiet,
3150         FILE *fp
3151         )
3152 {
3153         if (rawmode)
3154             rawprint(sttype, length, data, status, quiet, fp);
3155         else
3156             cookedprint(sttype, length, data, status, quiet, fp);
3157 }
3158
3159
3160 /*
3161  * rawprint - do a printout of the data in raw mode
3162  */
3163 static void
3164 rawprint(
3165         int datatype,
3166         size_t length,
3167         const char *data,
3168         int status,
3169         int quiet,
3170         FILE *fp
3171         )
3172 {
3173         const char *cp;
3174         const char *cpend;
3175
3176         /*
3177          * Essentially print the data as is.  We reformat unprintables, though.
3178          */
3179         cp = data;
3180         cpend = data + length;
3181
3182         if (!quiet)
3183                 (void) fprintf(fp, "status=0x%04x,\n", status);
3184
3185         while (cp < cpend) {
3186                 if (*cp == '\r') {
3187                         /*
3188                          * If this is a \r and the next character is a
3189                          * \n, supress this, else pretty print it.  Otherwise
3190                          * just output the character.
3191                          */
3192                         if (cp == (cpend - 1) || *(cp + 1) != '\n')
3193                             makeascii(1, cp, fp);
3194                 } else if (isspace((unsigned char)*cp) || isprint((unsigned char)*cp))
3195                         putc(*cp, fp);
3196                 else
3197                         makeascii(1, cp, fp);
3198                 cp++;
3199         }
3200 }
3201
3202
3203 /*
3204  * Global data used by the cooked output routines
3205  */
3206 int out_chars;          /* number of characters output */
3207 int out_linecount;      /* number of characters output on this line */
3208
3209
3210 /*
3211  * startoutput - get ready to do cooked output
3212  */
3213 static void
3214 startoutput(void)
3215 {
3216         out_chars = 0;
3217         out_linecount = 0;
3218 }
3219
3220
3221 /*
3222  * output - output a variable=value combination
3223  */
3224 static void
3225 output(
3226         FILE *fp,
3227         const char *name,
3228         const char *value
3229         )
3230 {
3231         int len;
3232
3233         /* strlen of "name=value" */
3234         len = size2int_sat(strlen(name) + 1 + strlen(value));
3235
3236         if (out_chars != 0) {
3237                 out_chars += 2;
3238                 if ((out_linecount + len + 2) > MAXOUTLINE) {
3239                         fputs(",\n", fp);
3240                         out_linecount = 0;
3241                 } else {
3242                         fputs(", ", fp);
3243                         out_linecount += 2;
3244                 }
3245         }
3246
3247         fputs(name, fp);
3248         putc('=', fp);
3249         fputs(value, fp);
3250         out_chars += len;
3251         out_linecount += len;
3252 }
3253
3254
3255 /*
3256  * endoutput - terminate a block of cooked output
3257  */
3258 static void
3259 endoutput(
3260         FILE *fp
3261         )
3262 {
3263         if (out_chars != 0)
3264                 putc('\n', fp);
3265 }
3266
3267
3268 /*
3269  * outputarr - output an array of values
3270  */
3271 static void
3272 outputarr(
3273         FILE *fp,
3274         char *name,
3275         int narr,
3276         l_fp *lfp
3277         )
3278 {
3279         char *bp;
3280         char *cp;
3281         size_t i;
3282         size_t len;
3283         char buf[256];
3284
3285         bp = buf;
3286         /*
3287          * Hack to align delay and offset values
3288          */
3289         for (i = (int)strlen(name); i < 11; i++)
3290             *bp++ = ' ';
3291
3292         for (i = narr; i > 0; i--) {
3293                 if (i != narr)
3294                     *bp++ = ' ';
3295                 cp = lfptoms(lfp, 2);
3296                 len = strlen(cp);
3297                 if (len > 7) {
3298                         cp[7] = '\0';
3299                         len = 7;
3300                 }
3301                 while (len < 7) {
3302                         *bp++ = ' ';
3303                         len++;
3304                 }
3305                 while (*cp != '\0')
3306                     *bp++ = *cp++;
3307                 lfp++;
3308         }
3309         *bp = '\0';
3310         output(fp, name, buf);
3311 }
3312
3313 static char *
3314 tstflags(
3315         u_long val
3316         )
3317 {
3318         register char *cp, *s;
3319         size_t cb;
3320         register int i;
3321         register const char *sep;
3322
3323         sep = "";
3324         s = cp = circ_buf[nextcb];
3325         if (++nextcb >= NUMCB)
3326                 nextcb = 0;
3327         cb = sizeof(circ_buf[0]);
3328
3329         snprintf(cp, cb, "%02lx", val);
3330         cp += strlen(cp);
3331         cb -= strlen(cp);
3332         if (!val) {
3333                 strlcat(cp, " ok", cb);
3334                 cp += strlen(cp);
3335                 cb -= strlen(cp);
3336         } else {
3337                 if (cb) {
3338                         *cp++ = ' ';
3339                         cb--;
3340                 }
3341                 for (i = 0; i < (int)COUNTOF(tstflagnames); i++) {
3342                         if (val & 0x1) {
3343                                 snprintf(cp, cb, "%s%s", sep,
3344                                          tstflagnames[i]);
3345                                 sep = ", ";
3346                                 cp += strlen(cp);
3347                                 cb -= strlen(cp);
3348                         }
3349                         val >>= 1;
3350                 }
3351         }
3352         if (cb)
3353                 *cp = '\0';
3354
3355         return s;
3356 }
3357
3358 /*
3359  * cookedprint - output variables in cooked mode
3360  */
3361 static void
3362 cookedprint(
3363         int datatype,
3364         size_t length,
3365         const char *data,
3366         int status,
3367         int quiet,
3368         FILE *fp
3369         )
3370 {
3371         char *name;
3372         char *value;
3373         char output_raw;
3374         int fmt;
3375         l_fp lfp;
3376         sockaddr_u hval;
3377         u_long uval;
3378         int narr;
3379         size_t len;
3380         l_fp lfparr[8];
3381         char b[12];
3382         char bn[2 * MAXVARLEN];
3383         char bv[2 * MAXVALLEN];
3384
3385         UNUSED_ARG(datatype);
3386
3387         if (!quiet)
3388                 fprintf(fp, "status=%04x %s,\n", status,
3389                         statustoa(datatype, status));
3390
3391         startoutput();
3392         while (nextvar(&length, &data, &name, &value)) {
3393                 fmt = varfmt(name);
3394                 output_raw = 0;
3395                 switch (fmt) {
3396
3397                 case PADDING:
3398                         output_raw = '*';
3399                         break;
3400
3401                 case TS:
3402                         if (!decodets(value, &lfp))
3403                                 output_raw = '?';
3404                         else
3405                                 output(fp, name, prettydate(&lfp));
3406                         break;
3407
3408                 case HA:        /* fallthru */
3409                 case NA:
3410                         if (!decodenetnum(value, &hval)) {
3411                                 output_raw = '?';
3412                         } else if (fmt == HA){
3413                                 output(fp, name, nntohost(&hval));
3414                         } else {
3415                                 output(fp, name, stoa(&hval));
3416                         }
3417                         break;
3418
3419                 case RF:
3420                         if (decodenetnum(value, &hval)) {
3421                                 if (ISREFCLOCKADR(&hval))
3422                                         output(fp, name,
3423                                                refnumtoa(&hval));
3424                                 else
3425                                         output(fp, name, stoa(&hval));
3426                         } else if (strlen(value) <= 4) {
3427                                 output(fp, name, value);
3428                         } else {
3429                                 output_raw = '?';
3430                         }
3431                         break;
3432
3433                 case LP:
3434                         if (!decodeuint(value, &uval) || uval > 3) {
3435                                 output_raw = '?';
3436                         } else {
3437                                 b[0] = (0x2 & uval)
3438                                            ? '1'
3439                                            : '0';
3440                                 b[1] = (0x1 & uval)
3441                                            ? '1'
3442                                            : '0';
3443                                 b[2] = '\0';
3444                                 output(fp, name, b);
3445                         }
3446                         break;
3447
3448                 case OC:
3449                         if (!decodeuint(value, &uval)) {
3450                                 output_raw = '?';
3451                         } else {
3452                                 snprintf(b, sizeof(b), "%03lo", uval);
3453                                 output(fp, name, b);
3454                         }
3455                         break;
3456
3457                 case AR:
3458                         if (!decodearr(value, &narr, lfparr))
3459                                 output_raw = '?';
3460                         else
3461                                 outputarr(fp, name, narr, lfparr);
3462                         break;
3463
3464                 case FX:
3465                         if (!decodeuint(value, &uval))
3466                                 output_raw = '?';
3467                         else
3468                                 output(fp, name, tstflags(uval));
3469                         break;
3470
3471                 default:
3472                         fprintf(stderr, "Internal error in cookedprint, %s=%s, fmt %d\n",
3473                                 name, value, fmt);
3474                         output_raw = '?';
3475                         break;
3476                 }
3477
3478                 if (output_raw != 0) {
3479                         /* TALOS-CAN-0063: avoid buffer overrun */
3480                         atoascii(name, MAXVARLEN, bn, sizeof(bn));
3481                         if (output_raw != '*') {
3482                                 atoascii(value, MAXVALLEN,
3483                                          bv, sizeof(bv) - 1);
3484                                 len = strlen(bv);
3485                                 bv[len] = output_raw;
3486                                 bv[len+1] = '\0';
3487                         } else {
3488                                 atoascii(value, MAXVALLEN,
3489                                          bv, sizeof(bv));
3490                         }
3491                         output(fp, bn, bv);
3492                 }
3493         }
3494         endoutput(fp);
3495 }
3496
3497
3498 /*
3499  * sortassoc - sort associations in the cache into ascending order
3500  */
3501 void
3502 sortassoc(void)
3503 {
3504         if (numassoc > 1)
3505                 qsort(assoc_cache, (size_t)numassoc,
3506                       sizeof(assoc_cache[0]), &assoccmp);
3507 }
3508
3509
3510 /*
3511  * assoccmp - compare two associations
3512  */
3513 static int
3514 assoccmp(
3515         const void *t1,
3516         const void *t2
3517         )
3518 {
3519         const struct association *ass1 = t1;
3520         const struct association *ass2 = t2;
3521
3522         if (ass1->assid < ass2->assid)
3523                 return -1;
3524         if (ass1->assid > ass2->assid)
3525                 return 1;
3526         return 0;
3527 }
3528
3529
3530 /*
3531  * grow_assoc_cache() - enlarge dynamic assoc_cache array
3532  *
3533  * The strategy is to add an assumed 4k page size at a time, leaving
3534  * room for malloc() bookkeeping overhead equivalent to 4 pointers.
3535  */
3536 void
3537 grow_assoc_cache(void)
3538 {
3539         static size_t   prior_sz;
3540         size_t          new_sz;
3541
3542         new_sz = prior_sz + 4 * 1024;
3543         if (0 == prior_sz) {
3544                 new_sz -= 4 * sizeof(void *);
3545         }
3546         assoc_cache = erealloc_zero(assoc_cache, new_sz, prior_sz); 
3547         prior_sz = new_sz;
3548         assoc_cache_slots = (u_int)(new_sz / sizeof(assoc_cache[0]));
3549 }
3550
3551
3552 /*
3553  * ntpq_custom_opt_handler - autoopts handler for -c and -p
3554  *
3555  * By default, autoopts loses the relative order of -c and -p options
3556  * on the command line.  This routine replaces the default handler for
3557  * those routines and builds a list of commands to execute preserving
3558  * the order.
3559  */
3560 void
3561 ntpq_custom_opt_handler(
3562         tOptions *pOptions,
3563         tOptDesc *pOptDesc
3564         )
3565 {
3566         switch (pOptDesc->optValue) {
3567
3568         default:
3569                 fprintf(stderr,
3570                         "ntpq_custom_opt_handler unexpected option '%c' (%d)\n",
3571                         pOptDesc->optValue, pOptDesc->optValue);
3572                 exit(1);
3573
3574         case 'c':
3575                 ADDCMD(pOptDesc->pzLastArg);
3576                 break;
3577
3578         case 'p':
3579                 ADDCMD("peers");
3580                 break;
3581         }
3582 }
3583 /*
3584  * Obtain list of digest names
3585  */
3586
3587 #ifdef OPENSSL
3588 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3589 struct hstate {
3590    char *list;
3591    const char **seen;
3592    int idx;
3593 };
3594 #define K_PER_LINE 8
3595 #define K_NL_PFX_STR "\n    "
3596 #define K_DELIM_STR ", "
3597 static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg )
3598 {
3599     size_t len, n;
3600     const char *name, *cp, **seen;
3601     struct hstate *hstate = arg;
3602     EVP_MD_CTX *ctx;
3603     u_int digest_len;
3604     u_char digest[EVP_MAX_MD_SIZE];
3605
3606     if (!m)
3607         return; /* Ignore aliases */
3608
3609     name = EVP_MD_name(m);
3610
3611     /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */
3612
3613     for( cp = name; *cp; cp++ ) {
3614         if( islower((unsigned char)*cp) )
3615             return;
3616     }
3617     len = (cp - name) + 1;
3618
3619     /* There are duplicates.  Discard if name has been seen. */
3620
3621     for (seen = hstate->seen; *seen; seen++)
3622         if (!strcmp(*seen, name))
3623             return;
3624     n = (seen - hstate->seen) + 2;
3625     hstate->seen = erealloc(hstate->seen, n * sizeof(*seen));
3626     hstate->seen[n-2] = name;
3627     hstate->seen[n-1] = NULL;
3628
3629     /* Discard MACs that NTP won't accept.
3630      * Keep this consistent with keytype_from_text() in ssl_init.c.
3631      */
3632
3633     ctx = EVP_MD_CTX_new();
3634     EVP_DigestInit(ctx, EVP_get_digestbyname(name));
3635     EVP_DigestFinal(ctx, digest, &digest_len);
3636     EVP_MD_CTX_free(ctx);
3637     if (digest_len > (MAX_MAC_LEN - sizeof(keyid_t)))
3638         return;
3639
3640     if (hstate->list != NULL)
3641         len += strlen(hstate->list);
3642     len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR);
3643
3644     if (hstate->list == NULL) {
3645         hstate->list = (char *)emalloc(len);
3646         hstate->list[0] = '\0';
3647     } else
3648         hstate->list = (char *)erealloc(hstate->list, len);
3649
3650     sprintf(hstate->list + strlen(hstate->list), "%s%s",
3651             ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR),
3652             name);
3653     if (hstate->idx >= K_PER_LINE)
3654         hstate->idx = 1;
3655     else
3656         hstate->idx++;
3657 }
3658 # endif
3659 #endif
3660
3661 static char *list_digest_names(void)
3662 {
3663     char *list = NULL;
3664
3665 #ifdef OPENSSL
3666 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3667     struct hstate hstate = { NULL, NULL, K_PER_LINE+1 };
3668
3669     hstate.seen = (const char **) emalloc_zero(1*sizeof( const char * )); // replaces -> calloc(1, sizeof( const char * ));
3670
3671     INIT_SSL();
3672     EVP_MD_do_all_sorted(list_md_fn, &hstate);
3673     list = hstate.list;
3674     free(hstate.seen);
3675 # else
3676     list = (char *)emalloc(sizeof("md5, others (upgrade to OpenSSL-1.0 for full list)"));
3677     strcpy(list, "md5, others (upgrade to OpenSSL-1.0 for full list)");
3678 # endif
3679 #else
3680     list = (char *)emalloc(sizeof("md5"));
3681     strcpy(list, "md5");
3682 #endif
3683
3684     return list;
3685 }
3686
3687 #define CTRLC_STACK_MAX 4
3688 static volatile size_t          ctrlc_stack_len = 0;
3689 static volatile Ctrl_C_Handler  ctrlc_stack[CTRLC_STACK_MAX];
3690
3691
3692
3693 int/*BOOL*/
3694 push_ctrl_c_handler(
3695         Ctrl_C_Handler func
3696         )
3697 {
3698         size_t size = ctrlc_stack_len;
3699         if (func && (size < CTRLC_STACK_MAX)) {
3700                 ctrlc_stack[size] = func;
3701                 ctrlc_stack_len = size + 1;
3702                 return TRUE;
3703         }
3704         return FALSE;   
3705 }
3706
3707 int/*BOOL*/
3708 pop_ctrl_c_handler(
3709         Ctrl_C_Handler func
3710         )
3711 {
3712         size_t size = ctrlc_stack_len;
3713         if (size) {
3714                 --size;
3715                 if (func == NULL || func == ctrlc_stack[size]) {
3716                         ctrlc_stack_len = size;
3717                         return TRUE;
3718                 }
3719         }
3720         return FALSE;
3721 }
3722
3723 static void
3724 on_ctrlc(void)
3725 {
3726         size_t size = ctrlc_stack_len;
3727         while (size)
3728                 if ((*ctrlc_stack[--size])())
3729                         break;
3730 }
3731
3732 static int
3733 my_easprintf(
3734         char **         ppinto,
3735         const char *    fmt   ,
3736         ...
3737         )
3738 {
3739         va_list va;
3740         int     prc;
3741         size_t  len = 128;
3742         char *  buf = emalloc(len);
3743
3744   again:
3745         /* Note: we expect the memory allocation to fail long before the
3746          * increment in buffer size actually overflows.
3747          */
3748         buf = (buf) ? erealloc(buf, len) : emalloc(len);
3749
3750         va_start(va, fmt);
3751         prc = vsnprintf(buf, len, fmt, va);
3752         va_end(va);
3753
3754         if (prc < 0) {
3755                 /* might be very old vsnprintf. Or actually MSVC... */
3756                 len += len >> 1;
3757                 goto again;
3758         }
3759         if ((size_t)prc >= len) {
3760                 /* at least we have the proper size now... */
3761                 len = (size_t)prc + 1;
3762                 goto again;
3763         }
3764         if ((size_t)prc < (len - 32))
3765                 buf = erealloc(buf, (size_t)prc + 1);
3766         *ppinto = buf;
3767         return prc;
3768 }