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