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