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