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