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