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