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