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