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