xref: /netbsd-src/external/bsd/ntp/dist/ntpdc/ntpdc.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: ntpdc.c,v 1.18 2020/05/25 20:47:26 christos Exp $	*/
2 
3 /*
4  * ntpdc - control and monitor your ntpd daemon
5  */
6 #include <config.h>
7 #include <stdio.h>
8 #include <stddef.h>
9 #include <ctype.h>
10 #include <signal.h>
11 #include <setjmp.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 "ntpdc.h"
25 #include "ntp_select.h"
26 #include "ntp_stdlib.h"
27 #include "ntp_assert.h"
28 #include "ntp_lineedit.h"
29 #ifdef OPENSSL
30 #include "openssl/evp.h"
31 #include "openssl/objects.h"
32 #endif
33 #include <ssl_applink.c>
34 
35 #include "ntp_libopts.h"
36 #include "ntpdc-opts.h"
37 #include "safecast.h"
38 
39 #ifdef SYS_VXWORKS
40 				/* vxWorks needs mode flag -casey*/
41 # define open(name, flags)   open(name, flags, 0777)
42 # define SERVER_PORT_NUM     123
43 #endif
44 
45 /* We use COMMAND as an autogen keyword */
46 #ifdef COMMAND
47 # undef COMMAND
48 #endif
49 
50 /*
51  * Because we now potentially understand a lot of commands (and
52  * it requires a lot of commands to talk to ntpd) we will run
53  * interactive if connected to a terminal.
54  */
55 static	int	interactive = 0;	/* set to 1 when we should prompt */
56 static	const char *	prompt = "ntpdc> ";	/* prompt to ask him about */
57 
58 /*
59  * Keyid used for authenticated requests.  Obtained on the fly.
60  */
61 static	u_long	info_auth_keyid;
62 static int keyid_entered = 0;
63 
64 static	int	info_auth_keytype = NID_md5;	/* MD5 */
65 static	size_t	info_auth_hashlen = 16;		/* MD5 */
66 u_long	current_time;		/* needed by authkeys; not used */
67 
68 /*
69  * for get_systime()
70  */
71 s_char	sys_precision;		/* local clock precision (log2 s) */
72 
73 int		ntpdcmain	(int,	char **);
74 /*
75  * Built in command handler declarations
76  */
77 static	int	openhost	(const char *);
78 static	int	sendpkt		(void *, size_t);
79 static	void	growpktdata	(void);
80 static	int	getresponse	(int, int, size_t *, size_t *, const char **, size_t);
81 static	int	sendrequest	(int, int, int, size_t, size_t, const char *);
82 static	void	getcmds		(void);
83 static	RETSIGTYPE abortcmd	(int);
84 static	void	docmd		(const char *);
85 static	void	tokenize	(const char *, char **, int *);
86 static	int	findcmd		(char *, struct xcmd *, struct xcmd *, struct xcmd **);
87 static	int	getarg		(char *, int, arg_v *);
88 static	int	getnetnum	(const char *, sockaddr_u *, char *, int);
89 static	void	help		(struct parse *, FILE *);
90 static	int	helpsort	(const void *, const void *);
91 static	void	printusage	(struct xcmd *, FILE *);
92 static	void	timeout		(struct parse *, FILE *);
93 static	void	my_delay	(struct parse *, FILE *);
94 static	void	host		(struct parse *, FILE *);
95 static	void	keyid		(struct parse *, FILE *);
96 static	void	keytype		(struct parse *, FILE *);
97 static	void	passwd		(struct parse *, FILE *);
98 static	void	hostnames	(struct parse *, FILE *);
99 static	void	setdebug	(struct parse *, FILE *);
100 static	void	quit		(struct parse *, FILE *);
101 static	void	version		(struct parse *, FILE *);
102 static	void	warning		(const char *, ...)
103     __attribute__((__format__(__printf__, 1, 2)));
104 static	void	error		(const char *, ...)
105     __attribute__((__format__(__printf__, 1, 2)));
106 static	u_long	getkeyid	(const char *);
107 
108 
109 
110 /*
111  * Built-in commands we understand
112  */
113 static	struct xcmd builtins[] = {
114 	{ "?",		help,		{  OPT|NTP_STR, NO, NO, NO },
115 	  { "command", "", "", "" },
116 	  "tell the use and syntax of commands" },
117 	{ "help",	help,		{  OPT|NTP_STR, NO, NO, NO },
118 	  { "command", "", "", "" },
119 	  "tell the use and syntax of commands" },
120 	{ "timeout",	timeout,	{ OPT|NTP_UINT, NO, NO, NO },
121 	  { "msec", "", "", "" },
122 	  "set the primary receive time out" },
123 	{ "delay",	my_delay,	{ OPT|NTP_INT, NO, NO, NO },
124 	  { "msec", "", "", "" },
125 	  "set the delay added to encryption time stamps" },
126 	{ "host",	host,		{ OPT|NTP_STR, OPT|NTP_STR, NO, NO },
127 	  { "-4|-6", "hostname", "", "" },
128 	  "specify the host whose NTP server we talk to" },
129 	{ "passwd",	passwd,		{ OPT|NTP_STR, NO, NO, NO },
130 	  { "", "", "", "" },
131 	  "specify a password to use for authenticated requests"},
132 	{ "hostnames",	hostnames,	{ OPT|NTP_STR, NO, NO, NO },
133 	  { "yes|no", "", "", "" },
134 	  "specify whether hostnames or net numbers are printed"},
135 	{ "debug",	setdebug,	{ OPT|NTP_STR, NO, NO, NO },
136 	  { "no|more|less", "", "", "" },
137 	  "set/change debugging level" },
138 	{ "quit",	quit,		{ NO, NO, NO, NO },
139 	  { "", "", "", "" },
140 	  "exit ntpdc" },
141 	{ "exit",	quit,		{ NO, NO, NO, NO },
142 	  { "", "", "", "" },
143 	  "exit ntpdc" },
144 	{ "keyid",	keyid,		{ OPT|NTP_UINT, NO, NO, NO },
145 	  { "key#", "", "", "" },
146 	  "set/show keyid to use for authenticated requests" },
147 	{ "keytype",	keytype,	{ OPT|NTP_STR, NO, NO, NO },
148 	  { "(md5|des)", "", "", "" },
149 	  "set/show key authentication type for authenticated requests (des|md5)" },
150 	{ "version",	version,	{ NO, NO, NO, NO },
151 	  { "", "", "", "" },
152 	  "print version number" },
153 	{ 0,		0,		{ NO, NO, NO, NO },
154 	  { "", "", "", "" }, "" }
155 };
156 
157 
158 /*
159  * Default values we use.
160  */
161 #define	DEFHOST		"localhost"	/* default host name */
162 #define	DEFTIMEOUT	(5)		/* 5 second time out */
163 #define	DEFSTIMEOUT	(2)		/* 2 second time out after first */
164 #define	DEFDELAY	0x51EB852	/* 20 milliseconds, l_fp fraction */
165 #define	LENHOSTNAME	256		/* host name is 256 characters long */
166 #define	MAXCMDS		100		/* maximum commands on cmd line */
167 #define	MAXHOSTS	200		/* maximum hosts on cmd line */
168 #define	MAXLINE		512		/* maximum line length */
169 #define	MAXTOKENS	(1+1+MAXARGS+MOREARGS+2)	/* maximum number of usable tokens */
170 #define	SCREENWIDTH  	78		/* nominal screen width in columns */
171 
172 /*
173  * Some variables used and manipulated locally
174  */
175 static	struct sock_timeval tvout = { DEFTIMEOUT, 0 };	/* time out for reads */
176 static	struct sock_timeval tvsout = { DEFSTIMEOUT, 0 };/* secondary time out */
177 static	l_fp delay_time;				/* delay time */
178 static	char currenthost[LENHOSTNAME];			/* current host name */
179 int showhostnames = 1;					/* show host names by default */
180 
181 static	int ai_fam_templ = AF_UNSPEC;		/* address family */
182 static	int ai_fam_default = AF_UNSPEC;	/* default address family */
183 static	SOCKET sockfd;					/* fd socket is opened on */
184 static	int havehost = 0;				/* set to 1 when host open */
185 int s_port = 0;
186 
187 /*
188  * Holds data returned from queries.  We allocate INITDATASIZE
189  * octets to begin with, increasing this as we need to.
190  */
191 #define	INITDATASIZE	(sizeof(struct resp_pkt) * 16)
192 #define	INCDATASIZE	(sizeof(struct resp_pkt) * 8)
193 
194 static	char *pktdata;
195 static	int pktdatasize;
196 
197 /*
198  * These are used to help the magic with old and new versions of ntpd.
199  */
200 int impl_ver = IMPL_XNTPD;
201 static int req_pkt_size = REQ_LEN_NOMAC;
202 
203 /*
204  * For commands typed on the command line (with the -c option)
205  */
206 static	int numcmds = 0;
207 static	const char *ccmds[MAXCMDS];
208 #define	ADDCMD(cp)	if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp)
209 
210 /*
211  * When multiple hosts are specified.
212  */
213 static	int numhosts = 0;
214 static	const char *chosts[MAXHOSTS];
215 #define	ADDHOST(cp)	if (numhosts < MAXHOSTS) chosts[numhosts++] = (cp)
216 
217 /*
218  * Error codes for internal use
219  */
220 #define	ERR_INCOMPLETE		16
221 #define	ERR_TIMEOUT		17
222 
223 /*
224  * Macro definitions we use
225  */
226 #define	ISSPACE(c)	((c) == ' ' || (c) == '\t')
227 #define	ISEOL(c)	((c) == '\n' || (c) == '\r' || (c) == '\0')
228 #define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
229 
230 /*
231  * Jump buffer for longjumping back to the command level.
232  *
233  * See ntpq/ntpq.c for an explanation why 'sig{set,long}jmp()' is used
234  * when available.
235  */
236 #if HAVE_DECL_SIGSETJMP && HAVE_DECL_SIGLONGJMP
237 # define JMP_BUF	sigjmp_buf
238 # define SETJMP(x)	sigsetjmp((x), 1)
239 # define LONGJMP(x, v)	siglongjmp((x),(v))
240 #else
241 # define JMP_BUF	jmp_buf
242 # define SETJMP(x)	setjmp((x))
243 # define LONGJMP(x, v)	longjmp((x),(v))
244 #endif
245 static	JMP_BUF		interrupt_buf;
246 static	volatile int	jump = 0;
247 
248 /*
249  * Pointer to current output unit
250  */
251 static	FILE *current_output = NULL;
252 
253 /*
254  * Command table imported from ntpdc_ops.c
255  */
256 extern struct xcmd opcmds[];
257 
258 char const *progname;
259 
260 #ifdef NO_MAIN_ALLOWED
261 CALL(ntpdc,"ntpdc",ntpdcmain);
262 #else
263 int
264 main(
265 	int argc,
266 	char *argv[]
267 	)
268 {
269 	return ntpdcmain(argc, argv);
270 }
271 #endif
272 
273 #ifdef SYS_VXWORKS
274 void clear_globals(void)
275 {
276     showhostnames = 0;              /* show host names by default */
277     havehost = 0;                   /* set to 1 when host open */
278     numcmds = 0;
279     numhosts = 0;
280 }
281 #endif
282 
283 /*
284  * main - parse arguments and handle options
285  */
286 int
287 ntpdcmain(
288 	int argc,
289 	char *argv[]
290 	)
291 {
292 	delay_time.l_ui = 0;
293 	delay_time.l_uf = DEFDELAY;
294 
295 #ifdef SYS_VXWORKS
296 	clear_globals();
297 	taskPrioritySet(taskIdSelf(), 100 );
298 #endif
299 
300 	init_lib();	/* sets up ipv4_works, ipv6_works */
301 	ssl_applink();
302 	init_auth();
303 
304 	/* Check to see if we have IPv6. Otherwise default to IPv4 */
305 	if (!ipv6_works)
306 		ai_fam_default = AF_INET;
307 
308 	progname = argv[0];
309 
310 	{
311 		int optct = ntpOptionProcess(&ntpdcOptions, argc, argv);
312 		argc -= optct;
313 		argv += optct;
314 	}
315 
316 	if (HAVE_OPT(IPV4))
317 		ai_fam_default = AF_INET;
318 	else if (HAVE_OPT(IPV6))
319 		ai_fam_default = AF_INET6;
320 
321 	ai_fam_templ = ai_fam_default;
322 
323 	if (HAVE_OPT(COMMAND)) {
324 		int		cmdct = STACKCT_OPT( COMMAND );
325 		const char**	cmds  = STACKLST_OPT( COMMAND );
326 
327 		while (cmdct-- > 0) {
328 			ADDCMD(*cmds++);
329 		}
330 	}
331 
332 	debug = OPT_VALUE_SET_DEBUG_LEVEL;
333 
334 	if (HAVE_OPT(INTERACTIVE)) {
335 		interactive = 1;
336 	}
337 
338 	if (HAVE_OPT(NUMERIC)) {
339 		showhostnames = 0;
340 	}
341 
342 	if (HAVE_OPT(LISTPEERS)) {
343 		ADDCMD("listpeers");
344 	}
345 
346 	if (HAVE_OPT(PEERS)) {
347 		ADDCMD("peers");
348 	}
349 
350 	if (HAVE_OPT(SHOWPEERS)) {
351 		ADDCMD("dmpeers");
352 	}
353 
354 	if (ntp_optind == argc) {
355 		ADDHOST(DEFHOST);
356 	} else {
357 		for (; ntp_optind < argc; ntp_optind++)
358 		    ADDHOST(argv[ntp_optind]);
359 	}
360 
361 	if (numcmds == 0 && interactive == 0
362 	    && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
363 		interactive = 1;
364 	}
365 
366 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
367 	if (interactive)
368 		(void) signal_no_reset(SIGINT, abortcmd);
369 #endif /* SYS_WINNT */
370 
371 	/*
372 	 * Initialize the packet data buffer
373 	 */
374 	pktdatasize = INITDATASIZE;
375 	pktdata = emalloc(INITDATASIZE);
376 
377 	if (numcmds == 0) {
378 		(void) openhost(chosts[0]);
379 		getcmds();
380 	} else {
381 		int ihost;
382 		int icmd;
383 
384 		for (ihost = 0; ihost < numhosts; ihost++) {
385 			if (openhost(chosts[ihost]))
386 			    for (icmd = 0; icmd < numcmds; icmd++) {
387 				    if (numhosts > 1)
388 					printf ("--- %s ---\n",chosts[ihost]);
389 				    docmd(ccmds[icmd]);
390 			    }
391 		}
392 	}
393 #ifdef SYS_WINNT
394 	WSACleanup();
395 #endif
396 	return(0);
397 } /* main end */
398 
399 
400 /*
401  * openhost - open a socket to a host
402  */
403 static int
404 openhost(
405 	const char *hname
406 	)
407 {
408 	char temphost[LENHOSTNAME];
409 	int a_info;
410 	struct addrinfo hints, *ai = NULL;
411 	sockaddr_u addr;
412 	size_t octets;
413 	const char *cp;
414 	char name[LENHOSTNAME];
415 	char service[5];
416 
417 	/*
418 	 * We need to get by the [] if they were entered
419 	 */
420 	if (*hname == '[') {
421 		cp = strchr(hname + 1, ']');
422 		if (!cp || (octets = (size_t)(cp - hname) - 1) >= sizeof(name)) {
423 			errno = EINVAL;
424 			warning("%s", "bad hostname/address");
425 			return 0;
426 		}
427 		memcpy(name, hname + 1, octets);
428 		name[octets] = '\0';
429 		hname = name;
430 	}
431 
432 	/*
433 	 * First try to resolve it as an ip address and if that fails,
434 	 * do a fullblown (dns) lookup. That way we only use the dns
435 	 * when it is needed and work around some implementations that
436 	 * will return an "IPv4-mapped IPv6 address" address if you
437 	 * give it an IPv4 address to lookup.
438 	 */
439 	strlcpy(service, "ntp", sizeof(service));
440 	ZERO(hints);
441 	hints.ai_family = ai_fam_templ;
442 	hints.ai_protocol = IPPROTO_UDP;
443 	hints.ai_socktype = SOCK_DGRAM;
444 	hints.ai_flags = Z_AI_NUMERICHOST;
445 
446 	a_info = getaddrinfo(hname, service, &hints, &ai);
447 	if (a_info == EAI_NONAME
448 #ifdef EAI_NODATA
449 	    || a_info == EAI_NODATA
450 #endif
451 	   ) {
452 		hints.ai_flags = AI_CANONNAME;
453 #ifdef AI_ADDRCONFIG
454 		hints.ai_flags |= AI_ADDRCONFIG;
455 #endif
456 		a_info = getaddrinfo(hname, service, &hints, &ai);
457 	}
458 	/* Some older implementations don't like AI_ADDRCONFIG. */
459 	if (a_info == EAI_BADFLAGS) {
460 		hints.ai_flags = AI_CANONNAME;
461 		a_info = getaddrinfo(hname, service, &hints, &ai);
462 	}
463 	if (a_info != 0) {
464 		fprintf(stderr, "%s\n", gai_strerror(a_info));
465 		if (ai != NULL)
466 			freeaddrinfo(ai);
467 		return 0;
468 	}
469 
470 	/*
471 	 * getaddrinfo() has returned without error so ai should not
472 	 * be NULL.
473 	 */
474 	INSIST(ai != NULL);
475 	ZERO(addr);
476 	octets = min(sizeof(addr), ai->ai_addrlen);
477 	memcpy(&addr, ai->ai_addr, octets);
478 
479 	if (ai->ai_canonname == NULL)
480 		strlcpy(temphost, stoa(&addr), sizeof(temphost));
481 	else
482 		strlcpy(temphost, ai->ai_canonname, sizeof(temphost));
483 
484 	if (debug > 2)
485 		printf("Opening host %s\n", temphost);
486 
487 	if (havehost == 1) {
488 		if (debug > 2)
489 			printf("Closing old host %s\n", currenthost);
490 		closesocket(sockfd);
491 		havehost = 0;
492 	}
493 	strlcpy(currenthost, temphost, sizeof(currenthost));
494 
495 	/* port maps to the same in both families */
496 	s_port = NSRCPORT(&addr);;
497 #ifdef SYS_VXWORKS
498 	((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
499 	if (ai->ai_family == AF_INET)
500 		*(struct sockaddr_in *)&hostaddr=
501 			*((struct sockaddr_in *)ai->ai_addr);
502 	else
503 		*(struct sockaddr_in6 *)&hostaddr=
504 			*((struct sockaddr_in6 *)ai->ai_addr);
505 #endif /* SYS_VXWORKS */
506 
507 #ifdef SYS_WINNT
508 	{
509 		int optionValue = SO_SYNCHRONOUS_NONALERT;
510 		int err;
511 
512 		err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (void *)&optionValue, sizeof(optionValue));
513 		if (err != NO_ERROR) {
514 			(void) fprintf(stderr, "cannot open nonoverlapped sockets\n");
515 			exit(1);
516 		}
517 	}
518 #endif /* SYS_WINNT */
519 
520 	sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
521 	if (sockfd == INVALID_SOCKET) {
522 		error("socket");
523 		exit(-1);
524 	}
525 
526 #ifdef NEED_RCVBUF_SLOP
527 # ifdef SO_RCVBUF
528 	{
529 		int rbufsize = INITDATASIZE + 2048; /* 2K for slop */
530 
531 		if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
532 			       (void *)&rbufsize, sizeof(int)) == -1)
533 		    error("setsockopt");
534 	}
535 # endif
536 #endif
537 
538 #ifdef SYS_VXWORKS
539 	if (connect(sockfd, (struct sockaddr *)&hostaddr,
540 		    sizeof(hostaddr)) == -1)
541 #else
542 	if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == -1)
543 #endif /* SYS_VXWORKS */
544 	{
545 		error("connect");
546 		exit(-1);
547 	}
548 
549 	freeaddrinfo(ai);
550 	havehost = 1;
551 	req_pkt_size = REQ_LEN_NOMAC;
552 	impl_ver = IMPL_XNTPD;
553 	return 1;
554 }
555 
556 
557 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
558 /*
559  * sendpkt - send a packet to the remote host
560  */
561 static int
562 sendpkt(
563 	void *	xdata,
564 	size_t	xdatalen
565 	)
566 {
567 	if (send(sockfd, xdata, xdatalen, 0) == -1) {
568 		warning("write to %s failed", currenthost);
569 		return -1;
570 	}
571 
572 	return 0;
573 }
574 
575 
576 /*
577  * growpktdata - grow the packet data area
578  */
579 static void
580 growpktdata(void)
581 {
582 	size_t priorsz;
583 
584 	priorsz = (size_t)pktdatasize;
585 	pktdatasize += INCDATASIZE;
586 	pktdata = erealloc_zero(pktdata, (size_t)pktdatasize, priorsz);
587 }
588 
589 
590 /*
591  * getresponse - get a (series of) response packet(s) and return the data
592  */
593 static int
594 getresponse(
595 	int implcode,
596 	int reqcode,
597 	size_t *ritems,
598 	size_t *rsize,
599 	const char **rdata,
600 	size_t esize
601 	)
602 {
603 	struct resp_pkt rpkt;
604 	struct sock_timeval tvo;
605 	size_t items;
606 	size_t i;
607 	size_t size;
608 	size_t datasize;
609 	char *datap;
610 	char *tmp_data;
611 	char haveseq[MAXSEQ+1];
612 	int firstpkt;
613 	int lastseq;
614 	int numrecv;
615 	int seq;
616 	fd_set fds;
617 	ssize_t n;
618 	int pad;
619 	/* absolute timeout checks. Not 'time_t' by intention! */
620 	uint32_t tobase;	/* base value for timeout */
621 	uint32_t tospan;	/* timeout span (max delay) */
622 	uint32_t todiff;	/* current delay */
623 
624 	/*
625 	 * This is pretty tricky.  We may get between 1 and many packets
626 	 * back in response to the request.  We peel the data out of
627 	 * each packet and collect it in one long block.  When the last
628 	 * packet in the sequence is received we'll know how many we
629 	 * should have had.  Note we use one long time out, should reconsider.
630 	 */
631 	*ritems = 0;
632 	*rsize = 0;
633 	firstpkt = 1;
634 	numrecv = 0;
635 	*rdata = datap = pktdata;
636 	lastseq = 999;	/* too big to be a sequence number */
637 	ZERO(haveseq);
638 	FD_ZERO(&fds);
639 	tobase = (uint32_t)time(NULL);
640 
641     again:
642 	if (firstpkt)
643 		tvo = tvout;
644 	else
645 		tvo = tvsout;
646 	tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
647 
648 	FD_SET(sockfd, &fds);
649 	n = select(sockfd+1, &fds, NULL, NULL, &tvo);
650 	if (n == -1) {
651 		warning("select fails");
652 		return -1;
653 	}
654 
655 	/*
656 	 * Check if this is already too late. Trash the data and fake a
657 	 * timeout if this is so.
658 	 */
659 	todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
660 	if ((n > 0) && (todiff > tospan)) {
661 		n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
662 		n -= n; /* faked timeout return from 'select()'*/
663 	}
664 
665 	if (n == 0) {
666 		/*
667 		 * Timed out.  Return what we have
668 		 */
669 		if (firstpkt) {
670 			(void) fprintf(stderr,
671 				       "%s: timed out, nothing received\n",
672 				       currenthost);
673 			return ERR_TIMEOUT;
674 		} else {
675 			(void) fprintf(stderr,
676 				       "%s: timed out with incomplete data\n",
677 				       currenthost);
678 			if (debug) {
679 				printf("Received sequence numbers");
680 				for (n = 0; n <= MAXSEQ; n++)
681 				    if (haveseq[n])
682 					printf(" %zd,", (size_t)n);
683 				if (lastseq != 999)
684 				    printf(" last frame received\n");
685 				else
686 				    printf(" last frame not received\n");
687 			}
688 			return ERR_INCOMPLETE;
689 		}
690 	}
691 
692 	n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
693 	if (n == -1) {
694 		warning("read");
695 		return -1;
696 	}
697 
698 
699 	/*
700 	 * Check for format errors.  Bug proofing.
701 	 */
702 	if (n < (ssize_t)RESP_HEADER_SIZE) {
703 		if (debug)
704 			printf("Short (%zd byte) packet received\n", (size_t)n);
705 		goto again;
706 	}
707 	if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION ||
708 	    INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) {
709 		if (debug)
710 			printf("Packet received with version %d\n",
711 			       INFO_VERSION(rpkt.rm_vn_mode));
712 		goto again;
713 	}
714 	if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) {
715 		if (debug)
716 			printf("Packet received with mode %d\n",
717 			       INFO_MODE(rpkt.rm_vn_mode));
718 		goto again;
719 	}
720 	if (INFO_IS_AUTH(rpkt.auth_seq)) {
721 		if (debug)
722 			printf("Encrypted packet received\n");
723 		goto again;
724 	}
725 	if (!ISRESPONSE(rpkt.rm_vn_mode)) {
726 		if (debug)
727 			printf("Received request packet, wanted response\n");
728 		goto again;
729 	}
730 	if (INFO_MBZ(rpkt.mbz_itemsize) != 0) {
731 		if (debug)
732 			printf("Received packet with nonzero MBZ field!\n");
733 		goto again;
734 	}
735 
736 	/*
737 	 * Check implementation/request.  Could be old data getting to us.
738 	 */
739 	if (rpkt.implementation != implcode || rpkt.request != reqcode) {
740 		if (debug)
741 			printf(
742 			    "Received implementation/request of %d/%d, wanted %d/%d",
743 			    rpkt.implementation, rpkt.request,
744 			    implcode, reqcode);
745 		goto again;
746 	}
747 
748 	/*
749 	 * Check the error code.  If non-zero, return it.
750 	 */
751 	if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) {
752 		if (debug && ISMORE(rpkt.rm_vn_mode)) {
753 			printf("Error code %d received on not-final packet\n",
754 			       INFO_ERR(rpkt.err_nitems));
755 		}
756 		return (int)INFO_ERR(rpkt.err_nitems);
757 	}
758 
759 	/*
760 	 * Collect items and size.  Make sure they make sense.
761 	 */
762 	items = INFO_NITEMS(rpkt.err_nitems);
763 	size = INFO_ITEMSIZE(rpkt.mbz_itemsize);
764 	if (esize > size)
765 		pad = esize - size;
766 	else
767 		pad = 0;
768 	datasize = items * size;
769 	if ((size_t)datasize > (n-RESP_HEADER_SIZE)) {
770 		if (debug)
771 		    printf(
772 			    "Received items %zu, size %zu (total %zu), data in packet is %zu\n",
773 			    items, size, datasize, n-RESP_HEADER_SIZE);
774 		goto again;
775 	}
776 
777 	/*
778 	 * If this isn't our first packet, make sure the size matches
779 	 * the other ones.
780 	 */
781 	if (!firstpkt && size != *rsize) {
782 		if (debug)
783 		    printf("Received itemsize %zu, previous %zu\n",
784 			   size, *rsize);
785 		goto again;
786 	}
787 	/*
788 	 * If we've received this before, +toss it
789 	 */
790 	seq = INFO_SEQ(rpkt.auth_seq);
791 	if (haveseq[seq]) {
792 		if (debug)
793 		    printf("Received duplicate sequence number %d\n", seq);
794 		goto again;
795 	}
796 	haveseq[seq] = 1;
797 
798 	/*
799 	 * If this is the last in the sequence, record that.
800 	 */
801 	if (!ISMORE(rpkt.rm_vn_mode)) {
802 		if (lastseq != 999) {
803 			printf("Received second end sequence packet\n");
804 			goto again;
805 		}
806 		lastseq = seq;
807 	}
808 
809 	/*
810 	 * So far, so good.  Copy this data into the output array. Bump
811 	 * the timeout base, in case we expect more data.
812 	 */
813 	tobase = (uint32_t)time(NULL);
814 	if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
815 		size_t offset = datap - pktdata;
816 		growpktdata();
817 		*rdata = pktdata; /* might have been realloced ! */
818 		datap = pktdata + offset;
819 	}
820 	/*
821 	 * We now move the pointer along according to size and number of
822 	 * items.  This is so we can play nice with older implementations
823 	 */
824 
825 	tmp_data = rpkt.u.data;
826 	for (i = 0; i < items; i++) {
827 		memcpy(datap, tmp_data, (unsigned)size);
828 		tmp_data += size;
829 		zero_mem(datap + size, pad);
830 		datap += size + pad;
831 	}
832 
833 	if (firstpkt) {
834 		firstpkt = 0;
835 		*rsize = size + pad;
836 	}
837 	*ritems += items;
838 
839 	/*
840 	 * Finally, check the count of received packets.  If we've got them
841 	 * all, return
842 	 */
843 	++numrecv;
844 	if (numrecv <= lastseq)
845 		goto again;
846 	return INFO_OKAY;
847 }
848 
849 
850 /*
851  * sendrequest - format and send a request packet
852  *
853  * Historically, ntpdc has used a fixed-size request packet regardless
854  * of the actual payload size.  When authenticating, the timestamp, key
855  * ID, and digest have been placed just before the end of the packet.
856  * With the introduction in late 2009 of support for authenticated
857  * ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we
858  * come up four bytes short.
859  *
860  * To maintain interop while allowing for larger digests, the behavior
861  * is unchanged when using 16-octet digests.  For larger digests, the
862  * timestamp, key ID, and digest are placed immediately following the
863  * request payload, with the overall packet size variable.  ntpd can
864  * distinguish 16-octet digests by the overall request size being
865  * REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled.  When using a
866  * longer digest, that request size should be avoided.
867  *
868  * With the form used with 20-octet and larger digests, the timestamp,
869  * key ID, and digest are located by ntpd relative to the start of the
870  * packet, and the size of the digest is then implied by the packet
871  * size.
872  */
873 static int
874 sendrequest(
875 	int implcode,
876 	int reqcode,
877 	int auth,
878 	size_t qitems,
879 	size_t qsize,
880 	const char *qdata
881 	)
882 {
883 	struct req_pkt qpkt;
884 	size_t	datasize;
885 	size_t	reqsize;
886 	u_long	key_id;
887 	l_fp	ts;
888 	l_fp *	ptstamp;
889 	size_t	maclen;
890 	char *	pass;
891 
892 	ZERO(qpkt);
893 	qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
894 	qpkt.implementation = (u_char)implcode;
895 	qpkt.request = (u_char)reqcode;
896 
897 	datasize = qitems * qsize;
898 	if (datasize && qdata != NULL) {
899 		memcpy(qpkt.u.data, qdata, datasize);
900 		qpkt.err_nitems = ERR_NITEMS(0, qitems);
901 		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);
902 	} else {
903 		qpkt.err_nitems = ERR_NITEMS(0, 0);
904 		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);  /* allow for optional first item */
905 	}
906 
907 	if (!auth || (keyid_entered && info_auth_keyid == 0)) {
908 		qpkt.auth_seq = AUTH_SEQ(0, 0);
909 		return sendpkt(&qpkt, req_pkt_size);
910 	}
911 
912 	if (info_auth_keyid == 0) {
913 		key_id = getkeyid("Keyid: ");
914 		if (!key_id) {
915 			fprintf(stderr, "Invalid key identifier\n");
916 			return 1;
917 		}
918 		info_auth_keyid = key_id;
919 	}
920 	if (!authistrusted(info_auth_keyid)) {
921 		pass = getpass_keytype(info_auth_keytype);
922 		if ('\0' == pass[0]) {
923 			fprintf(stderr, "Invalid password\n");
924 			return 1;
925 		}
926 		authusekey(info_auth_keyid, info_auth_keytype,
927 			   (u_char *)pass);
928 		authtrust(info_auth_keyid, 1);
929 	}
930 	qpkt.auth_seq = AUTH_SEQ(1, 0);
931 	if (info_auth_hashlen > 16) {
932 		/*
933 		 * Only ntpd which expects REQ_LEN_NOMAC plus maclen
934 		 * octets in an authenticated request using a 16 octet
935 		 * digest (that is, a newer ntpd) will handle digests
936 		 * larger than 16 octets, so for longer digests, do
937 		 * not attempt to shorten the requests for downlevel
938 		 * ntpd compatibility.
939 		 */
940 		if (REQ_LEN_NOMAC != req_pkt_size)
941 			return 1;
942 		reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp);
943 		/* align to 32 bits */
944 		reqsize = (reqsize + 3) & ~3;
945 	} else
946 		reqsize = req_pkt_size;
947 	ptstamp = (void *)((char *)&qpkt + reqsize);
948 	ptstamp--;
949 	get_systime(&ts);
950 	L_ADD(&ts, &delay_time);
951 	HTONL_FP(&ts, ptstamp);
952 	maclen = authencrypt(
953 		info_auth_keyid, (void *)&qpkt, size2int_chk(reqsize));
954 	if (!maclen) {
955 		fprintf(stderr, "Key not found\n");
956 		return 1;
957 	} else if (maclen != (size_t)(info_auth_hashlen + sizeof(keyid_t))) {
958 		fprintf(stderr,
959 			"%zu octet MAC, %zu expected with %zu octet digest\n",
960 			maclen, (info_auth_hashlen + sizeof(keyid_t)),
961 			info_auth_hashlen);
962 		return 1;
963 	}
964 	return sendpkt(&qpkt, reqsize + maclen);
965 }
966 
967 
968 /*
969  * doquery - send a request and process the response
970  */
971 int
972 doquery(
973 	int implcode,
974 	int reqcode,
975 	int auth,
976 	size_t qitems,
977 	size_t qsize,
978 	const char *qdata,
979 	size_t *ritems,
980 	size_t *rsize,
981 	const char **rdata,
982  	int quiet_mask,
983 	int esize
984 	)
985 {
986 	int res;
987 	char junk[512];
988 	fd_set fds;
989 	struct sock_timeval tvzero;
990 
991 	/*
992 	 * Check to make sure host is open
993 	 */
994 	if (!havehost) {
995 		(void) fprintf(stderr, "***No host open, use `host' command\n");
996 		return -1;
997 	}
998 
999 	/*
1000 	 * Poll the socket and clear out any pending data
1001 	 */
1002 again:
1003 	do {
1004 		tvzero.tv_sec = tvzero.tv_usec = 0;
1005 		FD_ZERO(&fds);
1006 		FD_SET(sockfd, &fds);
1007 		res = select(sockfd+1, &fds, NULL, NULL, &tvzero);
1008 		if (res == -1) {
1009 			warning("polling select");
1010 			return -1;
1011 		} else if (res > 0)
1012 
1013 		    (void) recv(sockfd, junk, sizeof junk, 0);
1014 	} while (res > 0);
1015 
1016 
1017 	/*
1018 	 * send a request
1019 	 */
1020 	res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata);
1021 	if (res != 0)
1022 		return res;
1023 
1024 	/*
1025 	 * Get the response.  If we got a standard error, print a message
1026 	 */
1027 	res = getresponse(implcode, reqcode, ritems, rsize, rdata, esize);
1028 
1029 	/*
1030 	 * Try to be compatible with older implementations of ntpd.
1031 	 */
1032 	if (res == INFO_ERR_FMT && req_pkt_size != 48) {
1033 		int oldsize;
1034 
1035 		oldsize = req_pkt_size;
1036 
1037 		switch(req_pkt_size) {
1038 		case REQ_LEN_NOMAC:
1039 			req_pkt_size = 160;
1040 			break;
1041 		case 160:
1042 			req_pkt_size = 48;
1043 			break;
1044 		}
1045 		if (impl_ver == IMPL_XNTPD) {
1046 			fprintf(stderr,
1047 			    "***Warning changing to older implementation\n");
1048 			return INFO_ERR_IMPL;
1049 		}
1050 
1051 		fprintf(stderr,
1052 		    "***Warning changing the request packet size from %d to %d\n",
1053 		    oldsize, req_pkt_size);
1054 		goto again;
1055 	}
1056 
1057  	/* log error message if not told to be quiet */
1058  	if ((res > 0) && (((1 << res) & quiet_mask) == 0)) {
1059 		switch(res) {
1060 		case INFO_ERR_IMPL:
1061 			/* Give us a chance to try the older implementation. */
1062 			if (implcode == IMPL_XNTPD)
1063 				break;
1064 			(void) fprintf(stderr,
1065 				       "***Server implementation incompatible with our own\n");
1066 			break;
1067 		case INFO_ERR_REQ:
1068 			(void) fprintf(stderr,
1069 				       "***Server doesn't implement this request\n");
1070 			break;
1071 		case INFO_ERR_FMT:
1072 			(void) fprintf(stderr,
1073 				       "***Server reports a format error in the received packet (shouldn't happen)\n");
1074 			break;
1075 		case INFO_ERR_NODATA:
1076 			(void) fprintf(stderr,
1077 				       "***Server reports data not found\n");
1078 			break;
1079 		case INFO_ERR_AUTH:
1080 			(void) fprintf(stderr, "***Permission denied\n");
1081 			break;
1082 		case ERR_TIMEOUT:
1083 			(void) fprintf(stderr, "***Request timed out\n");
1084 			break;
1085 		case ERR_INCOMPLETE:
1086 			(void) fprintf(stderr,
1087 				       "***Response from server was incomplete\n");
1088 			break;
1089 		default:
1090 			(void) fprintf(stderr,
1091 				       "***Server returns unknown error code %d\n", res);
1092 			break;
1093 		}
1094 	}
1095 	return res;
1096 }
1097 
1098 
1099 /*
1100  * getcmds - read commands from the standard input and execute them
1101  */
1102 static void
1103 getcmds(void)
1104 {
1105 	char *	line;
1106 	int	count;
1107 
1108 	ntp_readline_init(interactive ? prompt : NULL);
1109 
1110 	for (;;) {
1111 		line = ntp_readline(&count);
1112 		if (NULL == line)
1113 			break;
1114 		docmd(line);
1115 		free(line);
1116 	}
1117 
1118 	ntp_readline_uninit();
1119 }
1120 
1121 
1122 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
1123 /*
1124  * abortcmd - catch interrupts and abort the current command
1125  */
1126 static RETSIGTYPE
1127 abortcmd(
1128 	int sig
1129 	)
1130 {
1131 	if (current_output == stdout)
1132 		(void)fflush(stdout);
1133 	putc('\n', stderr);
1134 	(void)fflush(stderr);
1135 	if (jump) {
1136 		jump = 0;
1137 		LONGJMP(interrupt_buf, 1);
1138 	}
1139 }
1140 #endif /* SYS_WINNT */
1141 
1142 /*
1143  * docmd - decode the command line and execute a command
1144  */
1145 static void
1146 docmd(
1147 	const char *cmdline
1148 	)
1149 {
1150 	char *tokens[1+MAXARGS+MOREARGS+2];
1151 	struct parse pcmd;
1152 	int ntok;
1153 	int i, ti;
1154 	int rval;
1155 	struct xcmd *xcmd;
1156 
1157 	ai_fam_templ = ai_fam_default;
1158 	/*
1159 	 * Tokenize the command line.  If nothing on it, return.
1160 	 */
1161 	if (strlen(cmdline) >= MAXLINE) {
1162 		fprintf(stderr, "***Command ignored, more than %d characters:\n%s\n",
1163 			MAXLINE - 1, cmdline);
1164 		return;
1165 	}
1166 	tokenize(cmdline, tokens, &ntok);
1167 	if (ntok == 0)
1168 	    return;
1169 
1170 	/*
1171 	 * Find the appropriate command description.
1172 	 */
1173 	i = findcmd(tokens[0], builtins, opcmds, &xcmd);
1174 	if (i == 0) {
1175 		(void) fprintf(stderr, "***Command `%s' unknown\n",
1176 			       tokens[0]);
1177 		return;
1178 	} else if (i >= 2) {
1179 		(void) fprintf(stderr, "***Command `%s' ambiguous\n",
1180 			       tokens[0]);
1181 		return;
1182 	}
1183 
1184 	/*
1185 	 * Save the keyword, then walk through the arguments, interpreting
1186 	 * as we go.
1187 	 */
1188 	pcmd.keyword = tokens[0];
1189 	pcmd.nargs = 0;
1190 	ti = 1;
1191 	for (i = 0; i < MAXARGS && xcmd->arg[i] != NO;) {
1192 		if ((i+ti) >= ntok) {
1193 			if (!(xcmd->arg[i] & OPT)) {
1194 				printusage(xcmd, stderr);
1195 				return;
1196 			}
1197 			break;
1198 		}
1199 		if ((xcmd->arg[i] & OPT) && (*tokens[i+ti] == '>'))
1200 			break;
1201 		rval = getarg(tokens[i+ti], (int)xcmd->arg[i], &pcmd.argval[i]);
1202 		if (rval == -1) {
1203 			ti++;
1204 			continue;
1205 		}
1206 		if (rval == 0)
1207 			return;
1208 		pcmd.nargs++;
1209 		i++;
1210 	}
1211 
1212 	/* Any extra args are assumed to be "OPT|NTP_STR". */
1213 	for ( ; i < MAXARGS + MOREARGS;) {
1214 	     if ((i+ti) >= ntok)
1215 		  break;
1216 		rval = getarg(tokens[i+ti], (int)(OPT|NTP_STR), &pcmd.argval[i]);
1217 		if (rval == -1) {
1218 			ti++;
1219 			continue;
1220 		}
1221 		if (rval == 0)
1222 			return;
1223 		pcmd.nargs++;
1224 		i++;
1225 	}
1226 
1227 	i += ti;
1228 	if (i < ntok && *tokens[i] == '>') {
1229 		char *fname;
1230 
1231 		if (*(tokens[i]+1) != '\0')
1232 		    fname = tokens[i]+1;
1233 		else if ((i+1) < ntok)
1234 		    fname = tokens[i+1];
1235 		else {
1236 			(void) fprintf(stderr, "***No file for redirect\n");
1237 			return;
1238 		}
1239 
1240 		current_output = fopen(fname, "w");
1241 		if (current_output == NULL) {
1242 			(void) fprintf(stderr, "***Error opening %s: ", fname);
1243 			perror("");
1244 			return;
1245 		}
1246 	} else {
1247 		current_output = stdout;
1248 	}
1249 
1250 	if (interactive) {
1251 		if ( ! SETJMP(interrupt_buf)) {
1252 			jump = 1;
1253 			(xcmd->handler)(&pcmd, current_output);
1254 			jump = 0;
1255 		} else {
1256 			fflush(current_output);
1257 			fputs("\n >>> command aborted <<<\n", stderr);
1258 			fflush(stderr);
1259 		}
1260 	} else {
1261 		jump = 0;
1262 		(xcmd->handler)(&pcmd, current_output);
1263 	}
1264 	if ((NULL != current_output) && (stdout != current_output)) {
1265 		(void)fclose(current_output);
1266 		current_output = NULL;
1267 	}
1268 }
1269 
1270 
1271 /*
1272  * tokenize - turn a command line into tokens
1273  */
1274 static void
1275 tokenize(
1276 	const char *line,
1277 	char **tokens,
1278 	int *ntok
1279 	)
1280 {
1281 	register const char *cp;
1282 	register char *sp;
1283 	static char tspace[MAXLINE];
1284 
1285 	sp = tspace;
1286 	cp = line;
1287 	for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
1288 		tokens[*ntok] = sp;
1289 		while (ISSPACE(*cp))
1290 		    cp++;
1291 		if (ISEOL(*cp))
1292 		    break;
1293 		do {
1294 			*sp++ = *cp++;
1295 		} while (!ISSPACE(*cp) && !ISEOL(*cp));
1296 
1297 		*sp++ = '\0';
1298 	}
1299 }
1300 
1301 
1302 
1303 /*
1304  * findcmd - find a command in a command description table
1305  */
1306 static int
1307 findcmd(
1308 	register char *str,
1309 	struct xcmd *clist1,
1310 	struct xcmd *clist2,
1311 	struct xcmd **cmd
1312 	)
1313 {
1314 	register struct xcmd *cl;
1315 	size_t clen;
1316 	int nmatch;
1317 	struct xcmd *nearmatch = NULL;
1318 	struct xcmd *clist;
1319 
1320 	clen = strlen(str);
1321 	nmatch = 0;
1322 	if (clist1 != 0)
1323 	    clist = clist1;
1324 	else if (clist2 != 0)
1325 	    clist = clist2;
1326 	else
1327 	    return 0;
1328 
1329     again:
1330 	for (cl = clist; cl->keyword != 0; cl++) {
1331 		/* do a first character check, for efficiency */
1332 		if (*str != *(cl->keyword))
1333 		    continue;
1334 		if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
1335 			/*
1336 			 * Could be extact match, could be approximate.
1337 			 * Is exact if the length of the keyword is the
1338 			 * same as the str.
1339 			 */
1340 			if (*((cl->keyword) + clen) == '\0') {
1341 				*cmd = cl;
1342 				return 1;
1343 			}
1344 			nmatch++;
1345 			nearmatch = cl;
1346 		}
1347 	}
1348 
1349 				/*
1350 				 * See if there is more to do.  If so, go again.  Sorry about the
1351 				 * goto, too much looking at BSD sources...
1352 				 */
1353 	if (clist == clist1 && clist2 != 0) {
1354 		clist = clist2;
1355 		goto again;
1356 	}
1357 
1358 				/*
1359 				 * If we got extactly 1 near match, use it, else return number
1360 				 * of matches.
1361 				 */
1362 	if (nmatch == 1) {
1363 		*cmd = nearmatch;
1364 		return 1;
1365 	}
1366 	return nmatch;
1367 }
1368 
1369 
1370 /*
1371  * getarg - interpret an argument token
1372  *
1373  * string is always set.
1374  * type is set to the decoded type.
1375  *
1376  * return:	 0 - failure
1377  *		 1 - success
1378  *		-1 - skip to next token
1379  */
1380 static int
1381 getarg(
1382 	char *str,
1383 	int code,
1384 	arg_v *argp
1385 	)
1386 {
1387 	ZERO(*argp);
1388 	argp->string = str;
1389 	argp->type   = code & ~OPT;
1390 
1391 	switch (argp->type) {
1392 	case NTP_STR:
1393 		break;
1394 	case NTP_ADD:
1395 		if (!strcmp("-6", str)) {
1396 			ai_fam_templ = AF_INET6;
1397 			return -1;
1398 		} else if (!strcmp("-4", str)) {
1399 			ai_fam_templ = AF_INET;
1400 			return -1;
1401 		}
1402 		if (!getnetnum(str, &(argp->netnum), (char *)0, ai_fam_templ)) {
1403 			return 0;
1404 		}
1405 		break;
1406 	case NTP_UINT:
1407 		if (!atouint(str, &argp->uval)) {
1408 			fprintf(stderr, "***Illegal unsigned value %s\n",
1409 				str);
1410 			return 0;
1411 		}
1412 		break;
1413 	case NTP_INT:
1414 		if (!atoint(str, &argp->ival)) {
1415 			fprintf(stderr, "***Illegal integer value %s\n",
1416 				str);
1417 			return 0;
1418 		}
1419 		break;
1420 	case IP_VERSION:
1421 		if (!strcmp("-6", str))
1422 			argp->ival = 6 ;
1423 		else if (!strcmp("-4", str))
1424 			argp->ival = 4 ;
1425 		else {
1426 			(void) fprintf(stderr,
1427 			    "***Version must be either 4 or 6\n");
1428 			return 0;
1429 		}
1430 		break;
1431 	}
1432 
1433 	return 1;
1434 }
1435 
1436 
1437 /*
1438  * getnetnum - given a host name, return its net number
1439  *	       and (optional) full name
1440  */
1441 static int
1442 getnetnum(
1443 	const char *hname,
1444 	sockaddr_u *num,
1445 	char *fullhost,
1446 	int af
1447 	)
1448 {
1449 	struct addrinfo hints, *ai = NULL;
1450 
1451 	ZERO(hints);
1452 	hints.ai_family = af;
1453 	hints.ai_flags = AI_CANONNAME;
1454 #ifdef AI_ADDRCONFIG
1455 	hints.ai_flags |= AI_ADDRCONFIG;
1456 #endif
1457 
1458 	/*
1459 	 * decodenetnum only works with addresses, but handles syntax
1460 	 * that getaddrinfo doesn't:  [2001::1]:1234
1461 	 */
1462 	if (decodenetnum(hname, num)) {
1463 		if (fullhost != NULL)
1464 			getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1465 				    LENHOSTNAME, NULL, 0, 0);
1466 		return 1;
1467 	} else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1468 		INSIST(sizeof(*num) >= ai->ai_addrlen);
1469 		memcpy(num, ai->ai_addr, ai->ai_addrlen);
1470 		if (fullhost != NULL) {
1471 			if (ai->ai_canonname != NULL)
1472 				strlcpy(fullhost, ai->ai_canonname,
1473 					LENHOSTNAME);
1474 			else
1475 				getnameinfo(&num->sa, SOCKLEN(num),
1476 					    fullhost, LENHOSTNAME, NULL,
1477 					    0, 0);
1478 		}
1479 		return 1;
1480 	}
1481 	fprintf(stderr, "***Can't find host %s\n", hname);
1482 
1483 	return 0;
1484 }
1485 
1486 
1487 /*
1488  * nntohost - convert network number to host name.  This routine enforces
1489  *	       the showhostnames setting.
1490  */
1491 const char *
1492 nntohost(
1493 	sockaddr_u *netnum
1494 	)
1495 {
1496 	if (!showhostnames || SOCK_UNSPEC(netnum))
1497 		return stoa(netnum);
1498 	else if (ISREFCLOCKADR(netnum))
1499 		return refnumtoa(netnum);
1500 	else
1501 		return socktohost(netnum);
1502 }
1503 
1504 
1505 /*
1506  * Finally, the built in command handlers
1507  */
1508 
1509 /*
1510  * help - tell about commands, or details of a particular command
1511  */
1512 static void
1513 help(
1514 	struct parse *pcmd,
1515 	FILE *fp
1516 	)
1517 {
1518 	struct xcmd *xcp;
1519 	char *cmd;
1520 	const char *list[100];
1521 	size_t word, words;
1522 	size_t row, rows;
1523 	size_t col, cols;
1524 	size_t length;
1525 
1526 	if (pcmd->nargs == 0) {
1527 		words = 0;
1528 		for (xcp = builtins; xcp->keyword != 0; xcp++) {
1529 			if (*(xcp->keyword) != '?')
1530 				list[words++] = xcp->keyword;
1531 		}
1532 		for (xcp = opcmds; xcp->keyword != 0; xcp++)
1533 			list[words++] = xcp->keyword;
1534 
1535 		qsort((void *)list, words, sizeof(list[0]), helpsort);
1536 		col = 0;
1537 		for (word = 0; word < words; word++) {
1538 			length = strlen(list[word]);
1539 			col = max(col, length);
1540 		}
1541 
1542 		cols = SCREENWIDTH / ++col;
1543 		rows = (words + cols - 1) / cols;
1544 
1545 		fprintf(fp, "ntpdc commands:\n");
1546 
1547 		for (row = 0; row < rows; row++) {
1548 			for (word = row; word < words; word += rows)
1549 				fprintf(fp, "%-*.*s", (int)col,
1550 					(int)col - 1, list[word]);
1551 			fprintf(fp, "\n");
1552 		}
1553 	} else {
1554 		cmd = pcmd->argval[0].string;
1555 		words = findcmd(cmd, builtins, opcmds, &xcp);
1556 		if (words == 0) {
1557 			fprintf(stderr,
1558 				"Command `%s' is unknown\n", cmd);
1559 			return;
1560 		} else if (words >= 2) {
1561 			fprintf(stderr,
1562 				"Command `%s' is ambiguous\n", cmd);
1563 			return;
1564 		}
1565 		fprintf(fp, "function: %s\n", xcp->comment);
1566 		printusage(xcp, fp);
1567 	}
1568 }
1569 
1570 
1571 /*
1572  * helpsort - do hostname qsort comparisons
1573  */
1574 static int
1575 helpsort(
1576 	const void *t1,
1577 	const void *t2
1578 	)
1579 {
1580 	const char * const *	name1 = t1;
1581 	const char * const *	name2 = t2;
1582 
1583 	return strcmp(*name1, *name2);
1584 }
1585 
1586 
1587 /*
1588  * printusage - print usage information for a command
1589  */
1590 static void
1591 printusage(
1592 	struct xcmd *xcp,
1593 	FILE *fp
1594 	)
1595 {
1596 	int i, opt46;
1597 
1598 	opt46 = 0;
1599 	(void) fprintf(fp, "usage: %s", xcp->keyword);
1600 	for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
1601 		if (opt46 == 0 && (xcp->arg[i] & ~OPT) == NTP_ADD) {
1602 			(void) fprintf(fp, " [ -4|-6 ]");
1603 			opt46 = 1;
1604 		}
1605 		if (xcp->arg[i] & OPT)
1606 		    (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
1607 		else
1608 		    (void) fprintf(fp, " %s", xcp->desc[i]);
1609 	}
1610 	(void) fprintf(fp, "\n");
1611 }
1612 
1613 
1614 /*
1615  * timeout - set time out time
1616  */
1617 static void
1618 timeout(
1619 	struct parse *pcmd,
1620 	FILE *fp
1621 	)
1622 {
1623 	int val;
1624 
1625 	if (pcmd->nargs == 0) {
1626 		val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
1627 		(void) fprintf(fp, "primary timeout %d ms\n", val);
1628 	} else {
1629 		tvout.tv_sec = pcmd->argval[0].uval / 1000;
1630 		tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000))
1631 			* 1000;
1632 	}
1633 }
1634 
1635 
1636 /*
1637  * my_delay - set delay for auth requests
1638  */
1639 static void
1640 my_delay(
1641 	struct parse *pcmd,
1642 	FILE *fp
1643 	)
1644 {
1645 	int isneg;
1646 	u_long val;
1647 
1648 	if (pcmd->nargs == 0) {
1649 		val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
1650 		(void) fprintf(fp, "delay %lu ms\n", val);
1651 	} else {
1652 		if (pcmd->argval[0].ival < 0) {
1653 			isneg = 1;
1654 			val = ~(u_long)(pcmd->argval[0].ival) + 1UL;
1655 		} else {
1656 			isneg = 0;
1657 			val = (u_long)pcmd->argval[0].ival;
1658 		}
1659 
1660 		delay_time.l_ui = val / 1000;
1661 		val %= 1000;
1662 		delay_time.l_uf = val * 4294967;	/* 2**32/1000 */
1663 
1664 		if (isneg)
1665 		    L_NEG(&delay_time);
1666 	}
1667 }
1668 
1669 
1670 /*
1671  * host - set the host we are dealing with.
1672  */
1673 static void
1674 host(
1675 	struct parse *pcmd,
1676 	FILE *fp
1677 	)
1678 {
1679 	int i;
1680 
1681 	if (pcmd->nargs == 0) {
1682 		if (havehost)
1683 		    (void) fprintf(fp, "current host is %s\n", currenthost);
1684 		else
1685 		    (void) fprintf(fp, "no current host\n");
1686 		return;
1687 	}
1688 
1689 	i = 0;
1690 	if (pcmd->nargs == 2) {
1691 		if (!strcmp("-4", pcmd->argval[i].string))
1692 			ai_fam_templ = AF_INET;
1693 		else if (!strcmp("-6", pcmd->argval[i].string))
1694 			ai_fam_templ = AF_INET6;
1695 		else {
1696 			if (havehost)
1697 				(void) fprintf(fp,
1698 				    "current host remains %s\n", currenthost);
1699 			else
1700 				(void) fprintf(fp, "still no current host\n");
1701 			return;
1702 		}
1703 		i = 1;
1704 	}
1705 	if (openhost(pcmd->argval[i].string)) {
1706 		(void) fprintf(fp, "current host set to %s\n", currenthost);
1707 	} else {
1708 		if (havehost)
1709 		    (void) fprintf(fp,
1710 				   "current host remains %s\n", currenthost);
1711 		else
1712 		    (void) fprintf(fp, "still no current host\n");
1713 	}
1714 }
1715 
1716 
1717 /*
1718  * keyid - get a keyid to use for authenticating requests
1719  */
1720 static void
1721 keyid(
1722 	struct parse *pcmd,
1723 	FILE *fp
1724 	)
1725 {
1726 	if (pcmd->nargs == 0) {
1727 		if (info_auth_keyid == 0 && !keyid_entered)
1728 		    (void) fprintf(fp, "no keyid defined\n");
1729 		else if (info_auth_keyid == 0 && keyid_entered)
1730 		    (void) fprintf(fp, "no keyid will be sent\n");
1731 		else
1732 		    (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
1733 	} else {
1734 		info_auth_keyid = pcmd->argval[0].uval;
1735 		keyid_entered = 1;
1736 	}
1737 }
1738 
1739 
1740 /*
1741  * keytype - get type of key to use for authenticating requests
1742  */
1743 static void
1744 keytype(
1745 	struct parse *pcmd,
1746 	FILE *fp
1747 	)
1748 {
1749 	const char *	digest_name;
1750 	size_t		digest_len;
1751 	int		key_type;
1752 
1753 	if (!pcmd->nargs) {
1754 		fprintf(fp, "keytype is %s with %lu octet digests\n",
1755 			keytype_name(info_auth_keytype),
1756 			(u_long)info_auth_hashlen);
1757 		return;
1758 	}
1759 
1760 	digest_name = pcmd->argval[0].string;
1761 	digest_len = 0;
1762 	key_type = keytype_from_text(digest_name, &digest_len);
1763 
1764 	if (!key_type) {
1765 		fprintf(fp, "keytype must be 'md5'%s\n",
1766 #ifdef OPENSSL
1767 			" or a digest type provided by OpenSSL");
1768 #else
1769 			"");
1770 #endif
1771 		return;
1772 	}
1773 
1774 	info_auth_keytype = key_type;
1775 	info_auth_hashlen = digest_len;
1776 }
1777 
1778 
1779 /*
1780  * passwd - get an authentication key
1781  */
1782 /*ARGSUSED*/
1783 static void
1784 passwd(
1785 	struct parse *pcmd,
1786 	FILE *fp
1787 	)
1788 {
1789 	char *pass;
1790 
1791 	if (info_auth_keyid == 0) {
1792 		info_auth_keyid = getkeyid("Keyid: ");
1793 		if (info_auth_keyid == 0) {
1794 			(void)fprintf(fp, "Keyid must be defined\n");
1795 			return;
1796 		}
1797 	}
1798 	if (pcmd->nargs >= 1)
1799 		pass = pcmd->argval[0].string;
1800 	else {
1801 		pass = getpass_keytype(info_auth_keytype);
1802 		if ('\0' == *pass) {
1803 			fprintf(fp, "Password unchanged\n");
1804 			return;
1805 		}
1806 	}
1807 	authusekey(info_auth_keyid, info_auth_keytype, (u_char *)pass);
1808 	authtrust(info_auth_keyid, 1);
1809 }
1810 
1811 
1812 /*
1813  * hostnames - set the showhostnames flag
1814  */
1815 static void
1816 hostnames(
1817 	struct parse *pcmd,
1818 	FILE *fp
1819 	)
1820 {
1821 	if (pcmd->nargs == 0) {
1822 		if (showhostnames)
1823 		    (void) fprintf(fp, "hostnames being shown\n");
1824 		else
1825 		    (void) fprintf(fp, "hostnames not being shown\n");
1826 	} else {
1827 		if (STREQ(pcmd->argval[0].string, "yes"))
1828 		    showhostnames = 1;
1829 		else if (STREQ(pcmd->argval[0].string, "no"))
1830 		    showhostnames = 0;
1831 		else
1832 		    (void)fprintf(stderr, "What?\n");
1833 	}
1834 }
1835 
1836 
1837 /*
1838  * setdebug - set/change debugging level
1839  */
1840 static void
1841 setdebug(
1842 	struct parse *pcmd,
1843 	FILE *fp
1844 	)
1845 {
1846 	if (pcmd->nargs == 0) {
1847 		(void) fprintf(fp, "debug level is %d\n", debug);
1848 		return;
1849 	} else if (STREQ(pcmd->argval[0].string, "no")) {
1850 		debug = 0;
1851 	} else if (STREQ(pcmd->argval[0].string, "more")) {
1852 		debug++;
1853 	} else if (STREQ(pcmd->argval[0].string, "less")) {
1854 		debug--;
1855 	} else {
1856 		(void) fprintf(fp, "What?\n");
1857 		return;
1858 	}
1859 	(void) fprintf(fp, "debug level set to %d\n", debug);
1860 }
1861 
1862 
1863 /*
1864  * quit - stop this nonsense
1865  */
1866 /*ARGSUSED*/
1867 static void
1868 quit(
1869 	struct parse *pcmd,
1870 	FILE *fp
1871 	)
1872 {
1873 	if (havehost)
1874 	    closesocket(sockfd);
1875 	exit(0);
1876 }
1877 
1878 
1879 /*
1880  * version - print the current version number
1881  */
1882 /*ARGSUSED*/
1883 static void
1884 version(
1885 	struct parse *pcmd,
1886 	FILE *fp
1887 	)
1888 {
1889 
1890 	(void) fprintf(fp, "%s\n", Version);
1891 	return;
1892 }
1893 
1894 
1895 static void __attribute__((__format__(__printf__, 1, 0)))
1896 vwarning(const char *fmt, va_list ap)
1897 {
1898 	int serrno = errno;
1899 	(void) fprintf(stderr, "%s: ", progname);
1900 	vfprintf(stderr, fmt, ap);
1901 	(void) fprintf(stderr, ": %s\n", strerror(serrno));
1902 }
1903 
1904 /*
1905  * warning - print a warning message
1906  */
1907 static void __attribute__((__format__(__printf__, 1, 2)))
1908 warning(
1909 	const char *fmt,
1910 	...
1911 	)
1912 {
1913 	va_list ap;
1914 	va_start(ap, fmt);
1915 	vwarning(fmt, ap);
1916 	va_end(ap);
1917 }
1918 
1919 
1920 /*
1921  * error - print a message and exit
1922  */
1923 static void __attribute__((__format__(__printf__, 1, 2)))
1924 error(
1925 	const char *fmt,
1926 	...
1927 	)
1928 {
1929 	va_list ap;
1930 	va_start(ap, fmt);
1931 	vwarning(fmt, ap);
1932 	va_end(ap);
1933 	exit(1);
1934 }
1935 
1936 /*
1937  * getkeyid - prompt the user for a keyid to use
1938  */
1939 static u_long
1940 getkeyid(
1941 	const char *keyprompt
1942 	)
1943 {
1944 	int c;
1945 	FILE *fi;
1946 	char pbuf[20];
1947 	size_t i;
1948 	size_t ilim;
1949 
1950 #ifndef SYS_WINNT
1951 	if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
1952 #else
1953 	if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
1954 #endif /* SYS_WINNT */
1955 		fi = stdin;
1956 	else
1957 		setbuf(fi, (char *)NULL);
1958 	fprintf(stderr, "%s", keyprompt); fflush(stderr);
1959 	for (i = 0, ilim = COUNTOF(pbuf) - 1;
1960 	     i < ilim && (c = getc(fi)) != '\n' && c != EOF;
1961 	     )
1962 		pbuf[i++] = (char)c;
1963 	pbuf[i] = '\0';
1964 	if (fi != stdin)
1965 		fclose(fi);
1966 
1967 	return (u_long) atoi(pbuf);
1968 }
1969