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