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