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