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