xref: /freebsd/contrib/ntp/ntpdc/ntpdc_ops.c (revision 4b2eaea43fec8e8792be611dea204071a10b655a)
1 /*
2  * ntpdc_ops.c - subroutines which are called to perform operations by ntpdc
3  */
4 
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8 
9 #include <stdio.h>
10 
11 #include "ntpdc.h"
12 #include "ntp_control.h"
13 #include "ntp_refclock.h"
14 #include "ntp_stdlib.h"
15 
16 #include <ctype.h>
17 #ifdef HAVE_SYS_TIMEX_H
18 # include <sys/timex.h>
19 #endif
20 #include <netdb.h>
21 #if !defined(__bsdi__) && !defined(apollo)
22 #include <netinet/in.h>
23 #endif
24 
25 #include <arpa/inet.h>
26 
27 /*
28  * Declarations for command handlers in here
29  */
30 static	int	checkitems	P((int, FILE *));
31 static	int	checkitemsize	P((int, int));
32 static	int	check1item	P((int, FILE *));
33 static	void	peerlist	P((struct parse *, FILE *));
34 static	void	peers		P((struct parse *, FILE *));
35 static void	doconfig	P((struct parse *pcmd, FILE *fp, int mode, int refc));
36 static	void	dmpeers		P((struct parse *, FILE *));
37 static	void	dopeers		P((struct parse *, FILE *, int));
38 static	void	printpeer	P((struct info_peer *, FILE *));
39 static	void	showpeer	P((struct parse *, FILE *));
40 static	void	peerstats	P((struct parse *, FILE *));
41 static	void	loopinfo	P((struct parse *, FILE *));
42 static	void	sysinfo		P((struct parse *, FILE *));
43 static	void	sysstats	P((struct parse *, FILE *));
44 static	void	iostats		P((struct parse *, FILE *));
45 static	void	memstats	P((struct parse *, FILE *));
46 static	void	timerstats	P((struct parse *, FILE *));
47 static	void	addpeer		P((struct parse *, FILE *));
48 static	void	addserver	P((struct parse *, FILE *));
49 static	void	addrefclock	P((struct parse *, FILE *));
50 static	void	broadcast	P((struct parse *, FILE *));
51 static	void	doconfig	P((struct parse *, FILE *, int, int));
52 static	void	unconfig	P((struct parse *, FILE *));
53 static	void	set		P((struct parse *, FILE *));
54 static	void	sys_clear	P((struct parse *, FILE *));
55 static	void	doset		P((struct parse *, FILE *, int));
56 static	void	reslist		P((struct parse *, FILE *));
57 static	void	new_restrict	P((struct parse *, FILE *));
58 static	void	unrestrict	P((struct parse *, FILE *));
59 static	void	delrestrict	P((struct parse *, FILE *));
60 static	void	do_restrict	P((struct parse *, FILE *, int));
61 static	void	monlist		P((struct parse *, FILE *));
62 static	void	reset		P((struct parse *, FILE *));
63 static	void	preset		P((struct parse *, FILE *));
64 static	void	readkeys	P((struct parse *, FILE *));
65 static	void	trustkey	P((struct parse *, FILE *));
66 static	void	untrustkey	P((struct parse *, FILE *));
67 static	void	do_trustkey	P((struct parse *, FILE *, int));
68 static	void	authinfo	P((struct parse *, FILE *));
69 static	void	traps		P((struct parse *, FILE *));
70 static	void	addtrap		P((struct parse *, FILE *));
71 static	void	clrtrap		P((struct parse *, FILE *));
72 static	void	do_addclr_trap	P((struct parse *, FILE *, int));
73 static	void	requestkey	P((struct parse *, FILE *));
74 static	void	controlkey	P((struct parse *, FILE *));
75 static	void	do_changekey	P((struct parse *, FILE *, int));
76 static	void	ctlstats	P((struct parse *, FILE *));
77 static	void	clockstat	P((struct parse *, FILE *));
78 static	void	fudge		P((struct parse *, FILE *));
79 static	void	clkbug		P((struct parse *, FILE *));
80 static	void	kerninfo	P((struct parse *, FILE *));
81 
82 /*
83  * Commands we understand.  Ntpdc imports this.
84  */
85 struct xcmd opcmds[] = {
86 	{ "listpeers",	peerlist,	{  NO, NO, NO, NO },
87 	  { "", "", "", "" },
88 	  "display list of peers the server knows about" },
89 	{ "peers",	peers,		{ NO, NO, NO, NO },
90 	  { "", "", "", "" },
91 	  "display peer summary information" },
92 	{ "dmpeers",	dmpeers,	{ NO, NO, NO, NO },
93 	  { "", "", "", "" },
94 	  "display peer summary info the way Dave Mills likes it" },
95 	{ "showpeer",	showpeer,	{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
96 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
97 	  "display detailed information for one or more peers" },
98 	{ "pstats",	peerstats,	{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
99 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
100 	  "display statistical information for one or more peers" },
101 	{ "loopinfo",	loopinfo,	{ OPT|NTP_STR, NO, NO, NO },
102 	  { "oneline|multiline", "", "", "" },
103 	  "display loop filter information" },
104 	{ "sysinfo",	sysinfo,	{ NO, NO, NO, NO },
105 	  { "", "", "", "" },
106 	  "display local server information" },
107 	{ "sysstats",	sysstats,	{ NO, NO, NO, NO },
108 	  { "", "", "", "" },
109 	  "display local server statistics" },
110 	{ "memstats",	memstats,	{ NO, NO, NO, NO },
111 	  { "", "", "", "" },
112 	  "display peer memory usage statistics" },
113 	{ "iostats",	iostats,	{ NO, NO, NO, NO },
114 	  { "", "", "", "" },
115 	  "display I/O subsystem statistics" },
116 	{ "timerstats",	timerstats,	{ NO, NO, NO, NO },
117 	  { "", "", "", "" },
118 	  "display event timer subsystem statistics" },
119 	{ "addpeer",	addpeer,	{ ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
120 	  { "addr", "keyid", "version", "minpoll|prefer" },
121 	  "configure a new peer association" },
122 	{ "addserver",	addserver,	{ ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
123 	  { "addr", "keyid", "version", "minpoll|prefer" },
124 	  "configure a new server" },
125 	{ "addrefclock",addrefclock,	{ ADD, OPT|UINT, OPT|NTP_STR, OPT|NTP_STR },
126 	  { "addr", "mode", "minpoll|prefer", "minpoll|prefer" },
127 	  "configure a new server" },
128 	{ "broadcast",	broadcast,	{ ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
129 	  { "addr", "keyid", "version", "minpoll" },
130 	  "configure broadcasting time service" },
131 	{ "unconfig",	unconfig,	{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
132 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
133 	  "unconfigure existing peer assocations" },
134 	{ "enable",	set,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
135 	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
136 	  "set a system flag (auth, bclient, monitor, pll, kernel, stats)" },
137         { "disable",	sys_clear,      { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
138 	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
139 	  "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" },
140 	{ "reslist",	reslist,	{ NO, NO, NO, NO },
141 	  { "", "", "", "" },
142 	  "display the server's restrict list" },
143 	{ "restrict",	new_restrict,	{ ADD, ADD, NTP_STR, OPT|NTP_STR },
144 	  { "address", "mask",
145 	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
146 	    "..." },
147 	  "create restrict entry/add flags to entry" },
148 	{ "unrestrict", unrestrict,	{ ADD, ADD, NTP_STR, OPT|NTP_STR },
149 	  { "address", "mask",
150 	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
151 	    "..." },
152 	  "remove flags from a restrict entry" },
153 	{ "delrestrict", delrestrict,	{ ADD, ADD, OPT|NTP_STR, NO },
154 	  { "address", "mask", "ntpport", "" },
155 	  "delete a restrict entry" },
156 	{ "monlist",	monlist,	{ OPT|INT, NO, NO, NO },
157 	  { "version", "", "", "" },
158 	  "display data the server's monitor routines have collected" },
159 	{ "reset",	reset,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
160 	  { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
161 	  "reset various subsystem statistics counters" },
162 	{ "preset",	preset,		{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
163 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
164 	  "reset stat counters associated with particular peer(s)" },
165 	{ "readkeys",	readkeys,	{ NO, NO, NO, NO },
166 	  { "", "", "", "" },
167 	  "request a reread of the keys file and re-init of system keys" },
168 	{ "trustedkey",	trustkey,	{ UINT, OPT|UINT, OPT|UINT, OPT|UINT },
169 	  { "keyid", "keyid", "keyid", "keyid" },
170 	  "add one or more key ID's to the trusted list" },
171 	{ "untrustedkey", untrustkey,	{ UINT, OPT|UINT, OPT|UINT, OPT|UINT },
172 	  { "keyid", "keyid", "keyid", "keyid" },
173 	  "remove one or more key ID's from the trusted list" },
174 	{ "authinfo",	authinfo,	{ NO, NO, NO, NO },
175 	  { "", "", "", "" },
176 	  "display the state of the authentication code" },
177 	{ "traps",	traps,		{ NO, NO, NO, NO },
178 	  { "", "", "", "" },
179 	  "display the traps set in the server" },
180 	{ "addtrap",	addtrap,	{ ADD, OPT|UINT, OPT|ADD, NO },
181 	  { "address", "port", "interface", "" },
182 	  "configure a trap in the server" },
183 	{ "clrtrap",	clrtrap,	{ ADD, OPT|UINT, OPT|ADD, NO },
184 	  { "address", "port", "interface", "" },
185 	  "remove a trap (configured or otherwise) from the server" },
186 	{ "requestkey",	requestkey,	{ UINT, NO, NO, NO },
187 	  { "keyid", "", "", "" },
188 	  "change the keyid the server uses to authenticate requests" },
189 	{ "controlkey",	controlkey,	{ UINT, NO, NO, NO },
190 	  { "keyid", "", "", "" },
191 	  "change the keyid the server uses to authenticate control messages" },
192 	{ "ctlstats",	ctlstats,	{ NO, NO, NO, NO },
193 	  { "", "", "", "" },
194 	  "display packet count statistics from the control module" },
195 	{ "clockstat",	clockstat,	{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
196 	  { "address", "address", "address", "address" },
197 	  "display clock status information" },
198 	{ "fudge",	fudge,		{ ADD, NTP_STR, NTP_STR, NO },
199 	  { "address", "time1|time2|val1|val2|flags", "value", "" },
200 	  "set/change one of a clock's fudge factors" },
201 	{ "clkbug",	clkbug,		{ ADD, OPT|ADD, OPT|ADD, OPT|ADD },
202 	  { "address", "address", "address", "address" },
203 	  "display clock debugging information" },
204 	{ "kerninfo",	kerninfo,	{ NO, NO, NO, NO },
205 	  { "", "", "", "" },
206 	  "display the kernel pll/pps variables" },
207 
208 	{ 0,		0,		{ NO, NO, NO, NO },
209 	  { "", "", "", "" }, "" }
210 };
211 
212 
213 /*
214  * Imported from ntpdc.c
215  */
216 extern int showhostnames;
217 extern struct servent *server_entry;
218 
219 /*
220  * For quick string comparisons
221  */
222 #define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
223 
224 
225 /*
226  * checkitems - utility to print a message if no items were returned
227  */
228 static int
229 checkitems(
230 	int items,
231 	FILE *fp
232 	)
233 {
234 	if (items == 0) {
235 		(void) fprintf(fp, "No data returned in response to query\n");
236 		return 0;
237 	}
238 	return 1;
239 }
240 
241 
242 /*
243  * checkitemsize - utility to print a message if the item size is wrong
244  */
245 static int
246 checkitemsize(
247 	int itemsize,
248 	int expected
249 	)
250 {
251 	if (itemsize != expected) {
252 		(void) fprintf(stderr,
253 			       "***Incorrect item size returned by remote host (%d should be %d)\n",
254 			       itemsize, expected);
255 		return 0;
256 	}
257 	return 1;
258 }
259 
260 
261 /*
262  * check1item - check to make sure we have exactly one item
263  */
264 static int
265 check1item(
266 	int items,
267 	FILE *fp
268 	)
269 {
270 	if (items == 0) {
271 		(void) fprintf(fp, "No data returned in response to query\n");
272 		return 0;
273 	}
274 	if (items > 1) {
275 		(void) fprintf(fp, "Expected one item in response, got %d\n",
276 			       items);
277 		return 0;
278 	}
279 	return 1;
280 }
281 
282 
283 
284 /*
285  * peerlist - get a short list of peers
286  */
287 /*ARGSUSED*/
288 static void
289 peerlist(
290 	struct parse *pcmd,
291 	FILE *fp
292 	)
293 {
294 	struct info_peer_list *plist;
295 	int items;
296 	int itemsize;
297 	int res;
298 
299 	res = doquery(IMPL_XNTPD, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
300 		      &itemsize, (char **)&plist, 0);
301 
302 	if (res != 0 && items == 0)
303 	    return;
304 
305 	if (!checkitems(items, fp))
306 	    return;
307 
308 	if (!checkitemsize(itemsize, sizeof(struct info_peer_list)))
309 	    return;
310 
311 	while (items > 0) {
312 		(void) fprintf(fp, "%-9s %s\n", modetoa(plist->hmode),
313 			       nntohost(plist->address));
314 		plist++;
315 		items--;
316 	}
317 }
318 
319 
320 /*
321  * peers - show peer summary
322  */
323 static void
324 peers(
325 	struct parse *pcmd,
326 	FILE *fp
327 	)
328 {
329 	dopeers(pcmd, fp, 0);
330 }
331 
332 /*
333  * dmpeers - show peer summary, Dave Mills style
334  */
335 static void
336 dmpeers(
337 	struct parse *pcmd,
338 	FILE *fp
339 	)
340 {
341 	dopeers(pcmd, fp, 1);
342 }
343 
344 
345 /*
346  * peers - show peer summary
347  */
348 /*ARGSUSED*/
349 static void
350 dopeers(
351 	struct parse *pcmd,
352 	FILE *fp,
353 	int dmstyle
354 	)
355 {
356 	struct info_peer_summary *plist;
357 	int items;
358 	int itemsize;
359 	int ntp_poll;
360 	int res;
361 	int c;
362 	l_fp tempts;
363 
364 	res = doquery(IMPL_XNTPD, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
365 		      &items, &itemsize, (char **)&plist, 0);
366 
367 	if (res != 0 && items == 0)
368 	    return;
369 
370 	if (!checkitems(items, fp))
371 	    return;
372 
373 	if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)))
374 	    return;
375 
376 	(void) fprintf(fp,
377 		       "     remote           local      st poll reach  delay   offset    disp\n");
378 	(void) fprintf(fp,
379 		       "=======================================================================\n");
380 	while (items > 0) {
381 		if (!dmstyle) {
382 			if (plist->flags & INFO_FLAG_SYSPEER)
383 			    c = '*';
384 			else if (plist->hmode == MODE_ACTIVE)
385 			    c = '+';
386 			else if (plist->hmode == MODE_PASSIVE)
387 			    c = '-';
388 			else if (plist->hmode == MODE_CLIENT)
389 			    c = '=';
390 			else if (plist->hmode == MODE_BROADCAST)
391 			    c = '^';
392 			else if (plist->hmode == MODE_BCLIENT)
393 			    c = '~';
394 			else
395 			    c = ' ';
396 		} else {
397 			if (plist->flags & INFO_FLAG_SYSPEER)
398 			    c = '*';
399 			else if (plist->flags & INFO_FLAG_SHORTLIST)
400 			    c = '+';
401 			else if (plist->flags & INFO_FLAG_SEL_CANDIDATE)
402 			    c = '.';
403 			else
404 			    c = ' ';
405 		}
406 		NTOHL_FP(&(plist->offset), &tempts);
407 		ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
408 				  NTP_MINPOLL);
409 		(void) fprintf(fp,
410 			       "%c%-15.15s %-15.15s %2d %4d  %3o %7.7s %9.9s %7.7s\n",
411 			       c, nntohost(plist->srcadr),
412 			       numtoa(plist->dstadr),
413 			       plist->stratum, ntp_poll, plist->reach,
414 			       fptoa(NTOHS_FP(plist->delay), 5),
415 			       lfptoa(&tempts, 6),
416 			       ufptoa(NTOHS_FP(plist->dispersion), 5));
417 
418 		plist++;
419 		items--;
420 	}
421 }
422 
423 /* Convert a refid & stratum (in host order) to a string */
424 static char*
425 refid_string(
426 	u_int32 refid,
427 	int stratum
428 	)
429 {
430 	if (stratum <= 1) {
431 		static char junk[5];
432 		junk[4] = 0;
433 		memmove(junk, (char *)&refid, 4);
434 		return junk;
435 	}
436 
437 	return numtoa(refid);
438 }
439 
440 /*
441  * printpeer - print detail information for a peer
442  */
443 static void
444 printpeer(
445 	register struct info_peer *pp,
446 	FILE *fp
447 	)
448 {
449 	register int i;
450 	const char *str;
451 	l_fp tempts;
452 
453 	(void) fprintf(fp, "remote %s, local %s\n",
454 		       numtoa(pp->srcadr), numtoa(pp->dstadr));
455 
456 	(void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n",
457 		       modetoa(pp->hmode), modetoa(pp->pmode),
458 		       pp->stratum, pp->precision);
459 
460 	(void) fprintf(fp,
461 		       "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
462 		       pp->leap & 0x2 ? '1' : '0',
463 		       pp->leap & 0x1 ? '1' : '0',
464 		       refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
465 		       ufptoa(NTOHS_FP(pp->rootdispersion), 5));
466 
467 	(void) fprintf(fp,
468 		       "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
469 		       pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
470 
471 	(void) fprintf(fp,
472 		       "reach %03o, unreach %d, flash 0x%04x, ",
473 		       pp->reach, pp->unreach, pp->flash2);
474 
475 	(void) fprintf(fp, "boffset %s, ttl/mode %d\n",
476 		       fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
477 
478 	(void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
479 	if (pp->flags == 0) {
480 		(void) fprintf(fp, " none\n");
481 	} else {
482 		str = "";
483 		if (pp->flags & INFO_FLAG_SYSPEER) {
484 			(void) fprintf(fp, " system_peer");
485 			str = ",";
486 		}
487 		if (pp->flags & INFO_FLAG_CONFIG) {
488 			(void) fprintf(fp, "%s config", str);
489 			str = ",";
490 		}
491 		if (pp->flags & INFO_FLAG_REFCLOCK) {
492 			(void) fprintf(fp, "%s refclock", str);
493 			str = ",";
494 		}
495 		if (pp->flags & INFO_FLAG_AUTHENABLE) {
496 			(void) fprintf(fp, "%s auth", str);
497 			str = ",";
498 		}
499 		if (pp->flags & INFO_FLAG_BCLIENT) {
500 			(void) fprintf(fp, "%s bclient", str);
501 			str = ",";
502 		}
503 		if (pp->flags & INFO_FLAG_PREFER) {
504 			(void) fprintf(fp, "%s prefer", str);
505 			str = ",";
506 		}
507 		if (pp->flags & INFO_FLAG_BURST) {
508 			(void) fprintf(fp, "%s burst", str);
509 		}
510 		(void) fprintf(fp, "\n");
511 	}
512 
513 	NTOHL_FP(&pp->reftime, &tempts);
514 	(void) fprintf(fp, "reference time:      %s\n",
515 		       prettydate(&tempts));
516 	NTOHL_FP(&pp->org, &tempts);
517 	(void) fprintf(fp, "originate timestamp: %s\n",
518 		       prettydate(&tempts));
519 	NTOHL_FP(&pp->rec, &tempts);
520 	(void) fprintf(fp, "receive timestamp:   %s\n",
521 		       prettydate(&tempts));
522 	NTOHL_FP(&pp->xmt, &tempts);
523 	(void) fprintf(fp, "transmit timestamp:  %s\n",
524 		       prettydate(&tempts));
525 
526 	(void) fprintf(fp, "filter delay: ");
527 	for (i = 0; i < NTP_SHIFT; i++) {
528 		(void) fprintf(fp, " %-8.8s",
529 			       fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
530 		if (i == (NTP_SHIFT>>1)-1)
531 		    (void) fprintf(fp, "\n              ");
532 	}
533 	(void) fprintf(fp, "\n");
534 
535 	(void) fprintf(fp, "filter offset:");
536 	for (i = 0; i < NTP_SHIFT; i++) {
537 		NTOHL_FP(&pp->filtoffset[i], &tempts);
538 		(void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
539 		if (i == (NTP_SHIFT>>1)-1)
540 		    (void) fprintf(fp, "\n              ");
541 	}
542 	(void) fprintf(fp, "\n");
543 
544 	(void) fprintf(fp, "filter order: ");
545 	for (i = 0; i < NTP_SHIFT; i++) {
546 		(void) fprintf(fp, " %-8d", pp->order[i]);
547 		if (i == (NTP_SHIFT>>1)-1)
548 		    (void) fprintf(fp, "\n              ");
549 	}
550 	(void) fprintf(fp, "\n");
551 
552 
553 	NTOHL_FP(&pp->offset, &tempts);
554 	(void) fprintf(fp,
555 		       "offset %s, delay %s, error bound %s, filter error %s\n",
556 		       lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
557 		       ufptoa(NTOHS_FP(pp->dispersion), 5),
558 		       ufptoa(NTOHS_FP(pp->selectdisp), 5));
559 }
560 
561 
562 /*
563  * showpeer - show detailed information for a peer
564  */
565 static void
566 showpeer(
567 	struct parse *pcmd,
568 	FILE *fp
569 	)
570 {
571 	struct info_peer *pp;
572 	/* 4 is the maximum number of peers which will fit in a packet */
573 	struct info_peer_list plist[min(MAXARGS, 4)];
574 	int qitems;
575 	int items;
576 	int itemsize;
577 	int res;
578 
579 	for (qitems = 0; qitems < min(pcmd->nargs, 4); qitems++) {
580 		plist[qitems].address = pcmd->argval[qitems].netnum;
581 		plist[qitems].port = server_entry->s_port;
582 		plist[qitems].hmode = plist[qitems].flags = 0;
583 	}
584 
585 	res = doquery(IMPL_XNTPD, REQ_PEER_INFO, 0, qitems,
586 		      sizeof(struct info_peer_list), (char *)plist, &items,
587 		      &itemsize, (char **)&pp, 0);
588 
589 	if (res != 0 && items == 0)
590 	    return;
591 
592 	if (!checkitems(items, fp))
593 	    return;
594 
595 	if (!checkitemsize(itemsize, sizeof(struct info_peer)))
596 	    return;
597 
598 	while (items-- > 0) {
599 		printpeer(pp, fp);
600 		if (items > 0)
601 		    (void) fprintf(fp, "\n");
602 		pp++;
603 	}
604 }
605 
606 
607 /*
608  * peerstats - return statistics for a peer
609  */
610 static void
611 peerstats(
612 	struct parse *pcmd,
613 	FILE *fp
614 	)
615 {
616 	struct info_peer_stats *pp;
617 	/* 4 is the maximum number of peers which will fit in a packet */
618 	struct info_peer_list plist[min(MAXARGS, 4)];
619 	int qitems;
620 	int items;
621 	int itemsize;
622 	int res;
623 
624 	for (qitems = 0; qitems < min(pcmd->nargs, 4); qitems++) {
625 		plist[qitems].address = pcmd->argval[qitems].netnum;
626 		plist[qitems].port = server_entry->s_port;
627 		plist[qitems].hmode = plist[qitems].flags = 0;
628 	}
629 
630 	res = doquery(IMPL_XNTPD, REQ_PEER_STATS, 0, qitems,
631 		      sizeof(struct info_peer_list), (char *)plist, &items,
632 		      &itemsize, (char **)&pp, 0);
633 
634 	if (res != 0 && items == 0)
635 	    return;
636 
637 	if (!checkitems(items, fp))
638 	    return;
639 
640 	if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)))
641 	    return;
642 
643 	while (items-- > 0) {
644 		(void) fprintf(fp, "remote host:          %s\n",
645 			       nntohost(pp->srcadr));
646 		(void) fprintf(fp, "local interface:      %s\n",
647 			       numtoa(pp->dstadr));
648 		(void) fprintf(fp, "time last received:   %lds\n",
649 			       (long)ntohl(pp->timereceived));
650 		(void) fprintf(fp, "time until next send: %lds\n",
651 			       (long)ntohl(pp->timetosend));
652 		(void) fprintf(fp, "reachability change:  %lds\n",
653 			       (long)ntohl(pp->timereachable));
654 		(void) fprintf(fp, "packets sent:         %ld\n",
655 			       (long)ntohl(pp->sent));
656 		(void) fprintf(fp, "packets received:     %ld\n",
657 			       (long)ntohl(pp->processed));
658 		(void) fprintf(fp, "bad authentication:   %ld\n",
659 			       (long)ntohl(pp->badauth));
660 		(void) fprintf(fp, "bogus origin:         %ld\n",
661 			       (long)ntohl(pp->bogusorg));
662 		(void) fprintf(fp, "duplicate:            %ld\n",
663 			       (long)ntohl(pp->oldpkt));
664 		(void) fprintf(fp, "bad dispersion:       %ld\n",
665 			       (long)ntohl(pp->seldisp));
666 		(void) fprintf(fp, "bad reference time:   %ld\n",
667 			       (long)ntohl(pp->selbroken));
668 		(void) fprintf(fp, "candidate order:      %d\n",
669 			       (int)pp->candidate);
670 		if (items > 0)
671 		    (void) fprintf(fp, "\n");
672 		pp++;
673 	}
674 }
675 
676 
677 /*
678  * loopinfo - show loop filter information
679  */
680 static void
681 loopinfo(
682 	struct parse *pcmd,
683 	FILE *fp
684 	)
685 {
686 	struct info_loop *il;
687 	int items;
688 	int itemsize;
689 	int oneline = 0;
690 	int res;
691 	l_fp tempts;
692 
693 	if (pcmd->nargs > 0) {
694 		if (STREQ(pcmd->argval[0].string, "oneline"))
695 		    oneline = 1;
696 		else if (STREQ(pcmd->argval[0].string, "multiline"))
697 		    oneline = 0;
698 		else {
699 			(void) fprintf(stderr, "How many lines?\n");
700 			return;
701 		}
702 	}
703 
704 	res = doquery(IMPL_XNTPD, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
705 		      &items, &itemsize, (char **)&il, 0);
706 
707 	if (res != 0 && items == 0)
708 	    return;
709 
710 	if (!check1item(items, fp))
711 	    return;
712 
713 	if (!checkitemsize(itemsize, sizeof(struct info_loop)))
714 	    return;
715 
716 	if (oneline) {
717 		l_fp temp2ts;
718 
719 		NTOHL_FP(&il->last_offset, &tempts);
720 		NTOHL_FP(&il->drift_comp, &temp2ts);
721 
722 		(void) fprintf(fp,
723 			       "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
724 			       lfptoa(&tempts, 6),
725 			       lfptoa(&temp2ts, 3),
726 			       (u_long)ntohl(il->compliance),
727 			       (u_long)ntohl(il->watchdog_timer));
728 	} else {
729 		NTOHL_FP(&il->last_offset, &tempts);
730 		(void) fprintf(fp, "offset:               %s s\n",
731 			       lfptoa(&tempts, 6));
732 		NTOHL_FP(&il->drift_comp, &tempts);
733 		(void) fprintf(fp, "frequency:            %s ppm\n",
734 			       lfptoa(&tempts, 3));
735 		(void) fprintf(fp, "poll adjust:          %ld\n",
736 			       (u_long)ntohl(il->compliance));
737 		(void) fprintf(fp, "watchdog timer:       %ld s\n",
738 			       (u_long)ntohl(il->watchdog_timer));
739 	}
740 }
741 
742 
743 /*
744  * sysinfo - show current system state
745  */
746 /*ARGSUSED*/
747 static void
748 sysinfo(
749 	struct parse *pcmd,
750 	FILE *fp
751 	)
752 {
753 	struct info_sys *is;
754 	int items;
755 	int itemsize;
756 	int res;
757 	l_fp tempts;
758 
759 	res = doquery(IMPL_XNTPD, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
760 		      &items, &itemsize, (char **)&is, 0);
761 
762 	if (res != 0 && items == 0)
763 	    return;
764 
765 	if (!check1item(items, fp))
766 	    return;
767 
768 	if (!checkitemsize(itemsize, sizeof(struct info_sys)))
769 	    return;
770 
771 	(void) fprintf(fp, "system peer:          %s\n", nntohost(is->peer));
772 	(void) fprintf(fp, "system peer mode:     %s\n", modetoa(is->peer_mode));
773 	(void) fprintf(fp, "leap indicator:       %c%c\n",
774 		       is->leap & 0x2 ? '1' : '0',
775 		       is->leap & 0x1 ? '1' : '0');
776 	(void) fprintf(fp, "stratum:              %d\n", (int)is->stratum);
777 	(void) fprintf(fp, "precision:            %d\n", (int)is->precision);
778 	(void) fprintf(fp, "root distance:        %s s\n",
779 		       fptoa(NTOHS_FP(is->rootdelay), 5));
780 	(void) fprintf(fp, "root dispersion:      %s s\n",
781 		       ufptoa(NTOHS_FP(is->rootdispersion), 5));
782 	(void) fprintf(fp, "reference ID:         [%s]\n",
783 		       refid_string(is->refid, is->stratum));
784 	NTOHL_FP(&is->reftime, &tempts);
785 	(void) fprintf(fp, "reference time:       %s\n", prettydate(&tempts));
786 
787 	(void) fprintf(fp, "system flags:         ");
788 	if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
789 	    INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL |
790 	    INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
791 		(void) fprintf(fp, "none\n");
792 	} else {
793 		if (is->flags & INFO_FLAG_BCLIENT)
794 		    (void) fprintf(fp, "bclient ");
795 		if (is->flags & INFO_FLAG_AUTHENTICATE)
796 		    (void) fprintf(fp, "auth ");
797 		if (is->flags & INFO_FLAG_MONITOR)
798 		    (void) fprintf(fp, "monitor ");
799 		if (is->flags & INFO_FLAG_NTP)
800 		    (void) fprintf(fp, "ntp ");
801 		if (is->flags & INFO_FLAG_KERNEL)
802 		    (void) fprintf(fp, "kernel ");
803 		if (is->flags & INFO_FLAG_FILEGEN)
804 		    (void) fprintf(fp, "stats ");
805 		if (is->flags & INFO_FLAG_CAL)
806 		    (void) fprintf(fp, "calibrate ");
807 		if (is->flags & INFO_FLAG_PPS_SYNC)
808 		    (void) fprintf(fp, "pps ");
809 		(void) fprintf(fp, "\n");
810 	}
811 	(void) fprintf(fp, "jitter:               %s s\n",
812 		       fptoa(ntohl(is->frequency), 6));
813 	(void) fprintf(fp, "stability:            %s ppm\n",
814 		       ufptoa(ntohl(is->stability), 3));
815 	(void) fprintf(fp, "broadcastdelay:       %s s\n",
816 		       fptoa(NTOHS_FP(is->bdelay), 6));
817 	NTOHL_FP(&is->authdelay, &tempts);
818 	(void) fprintf(fp, "authdelay:            %s s\n", lfptoa(&tempts, 6));
819 }
820 
821 
822 /*
823  * sysstats - print system statistics
824  */
825 /*ARGSUSED*/
826 static void
827 sysstats(
828 	struct parse *pcmd,
829 	FILE *fp
830 	)
831 {
832 	struct info_sys_stats *ss;
833 	int items;
834 	int itemsize;
835 	int res;
836 
837 	res = doquery(IMPL_XNTPD, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
838 		      &items, &itemsize, (char **)&ss, 0);
839 
840 	if (res != 0 && items == 0)
841 	    return;
842 
843 	if (!check1item(items, fp))
844 	    return;
845 
846 	if (itemsize != sizeof(struct info_sys_stats) &&
847 	    itemsize != sizeof(struct old_info_sys_stats)) {
848 		/* issue warning according to new structure size */
849 		checkitemsize(itemsize, sizeof(struct info_sys_stats));
850 		return;
851 	}
852 
853 	(void) fprintf(fp, "system uptime:          %ld\n",
854 		       (u_long)ntohl(ss->timeup));
855 	(void) fprintf(fp, "time since reset:       %ld\n",
856 		       (u_long)ntohl(ss->timereset));
857 	(void) fprintf(fp, "bad stratum in packet:  %ld\n",
858 		       (u_long)ntohl(ss->badstratum));
859 	(void) fprintf(fp, "old version packets:    %ld\n",
860 		       (u_long)ntohl(ss->oldversionpkt));
861 	(void) fprintf(fp, "new version packets:    %ld\n",
862 		       (u_long)ntohl(ss->newversionpkt));
863 	(void) fprintf(fp, "unknown version number: %ld\n",
864 		       (u_long)ntohl(ss->unknownversion));
865 	(void) fprintf(fp, "bad packet format:      %ld\n",
866 		       (u_long)ntohl(ss->badlength));
867 	(void) fprintf(fp, "packets processed:      %ld\n",
868 		       (u_long)ntohl(ss->processed));
869 	(void) fprintf(fp, "bad authentication:     %ld\n",
870 		       (u_long)ntohl(ss->badauth));
871 	if (itemsize != sizeof(struct info_sys_stats))
872 	    return;
873 
874 	(void) fprintf(fp, "packets rejected:       %ld\n",
875 		       (u_long)ntohl(ss->limitrejected));
876 }
877 
878 
879 
880 /*
881  * iostats - print I/O statistics
882  */
883 /*ARGSUSED*/
884 static void
885 iostats(
886 	struct parse *pcmd,
887 	FILE *fp
888 	)
889 {
890 	struct info_io_stats *io;
891 	int items;
892 	int itemsize;
893 	int res;
894 
895 	res = doquery(IMPL_XNTPD, REQ_IO_STATS, 0, 0, 0, (char *)NULL,
896 		      &items, &itemsize, (char **)&io, 0);
897 
898 	if (res != 0 && items == 0)
899 	    return;
900 
901 	if (!check1item(items, fp))
902 	    return;
903 
904 	if (!checkitemsize(itemsize, sizeof(struct info_io_stats)))
905 	    return;
906 
907 	(void) fprintf(fp, "time since reset:     %ld\n",
908 		       (u_long)ntohl(io->timereset));
909 	(void) fprintf(fp, "receive buffers:      %d\n",
910 		       ntohs(io->totalrecvbufs));
911 	(void) fprintf(fp, "free receive buffers: %d\n",
912 		       ntohs(io->freerecvbufs));
913 	(void) fprintf(fp, "used receive buffers: %d\n",
914 		       ntohs(io->fullrecvbufs));
915 	(void) fprintf(fp, "low water refills:    %d\n",
916 		       ntohs(io->lowwater));
917 	(void) fprintf(fp, "dropped packets:      %ld\n",
918 		       (u_long)ntohl(io->dropped));
919 	(void) fprintf(fp, "ignored packets:      %ld\n",
920 		       (u_long)ntohl(io->ignored));
921 	(void) fprintf(fp, "received packets:     %ld\n",
922 		       (u_long)ntohl(io->received));
923 	(void) fprintf(fp, "packets sent:         %ld\n",
924 		       (u_long)ntohl(io->sent));
925 	(void) fprintf(fp, "packets not sent:     %ld\n",
926 		       (u_long)ntohl(io->notsent));
927 	(void) fprintf(fp, "interrupts handled:   %ld\n",
928 		       (u_long)ntohl(io->interrupts));
929 	(void) fprintf(fp, "received by int:      %ld\n",
930 		       (u_long)ntohl(io->int_received));
931 }
932 
933 
934 /*
935  * memstats - print peer memory statistics
936  */
937 /*ARGSUSED*/
938 static void
939 memstats(
940 	struct parse *pcmd,
941 	FILE *fp
942 	)
943 {
944 	struct info_mem_stats *mem;
945 	int i;
946 	int items;
947 	int itemsize;
948 	int res;
949 
950 	res = doquery(IMPL_XNTPD, REQ_MEM_STATS, 0, 0, 0, (char *)NULL,
951 		      &items, &itemsize, (char **)&mem, 0);
952 
953 	if (res != 0 && items == 0)
954 	    return;
955 
956 	if (!check1item(items, fp))
957 	    return;
958 
959 	if (!checkitemsize(itemsize, sizeof(struct info_mem_stats)))
960 	    return;
961 
962 	(void) fprintf(fp, "time since reset:     %ld\n",
963 		       (u_long)ntohl(mem->timereset));
964 	(void) fprintf(fp, "total peer memory:    %d\n",
965 		       ntohs(mem->totalpeermem));
966 	(void) fprintf(fp, "free peer memory:     %d\n",
967 		       ntohs(mem->freepeermem));
968 	(void) fprintf(fp, "calls to findpeer:    %ld\n",
969 		       (u_long)ntohl(mem->findpeer_calls));
970 	(void) fprintf(fp, "new peer allocations: %ld\n",
971 		       (u_long)ntohl(mem->allocations));
972 	(void) fprintf(fp, "peer demobilizations: %ld\n",
973 		       (u_long)ntohl(mem->demobilizations));
974 
975 	(void) fprintf(fp, "hash table counts:   ");
976 	for (i = 0; i < HASH_SIZE; i++) {
977 		(void) fprintf(fp, "%4d", (int)mem->hashcount[i]);
978 		if ((i % 8) == 7 && i != (HASH_SIZE-1)) {
979 			(void) fprintf(fp, "\n                     ");
980 		}
981 	}
982 	(void) fprintf(fp, "\n");
983 }
984 
985 
986 
987 /*
988  * timerstats - print timer statistics
989  */
990 /*ARGSUSED*/
991 static void
992 timerstats(
993 	struct parse *pcmd,
994 	FILE *fp
995 	)
996 {
997 	struct info_timer_stats *tim;
998 	int items;
999 	int itemsize;
1000 	int res;
1001 
1002 	res = doquery(IMPL_XNTPD, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL,
1003 		      &items, &itemsize, (char **)&tim, 0);
1004 
1005 	if (res != 0 && items == 0)
1006 	    return;
1007 
1008 	if (!check1item(items, fp))
1009 	    return;
1010 
1011 	if (!checkitemsize(itemsize, sizeof(struct info_timer_stats)))
1012 	    return;
1013 
1014 	(void) fprintf(fp, "time since reset:  %ld\n",
1015 		       (u_long)ntohl(tim->timereset));
1016 	(void) fprintf(fp, "alarms handled:    %ld\n",
1017 		       (u_long)ntohl(tim->alarms));
1018 	(void) fprintf(fp, "alarm overruns:    %ld\n",
1019 		       (u_long)ntohl(tim->overflows));
1020 	(void) fprintf(fp, "calls to transmit: %ld\n",
1021 		       (u_long)ntohl(tim->xmtcalls));
1022 }
1023 
1024 
1025 /*
1026  * addpeer - configure an active mode association
1027  */
1028 static void
1029 addpeer(
1030 	struct parse *pcmd,
1031 	FILE *fp
1032 	)
1033 {
1034 	doconfig(pcmd, fp, MODE_ACTIVE, 0);
1035 }
1036 
1037 
1038 /*
1039  * addserver - configure a client mode association
1040  */
1041 static void
1042 addserver(
1043 	struct parse *pcmd,
1044 	FILE *fp
1045 	)
1046 {
1047 	doconfig(pcmd, fp, MODE_CLIENT, 0);
1048 }
1049 
1050 /*
1051  * addrefclock - configure a reference clock association
1052  */
1053 static void
1054 addrefclock(
1055 	struct parse *pcmd,
1056 	FILE *fp
1057 	)
1058 {
1059 	doconfig(pcmd, fp, MODE_CLIENT, 1);
1060 }
1061 
1062 /*
1063  * broadcast - configure a broadcast mode association
1064  */
1065 static void
1066 broadcast(
1067 	struct parse *pcmd,
1068 	FILE *fp
1069 	)
1070 {
1071 	doconfig(pcmd, fp, MODE_BROADCAST, 0);
1072 }
1073 
1074 
1075 /*
1076  * config - configure a new peer association
1077  */
1078 static void
1079 doconfig(
1080 	struct parse *pcmd,
1081 	FILE *fp,
1082 	int mode,
1083         int refc
1084 	)
1085 {
1086 	struct conf_peer cpeer;
1087 	int items;
1088 	int itemsize;
1089 	char *dummy;
1090 	u_long keyid;
1091 	u_int version;
1092 	u_char minpoll;
1093 	u_int flags;
1094 	u_char cmode;
1095 	int res;
1096 
1097 	keyid = 0;
1098 	version = NTP_OLDVERSION + 1;
1099 	flags = 0;
1100 	res = 0;
1101 	cmode = 0;
1102 	minpoll = NTP_MINDPOLL;
1103 
1104 	items = pcmd->nargs;
1105 
1106 	if (refc) {
1107 		if (pcmd->nargs > 1) {
1108 			cmode = (u_char) pcmd->argval[1].uval;
1109 			items = 2;
1110 		}
1111 	} else {
1112 		if (pcmd->nargs > 1) {
1113 			keyid = pcmd->argval[1].uval;
1114 			if (keyid > 0) {
1115 				flags |= CONF_FLAG_AUTHENABLE;
1116 			}
1117 			if (pcmd->nargs > 2) {
1118 				version = (u_int)pcmd->argval[2].uval;
1119 				if (version > NTP_VERSION ||
1120 				    version < NTP_OLDVERSION) {
1121 					(void)fprintf(fp,
1122 					"invalid version number %u\n",
1123 					    version);
1124 					res++;
1125 				}
1126 				items = 3;
1127 			}
1128 		}
1129 	}
1130 
1131 	while (pcmd->nargs > items) {
1132 		if (STREQ(pcmd->argval[items].string, "prefer"))
1133 		    flags |= CONF_FLAG_PREFER;
1134 		else if (STREQ(pcmd->argval[items].string, "burst"))
1135 		    flags |= CONF_FLAG_BURST;
1136 		else {
1137 		        long val;
1138 			if (!atoint(pcmd->argval[items].string, &val)) {
1139 				(void) fprintf(fp,
1140 				    "%s not understood\n",
1141 				    pcmd->argval[items].string);
1142 				res++;
1143 				break;
1144 			} else {
1145 				if (val >= NTP_MINPOLL && val <= NTP_MAXPOLL) {
1146 					minpoll = (u_char)val;
1147 				} else {
1148 					(void) fprintf(fp,
1149 						       "minpol must be within %d..%d\n",
1150 						       NTP_MINPOLL, NTP_MAXPOLL);
1151 					res++;
1152 					break;
1153 				}
1154 			}
1155 		}
1156 		items++;
1157 	}
1158 
1159 	if (res)
1160 	    return;
1161 
1162 	memset((void *)&cpeer, 0, sizeof cpeer);
1163 
1164 	cpeer.peeraddr = pcmd->argval[0].netnum;
1165 	cpeer.hmode = (u_char) mode;
1166 	cpeer.keyid = keyid;
1167 	cpeer.version = (u_char) version;
1168 	cpeer.minpoll = minpoll;
1169 	cpeer.maxpoll = NTP_MAXDPOLL;
1170 	cpeer.flags = (u_char)flags;
1171 	cpeer.ttl = cmode;
1172 
1173 	res = doquery(IMPL_XNTPD, REQ_CONFIG, 1, 1,
1174 		      sizeof(struct conf_peer), (char *)&cpeer, &items,
1175 		      &itemsize, &dummy, 0);
1176 
1177 	if (res == INFO_ERR_FMT) {
1178 		(void) fprintf(fp,
1179 		    "***Retrying command with old conf_peer size\n");
1180 		res = doquery(IMPL_XNTPD, REQ_CONFIG, 1, 1,
1181 			      sizeof(struct old_conf_peer), (char *)&cpeer,
1182 			      &items, &itemsize, &dummy, 0);
1183 	}
1184 	if (res == 0)
1185 	    (void) fprintf(fp, "done!\n");
1186 	return;
1187 }
1188 
1189 
1190 /*
1191  * unconfig - unconfigure some associations
1192  */
1193 static void
1194 unconfig(
1195 	struct parse *pcmd,
1196 	FILE *fp
1197 	)
1198 {
1199 	/* 8 is the maximum number of peers which will fit in a packet */
1200 	struct conf_unpeer plist[min(MAXARGS, 8)];
1201 	int qitems;
1202 	int items;
1203 	int itemsize;
1204 	char *dummy;
1205 	int res;
1206 
1207 	for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) {
1208 		plist[qitems].peeraddr = pcmd->argval[qitems].netnum;
1209 	}
1210 
1211 	res = doquery(IMPL_XNTPD, REQ_UNCONFIG, 1, qitems,
1212 		      sizeof(struct conf_unpeer), (char *)plist, &items,
1213 		      &itemsize, &dummy, 0);
1214 
1215 	if (res == 0)
1216 	    (void) fprintf(fp, "done!\n");
1217 }
1218 
1219 
1220 /*
1221  * set - set some system flags
1222  */
1223 static void
1224 set(
1225 	struct parse *pcmd,
1226 	FILE *fp
1227 	)
1228 {
1229 	doset(pcmd, fp, REQ_SET_SYS_FLAG);
1230 }
1231 
1232 
1233 /*
1234  * clear - clear some system flags
1235  */
1236 static void
1237 sys_clear(
1238 	struct parse *pcmd,
1239 	FILE *fp
1240 	)
1241 {
1242 	doset(pcmd, fp, REQ_CLR_SYS_FLAG);
1243 }
1244 
1245 
1246 /*
1247  * doset - set/clear system flags
1248  */
1249 static void
1250 doset(
1251 	struct parse *pcmd,
1252 	FILE *fp,
1253 	int req
1254 	)
1255 {
1256 	/* 8 is the maximum number of peers which will fit in a packet */
1257 	struct conf_sys_flags sys;
1258 	int items;
1259 	int itemsize;
1260 	char *dummy;
1261 	int res;
1262 
1263 	sys.flags = 0;
1264 	res = 0;
1265 	for (items = 0; items < pcmd->nargs; items++) {
1266 		if (STREQ(pcmd->argval[items].string, "auth"))
1267 			sys.flags |= SYS_FLAG_AUTH;
1268 		else if (STREQ(pcmd->argval[items].string, "bclient"))
1269 			sys.flags |= SYS_FLAG_BCLIENT;
1270 		else if (STREQ(pcmd->argval[items].string, "calibrate"))
1271 			sys.flags |= SYS_FLAG_CAL;
1272 		else if (STREQ(pcmd->argval[items].string, "kernel"))
1273 			sys.flags |= SYS_FLAG_KERNEL;
1274 		else if (STREQ(pcmd->argval[items].string, "monitor"))
1275 			sys.flags |= SYS_FLAG_MONITOR;
1276 		else if (STREQ(pcmd->argval[items].string, "ntp"))
1277 			sys.flags |= SYS_FLAG_NTP;
1278 		else if (STREQ(pcmd->argval[items].string, "pps"))
1279 			sys.flags |= SYS_FLAG_PPS;
1280 		else if (STREQ(pcmd->argval[items].string, "stats"))
1281 			sys.flags |= SYS_FLAG_FILEGEN;
1282 		else {
1283 			(void) fprintf(fp, "Unknown flag %s\n",
1284 			    pcmd->argval[items].string);
1285 			res = 1;
1286 		}
1287 	}
1288 
1289 	if (res || sys.flags == 0)
1290 	    return;
1291 
1292 	res = doquery(IMPL_XNTPD, req, 1, 1,
1293 		      sizeof(struct conf_sys_flags), (char *)&sys, &items,
1294 		      &itemsize, &dummy, 0);
1295 
1296 	if (res == 0)
1297 	    (void) fprintf(fp, "done!\n");
1298 }
1299 
1300 
1301 /*
1302  * data for printing/interrpreting the restrict flags
1303  */
1304 struct resflags {
1305   const char *str;
1306 	int bit;
1307 };
1308 
1309 static struct resflags resflags[] = {
1310 	{ "ignore",	RES_IGNORE },
1311 	{ "noserve",	RES_DONTSERVE },
1312 	{ "notrust",	RES_DONTTRUST },
1313 	{ "noquery",	RES_NOQUERY },
1314 	{ "nomodify",	RES_NOMODIFY },
1315 	{ "nopeer",	RES_NOPEER },
1316 	{ "notrap",	RES_NOTRAP },
1317 	{ "lptrap",	RES_LPTRAP },
1318 	{ "limited",	RES_LIMITED },
1319 	{ "version",	RES_VERSION },
1320 	{ "kod",	RES_DEMOBILIZE },
1321 
1322 	{ "",		0 }
1323 };
1324 
1325 static struct resflags resmflags[] = {
1326 	{ "ntpport",	RESM_NTPONLY },
1327 	{ "interface",	RESM_INTERFACE },
1328 	{ "",		0 }
1329 };
1330 
1331 
1332 /*
1333  * reslist - obtain and print the server's restrict list
1334  */
1335 /*ARGSUSED*/
1336 static void
1337 reslist(
1338 	struct parse *pcmd,
1339 	FILE *fp
1340 	)
1341 {
1342 	struct info_restrict *rl;
1343 	int items;
1344 	int itemsize;
1345 	int res;
1346 	char *addr;
1347 	char *mask;
1348 	struct resflags *rf;
1349 	u_int32 count;
1350 	u_short flags;
1351 	u_short mflags;
1352 	char flagstr[300];
1353 	static const char *comma = ", ";
1354 
1355 	res = doquery(IMPL_XNTPD, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
1356 		      &items, &itemsize, (char **)&rl, 0);
1357 
1358 	if (res != 0 && items == 0)
1359 	    return;
1360 
1361 	if (!checkitems(items, fp))
1362 	    return;
1363 
1364 	if (!checkitemsize(itemsize, sizeof(struct info_restrict)))
1365 	    return;
1366 
1367 	(void) fprintf(fp,
1368 		       "   address          mask            count        flags\n");
1369 	(void) fprintf(fp,
1370 		       "=====================================================================\n");
1371 	while (items > 0) {
1372 		if ((rl->mask == (u_int32)0xffffffff))
1373 		    addr = nntohost(rl->addr);
1374 		else
1375 		    addr = numtoa( rl->addr );
1376 		mask = numtoa(rl->mask);
1377 		count = ntohl(rl->count);
1378 		flags = ntohs(rl->flags);
1379 		mflags = ntohs(rl->mflags);
1380 		flagstr[0] = '\0';
1381 
1382 		res = 1;
1383 		rf = &resmflags[0];
1384 		while (rf->bit != 0) {
1385 			if (mflags & rf->bit) {
1386 				if (!res)
1387 				    (void) strcat(flagstr, comma);
1388 				res = 0;
1389 				(void) strcat(flagstr, rf->str);
1390 			}
1391 			rf++;
1392 		}
1393 
1394 		rf = &resflags[0];
1395 		while (rf->bit != 0) {
1396 			if (flags & rf->bit) {
1397 				if (!res)
1398 				    (void) strcat(flagstr, comma);
1399 				res = 0;
1400 				(void) strcat(flagstr, rf->str);
1401 			}
1402 			rf++;
1403 		}
1404 
1405 		if (flagstr[0] == '\0')
1406 		    (void) strcpy(flagstr, "none");
1407 
1408 		(void) fprintf(fp, "%-15.15s %-15.15s %9ld  %s\n",
1409 			       addr, mask, (u_long)count, flagstr);
1410 		rl++;
1411 		items--;
1412 	}
1413 }
1414 
1415 
1416 
1417 /*
1418  * new_restrict - create/add a set of restrictions
1419  */
1420 static void
1421 new_restrict(
1422 	struct parse *pcmd,
1423 	FILE *fp
1424 	)
1425 {
1426 	do_restrict(pcmd, fp, REQ_RESADDFLAGS);
1427 }
1428 
1429 
1430 /*
1431  * unrestrict - remove restriction flags from existing entry
1432  */
1433 static void
1434 unrestrict(
1435 	struct parse *pcmd,
1436 	FILE *fp
1437 	)
1438 {
1439 	do_restrict(pcmd, fp, REQ_RESSUBFLAGS);
1440 }
1441 
1442 
1443 /*
1444  * delrestrict - delete an existing restriction
1445  */
1446 static void
1447 delrestrict(
1448 	struct parse *pcmd,
1449 	FILE *fp
1450 	)
1451 {
1452 	do_restrict(pcmd, fp, REQ_UNRESTRICT);
1453 }
1454 
1455 
1456 /*
1457  * do_restrict - decode commandline restrictions and make the request
1458  */
1459 static void
1460 do_restrict(
1461 	struct parse *pcmd,
1462 	FILE *fp,
1463 	int req_code
1464 	)
1465 {
1466 	struct conf_restrict cres;
1467 	int items;
1468 	int itemsize;
1469 	char *dummy;
1470 	u_int32 num;
1471 	u_long bit;
1472 	int i;
1473 	int res;
1474 	int err;
1475 
1476 	cres.addr = pcmd->argval[0].netnum;
1477 	cres.mask = pcmd->argval[1].netnum;
1478 	cres.flags = 0;
1479 	cres.mflags = 0;
1480 	err = 0;
1481 	for (res = 2; res < pcmd->nargs; res++) {
1482 		if (STREQ(pcmd->argval[res].string, "ntpport")) {
1483 			cres.mflags |= RESM_NTPONLY;
1484 		} else {
1485 			for (i = 0; resflags[i].bit != 0; i++) {
1486 				if (STREQ(pcmd->argval[res].string,
1487 					  resflags[i].str))
1488 				    break;
1489 			}
1490 			if (resflags[i].bit != 0) {
1491 				cres.flags |= resflags[i].bit;
1492 				if (req_code == REQ_UNRESTRICT) {
1493 					(void) fprintf(fp,
1494 						       "Flag %s inappropriate\n",
1495 						       resflags[i].str);
1496 					err++;
1497 				}
1498 			} else {
1499 				(void) fprintf(fp, "Unknown flag %s\n",
1500 					       pcmd->argval[res].string);
1501 				err++;
1502 			}
1503 		}
1504 	}
1505 
1506 	/*
1507 	 * Make sure mask for default address is zero.  Otherwise,
1508 	 * make sure mask bits are contiguous.
1509 	 */
1510 	if (cres.addr == 0) {
1511 		cres.mask = 0;
1512 	} else {
1513 		num = ntohl(cres.mask);
1514 		for (bit = 0x80000000; bit != 0; bit >>= 1)
1515 		    if ((num & bit) == 0)
1516 			break;
1517 		for ( ; bit != 0; bit >>= 1)
1518 		    if ((num & bit) != 0)
1519 			break;
1520 		if (bit != 0) {
1521 			(void) fprintf(fp, "Invalid mask %s\n",
1522 				       numtoa(cres.mask));
1523 			err++;
1524 		}
1525 	}
1526 
1527 	if (err)
1528 	    return;
1529 
1530 	res = doquery(IMPL_XNTPD, req_code, 1, 1,
1531 		      sizeof(struct conf_restrict), (char *)&cres, &items,
1532 		      &itemsize, &dummy, 0);
1533 
1534 	if (res == 0)
1535 	    (void) fprintf(fp, "done!\n");
1536 	return;
1537 }
1538 
1539 
1540 /*
1541  * monlist - obtain and print the server's monitor data
1542  */
1543 /*ARGSUSED*/
1544 static void
1545 monlist(
1546 	struct parse *pcmd,
1547 	FILE *fp
1548 	)
1549 {
1550 	char *struct_star;
1551 	struct in_addr addr;
1552 	int items;
1553 	int itemsize;
1554 	int res;
1555 	int version = -1;
1556 
1557 	if (pcmd->nargs > 0) {
1558 		version = pcmd->argval[0].ival;
1559 	}
1560 
1561 	res = doquery(IMPL_XNTPD,
1562 		      (version == 1 || version == -1) ? REQ_MON_GETLIST_1 :
1563 		      REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
1564 		      &items, &itemsize, &struct_star,
1565 		      (version < 0) ? (1 << INFO_ERR_REQ) : 0);
1566 
1567 	if (res == INFO_ERR_REQ && version < 0)
1568 	    res = doquery(IMPL_XNTPD, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
1569 			  &items, &itemsize, &struct_star, 0);
1570 
1571 	if (res != 0 && items == 0)
1572 	    return;
1573 
1574 	if (!checkitems(items, fp))
1575 	    return;
1576 
1577 	if (itemsize == sizeof(struct info_monitor_1)) {
1578 		struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star;
1579 
1580 		(void) fprintf(fp,
1581 			       "remote address          port local address      count m ver drop   last   first\n");
1582 		(void) fprintf(fp,
1583 			       "===============================================================================\n");
1584 		while (items > 0) {
1585 			addr.s_addr = ml->daddr;
1586 			(void) fprintf(fp,
1587 				       "%-22.22s %5d %-15s %8ld %1d %1d %6lu %6lu %7lu\n",
1588 				       nntohost(ml->addr),
1589 				       ntohs(ml->port),
1590 				       inet_ntoa(addr),
1591 				       (u_long)ntohl(ml->count),
1592 				       ml->mode,
1593 				       ml->version,
1594 				       (u_long)ntohl(ml->lastdrop),
1595 				       (u_long)ntohl(ml->lasttime),
1596 				       (u_long)ntohl(ml->firsttime));
1597 			ml++;
1598 			items--;
1599 		}
1600 	} else if (itemsize == sizeof(struct info_monitor)) {
1601 		struct info_monitor *ml = (struct info_monitor *) struct_star;
1602 
1603 		(void) fprintf(fp,
1604 			       "     address               port     count mode ver lastdrop  lasttime firsttime\n");
1605 		(void) fprintf(fp,
1606 			       "===============================================================================\n");
1607 		while (items > 0) {
1608 			addr.s_addr = ml->lastdrop;
1609 			(void) fprintf(fp,
1610 				       "%-25.25s %5d %9ld %4d %2d %9lu %9lu %9lu\n",
1611 				       nntohost(ml->addr),
1612 				       ntohs(ml->port),
1613 				       (u_long)ntohl(ml->count),
1614 				       ml->mode,
1615 				       ml->version,
1616 				       (u_long)ntohl(ml->lastdrop),
1617 				       (u_long)ntohl(ml->lasttime),
1618 				       (u_long)ntohl(ml->firsttime));
1619 			ml++;
1620 			items--;
1621 		}
1622 	} else if (itemsize == sizeof(struct old_info_monitor)) {
1623 		struct old_info_monitor *oml = (struct old_info_monitor *)struct_star;
1624 		(void) fprintf(fp,
1625 			       "     address          port     count  mode version  lasttime firsttime\n");
1626 		(void) fprintf(fp,
1627 			       "======================================================================\n");
1628 		while (items > 0) {
1629 			(void) fprintf(fp, "%-20.20s %5d %9ld %4d   %3d %9lu %9lu\n",
1630 				       nntohost(oml->addr),
1631 				       ntohs(oml->port),
1632 				       (u_long)ntohl(oml->count),
1633 				       oml->mode,
1634 				       oml->version,
1635 				       (u_long)ntohl(oml->lasttime),
1636 				       (u_long)ntohl(oml->firsttime));
1637 			oml++;
1638 			items--;
1639 		}
1640 	} else {
1641 		/* issue warning according to new info_monitor size */
1642 		checkitemsize(itemsize, sizeof(struct info_monitor));
1643 	}
1644 }
1645 
1646 
1647 /*
1648  * Mapping between command line strings and stat reset flags
1649  */
1650 struct statreset {
1651   const char *str;
1652 	int flag;
1653 } sreset[] = {
1654 	{ "io",		RESET_FLAG_IO },
1655 	{ "sys",	RESET_FLAG_SYS },
1656 	{ "mem",	RESET_FLAG_MEM },
1657 	{ "timer",	RESET_FLAG_TIMER },
1658 	{ "auth",	RESET_FLAG_AUTH },
1659 	{ "allpeers",	RESET_FLAG_ALLPEERS },
1660 	{ "",		0 }
1661 };
1662 
1663 /*
1664  * reset - reset statistic counters
1665  */
1666 static void
1667 reset(
1668 	struct parse *pcmd,
1669 	FILE *fp
1670 	)
1671 {
1672 	struct reset_flags rflags;
1673 	int items;
1674 	int itemsize;
1675 	char *dummy;
1676 	int i;
1677 	int res;
1678 	int err;
1679 
1680 	err = 0;
1681 	rflags.flags = 0;
1682 	for (res = 0; res < pcmd->nargs; res++) {
1683 		for (i = 0; sreset[i].flag != 0; i++) {
1684 			if (STREQ(pcmd->argval[res].string, sreset[i].str))
1685 			    break;
1686 		}
1687 		if (sreset[i].flag == 0) {
1688 			(void) fprintf(fp, "Flag %s unknown\n",
1689 				       pcmd->argval[res].string);
1690 			err++;
1691 		} else {
1692 			rflags.flags |= sreset[i].flag;
1693 		}
1694 	}
1695 
1696 	if (err) {
1697 		(void) fprintf(fp, "Not done due to errors\n");
1698 		return;
1699 	}
1700 
1701 	res = doquery(IMPL_XNTPD, REQ_RESET_STATS, 1, 1,
1702 		      sizeof(struct reset_flags), (char *)&rflags, &items,
1703 		      &itemsize, &dummy, 0);
1704 
1705 	if (res == 0)
1706 	    (void) fprintf(fp, "done!\n");
1707 	return;
1708 }
1709 
1710 
1711 
1712 /*
1713  * preset - reset stat counters for particular peers
1714  */
1715 static void
1716 preset(
1717 	struct parse *pcmd,
1718 	FILE *fp
1719 	)
1720 {
1721 	/* 8 is the maximum number of peers which will fit in a packet */
1722 	struct conf_unpeer plist[min(MAXARGS, 8)];
1723 	int qitems;
1724 	int items;
1725 	int itemsize;
1726 	char *dummy;
1727 	int res;
1728 
1729 	for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) {
1730 		plist[qitems].peeraddr = pcmd->argval[qitems].netnum;
1731 	}
1732 
1733 	res = doquery(IMPL_XNTPD, REQ_RESET_PEER, 1, qitems,
1734 		      sizeof(struct conf_unpeer), (char *)plist, &items,
1735 		      &itemsize, &dummy, 0);
1736 
1737 	if (res == 0)
1738 	    (void) fprintf(fp, "done!\n");
1739 }
1740 
1741 
1742 /*
1743  * readkeys - request the server to reread the keys file
1744  */
1745 /*ARGSUSED*/
1746 static void
1747 readkeys(
1748 	struct parse *pcmd,
1749 	FILE *fp
1750 	)
1751 {
1752 	int items;
1753 	int itemsize;
1754 	char *dummy;
1755 	int res;
1756 
1757 	res = doquery(IMPL_XNTPD, REQ_REREAD_KEYS, 1, 0, 0, (char *)0,
1758 		      &items, &itemsize, &dummy, 0);
1759 
1760 	if (res == 0)
1761 	    (void) fprintf(fp, "done!\n");
1762 	return;
1763 }
1764 
1765 
1766 /*
1767  * trustkey - add some keys to the trusted key list
1768  */
1769 static void
1770 trustkey(
1771 	struct parse *pcmd,
1772 	FILE *fp
1773 	)
1774 {
1775 	do_trustkey(pcmd, fp, REQ_TRUSTKEY);
1776 }
1777 
1778 
1779 /*
1780  * untrustkey - remove some keys from the trusted key list
1781  */
1782 static void
1783 untrustkey(
1784 	struct parse *pcmd,
1785 	FILE *fp
1786 	)
1787 {
1788 	do_trustkey(pcmd, fp, REQ_UNTRUSTKEY);
1789 }
1790 
1791 
1792 /*
1793  * do_trustkey - do grunge work of adding/deleting keys
1794  */
1795 static void
1796 do_trustkey(
1797 	struct parse *pcmd,
1798 	FILE *fp,
1799 	int req
1800 	)
1801 {
1802 	u_long keyids[MAXARGS];
1803 	int i;
1804 	int items;
1805 	int itemsize;
1806 	char *dummy;
1807 	int ritems;
1808 	int res;
1809 
1810 	ritems = 0;
1811 	for (i = 0; i < pcmd->nargs; i++) {
1812 		keyids[ritems++] = pcmd->argval[i].uval;
1813 	}
1814 
1815 	res = doquery(IMPL_XNTPD, req, 1, ritems, sizeof(u_long),
1816 		      (char *)keyids, &items, &itemsize, &dummy, 0);
1817 
1818 	if (res == 0)
1819 	    (void) fprintf(fp, "done!\n");
1820 	return;
1821 }
1822 
1823 
1824 
1825 /*
1826  * authinfo - obtain and print info about authentication
1827  */
1828 /*ARGSUSED*/
1829 static void
1830 authinfo(
1831 	struct parse *pcmd,
1832 	FILE *fp
1833 	)
1834 {
1835 	struct info_auth *ia;
1836 	int items;
1837 	int itemsize;
1838 	int res;
1839 
1840 	res = doquery(IMPL_XNTPD, REQ_AUTHINFO, 0, 0, 0, (char *)NULL,
1841 		      &items, &itemsize, (char **)&ia, 0);
1842 
1843 	if (res != 0 && items == 0)
1844 	    return;
1845 
1846 	if (!check1item(items, fp))
1847 	    return;
1848 
1849 	if (!checkitemsize(itemsize, sizeof(struct info_auth)))
1850 	    return;
1851 
1852 	(void) fprintf(fp, "time since reset:     %ld\n",
1853 	    (u_long)ntohl(ia->timereset));
1854 	(void) fprintf(fp, "stored keys:          %ld\n",
1855 	    (u_long)ntohl(ia->numkeys));
1856 	(void) fprintf(fp, "free keys:            %ld\n",
1857 	    (u_long)ntohl(ia->numfreekeys));
1858 	(void) fprintf(fp, "key lookups:          %ld\n",
1859 	    (u_long)ntohl(ia->keylookups));
1860 	(void) fprintf(fp, "keys not found:       %ld\n",
1861 	    (u_long)ntohl(ia->keynotfound));
1862 	(void) fprintf(fp, "uncached keys:        %ld\n",
1863 	    (u_long)ntohl(ia->keyuncached));
1864 	(void) fprintf(fp, "encryptions:          %ld\n",
1865 	    (u_long)ntohl(ia->encryptions));
1866 	(void) fprintf(fp, "decryptions:          %ld\n",
1867 	    (u_long)ntohl(ia->decryptions));
1868 	(void) fprintf(fp, "expired keys:         %ld\n",
1869 	    (u_long)ntohl(ia->expired));
1870 }
1871 
1872 
1873 
1874 /*
1875  * traps - obtain and print a list of traps
1876  */
1877 /*ARGSUSED*/
1878 static void
1879 traps(
1880 	struct parse *pcmd,
1881 	FILE *fp
1882 	)
1883 {
1884 	int i;
1885 	struct info_trap *it;
1886 	int items;
1887 	int itemsize;
1888 	int res;
1889 
1890 	res = doquery(IMPL_XNTPD, REQ_TRAPS, 0, 0, 0, (char *)NULL,
1891 		      &items, &itemsize, (char **)&it, 0);
1892 
1893 	if (res != 0 && items == 0)
1894 	    return;
1895 
1896 	if (!checkitems(items, fp))
1897 	    return;
1898 
1899 	if (!checkitemsize(itemsize, sizeof(struct info_trap)))
1900 	    return;
1901 
1902 	for (i = 0; i < items; i++ ) {
1903 		if (i != 0)
1904 		    (void) fprintf(fp, "\n");
1905 		(void) fprintf(fp, "address %s, port %d\n",
1906 			       numtoa(it->trap_address), ntohs(it->trap_port));
1907 		(void) fprintf(fp, "interface: %s, ",
1908 			       (it->local_address == 0)
1909 			       ? "wildcard"
1910 			       : numtoa(it->local_address));
1911 
1912 		if (ntohl(it->flags) & TRAP_CONFIGURED)
1913 		    (void) fprintf(fp, "configured\n");
1914 		else if (ntohl(it->flags) & TRAP_NONPRIO)
1915 		    (void) fprintf(fp, "low priority\n");
1916 		else
1917 		    (void) fprintf(fp, "normal priority\n");
1918 
1919 		(void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n",
1920 			       (long)ntohl(it->origtime),
1921 			       (long)ntohl(it->settime));
1922 		(void) fprintf(fp, "sequence %d, number of resets %ld\n",
1923 			       ntohs(it->sequence),
1924 			       (long)ntohl(it->resets));
1925 	}
1926 }
1927 
1928 
1929 /*
1930  * addtrap - configure a trap
1931  */
1932 static void
1933 addtrap(
1934 	struct parse *pcmd,
1935 	FILE *fp
1936 	)
1937 {
1938 	do_addclr_trap(pcmd, fp, REQ_ADD_TRAP);
1939 }
1940 
1941 
1942 /*
1943  * clrtrap - clear a trap from the server
1944  */
1945 static void
1946 clrtrap(
1947 	struct parse *pcmd,
1948 	FILE *fp
1949 	)
1950 {
1951 	do_addclr_trap(pcmd, fp, REQ_CLR_TRAP);
1952 }
1953 
1954 
1955 /*
1956  * do_addclr_trap - do grunge work of adding/deleting traps
1957  */
1958 static void
1959 do_addclr_trap(
1960 	struct parse *pcmd,
1961 	FILE *fp,
1962 	int req
1963 	)
1964 {
1965 	struct conf_trap ctrap;
1966 	int items;
1967 	int itemsize;
1968 	char *dummy;
1969 	int res;
1970 
1971 	ctrap.trap_address = pcmd->argval[0].netnum;
1972 	ctrap.local_address = 0;
1973 	ctrap.trap_port = htons(TRAPPORT);
1974 	ctrap.unused = 0;
1975 
1976 	if (pcmd->nargs > 1) {
1977 		ctrap.trap_port
1978 			= htons((u_short)(pcmd->argval[1].uval & 0xffff));
1979 		if (pcmd->nargs > 2)
1980 		    ctrap.local_address = pcmd->argval[2].netnum;
1981 	}
1982 
1983 	res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(struct conf_trap),
1984 		      (char *)&ctrap, &items, &itemsize, &dummy, 0);
1985 
1986 	if (res == 0)
1987 	    (void) fprintf(fp, "done!\n");
1988 	return;
1989 }
1990 
1991 
1992 
1993 /*
1994  * requestkey - change the server's request key (a dangerous request)
1995  */
1996 static void
1997 requestkey(
1998 	struct parse *pcmd,
1999 	FILE *fp
2000 	)
2001 {
2002 	do_changekey(pcmd, fp, REQ_REQUEST_KEY);
2003 }
2004 
2005 
2006 /*
2007  * controlkey - change the server's control key
2008  */
2009 static void
2010 controlkey(
2011 	struct parse *pcmd,
2012 	FILE *fp
2013 	)
2014 {
2015 	do_changekey(pcmd, fp, REQ_CONTROL_KEY);
2016 }
2017 
2018 
2019 
2020 /*
2021  * do_changekey - do grunge work of changing keys
2022  */
2023 static void
2024 do_changekey(
2025 	struct parse *pcmd,
2026 	FILE *fp,
2027 	int req
2028 	)
2029 {
2030 	u_long key;
2031 	int items;
2032 	int itemsize;
2033 	char *dummy;
2034 	int res;
2035 
2036 
2037 	key = htonl((u_int32)pcmd->argval[0].uval);
2038 
2039 	res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(u_int32),
2040 		      (char *)&key, &items, &itemsize, &dummy, 0);
2041 
2042 	if (res == 0)
2043 	    (void) fprintf(fp, "done!\n");
2044 	return;
2045 }
2046 
2047 
2048 
2049 /*
2050  * ctlstats - obtain and print info about authentication
2051  */
2052 /*ARGSUSED*/
2053 static void
2054 ctlstats(
2055 	struct parse *pcmd,
2056 	FILE *fp
2057 	)
2058 {
2059 	struct info_control *ic;
2060 	int items;
2061 	int itemsize;
2062 	int res;
2063 
2064 	res = doquery(IMPL_XNTPD, REQ_GET_CTLSTATS, 0, 0, 0, (char *)NULL,
2065 		      &items, &itemsize, (char **)&ic, 0);
2066 
2067 	if (res != 0 && items == 0)
2068 	    return;
2069 
2070 	if (!check1item(items, fp))
2071 	    return;
2072 
2073 	if (!checkitemsize(itemsize, sizeof(struct info_control)))
2074 	    return;
2075 
2076 	(void) fprintf(fp, "time since reset:       %ld\n",
2077 		       (u_long)ntohl(ic->ctltimereset));
2078 	(void) fprintf(fp, "requests received:      %ld\n",
2079 		       (u_long)ntohl(ic->numctlreq));
2080 	(void) fprintf(fp, "responses sent:         %ld\n",
2081 		       (u_long)ntohl(ic->numctlresponses));
2082 	(void) fprintf(fp, "fragments sent:         %ld\n",
2083 		       (u_long)ntohl(ic->numctlfrags));
2084 	(void) fprintf(fp, "async messages sent:    %ld\n",
2085 		       (u_long)ntohl(ic->numasyncmsgs));
2086 	(void) fprintf(fp, "error msgs sent:        %ld\n",
2087 		       (u_long)ntohl(ic->numctlerrors));
2088 	(void) fprintf(fp, "total bad pkts:         %ld\n",
2089 		       (u_long)ntohl(ic->numctlbadpkts));
2090 	(void) fprintf(fp, "packet too short:       %ld\n",
2091 		       (u_long)ntohl(ic->numctltooshort));
2092 	(void) fprintf(fp, "response on input:      %ld\n",
2093 		       (u_long)ntohl(ic->numctlinputresp));
2094 	(void) fprintf(fp, "fragment on input:      %ld\n",
2095 		       (u_long)ntohl(ic->numctlinputfrag));
2096 	(void) fprintf(fp, "error set on input:     %ld\n",
2097 		       (u_long)ntohl(ic->numctlinputerr));
2098 	(void) fprintf(fp, "bad offset on input:    %ld\n",
2099 		       (u_long)ntohl(ic->numctlbadoffset));
2100 	(void) fprintf(fp, "bad version packets:    %ld\n",
2101 		       (u_long)ntohl(ic->numctlbadversion));
2102 	(void) fprintf(fp, "data in pkt too short:  %ld\n",
2103 		       (u_long)ntohl(ic->numctldatatooshort));
2104 	(void) fprintf(fp, "unknown op codes:       %ld\n",
2105 		       (u_long)ntohl(ic->numctlbadop));
2106 }
2107 
2108 
2109 /*
2110  * clockstat - get and print clock status information
2111  */
2112 static void
2113 clockstat(
2114 	struct parse *pcmd,
2115 	FILE *fp
2116 	)
2117 {
2118 	struct info_clock *cl;
2119 	/* 8 is the maximum number of clocks which will fit in a packet */
2120 	u_long clist[min(MAXARGS, 8)];
2121 	int qitems;
2122 	int items;
2123 	int itemsize;
2124 	int res;
2125 	l_fp ts;
2126 	struct clktype *clk;
2127 	u_long ltemp;
2128 
2129 	for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++)
2130 	    clist[qitems] = pcmd->argval[qitems].netnum;
2131 
2132 	res = doquery(IMPL_XNTPD, REQ_GET_CLOCKINFO, 0, qitems,
2133 		      sizeof(u_int32), (char *)clist, &items,
2134 		      &itemsize, (char **)&cl, 0);
2135 
2136 	if (res != 0 && items == 0)
2137 	    return;
2138 
2139 	if (!checkitems(items, fp))
2140 	    return;
2141 
2142 	if (!checkitemsize(itemsize, sizeof(struct info_clock)))
2143 	    return;
2144 
2145 	while (items-- > 0) {
2146 		(void) fprintf(fp, "clock address:        %s\n",
2147 			       numtoa(cl->clockadr));
2148 		for (clk = clktypes; clk->code >= 0; clk++)
2149 		    if (clk->code == cl->type)
2150 			break;
2151 		if (clk->code >= 0)
2152 		    (void) fprintf(fp, "clock type:           %s\n",
2153 				   clk->clocktype);
2154 		else
2155 		    (void) fprintf(fp, "clock type:           unknown type (%d)\n",
2156 				   cl->type);
2157 		(void) fprintf(fp, "last event:           %d\n",
2158 			       cl->lastevent);
2159 		(void) fprintf(fp, "current status:       %d\n",
2160 			       cl->currentstatus);
2161 		(void) fprintf(fp, "number of polls:      %lu\n",
2162 			       (u_long)ntohl(cl->polls));
2163 		(void) fprintf(fp, "no response to poll:  %lu\n",
2164 			       (u_long)ntohl(cl->noresponse));
2165 		(void) fprintf(fp, "bad format responses: %lu\n",
2166 			       (u_long)ntohl(cl->badformat));
2167 		(void) fprintf(fp, "bad data responses:   %lu\n",
2168 			       (u_long)ntohl(cl->baddata));
2169 		(void) fprintf(fp, "running time:         %lu\n",
2170 			       (u_long)ntohl(cl->timestarted));
2171 		NTOHL_FP(&cl->fudgetime1, &ts);
2172 		(void) fprintf(fp, "fudge time 1:         %s\n",
2173 			       lfptoa(&ts, 6));
2174 		NTOHL_FP(&cl->fudgetime2, &ts);
2175 		(void) fprintf(fp, "fudge time 2:         %s\n",
2176 			       lfptoa(&ts, 6));
2177 		(void) fprintf(fp, "stratum:              %ld\n",
2178 			       (u_long)ntohl(cl->fudgeval1));
2179 		ltemp = ntohl(cl->fudgeval2);
2180 		(void) fprintf(fp, "reference ID:         %s\n",
2181 			       (char *)&ltemp);
2182 		(void) fprintf(fp, "fudge flags:          0x%x\n",
2183 			       cl->flags);
2184 
2185 		if (items > 0)
2186 		    (void) fprintf(fp, "\n");
2187 		cl++;
2188 	}
2189 }
2190 
2191 
2192 /*
2193  * fudge - set clock fudge factors
2194  */
2195 static void
2196 fudge(
2197 	struct parse *pcmd,
2198 	FILE *fp
2199 	)
2200 {
2201 	struct conf_fudge fudgedata;
2202 	int items;
2203 	int itemsize;
2204 	char *dummy;
2205 	l_fp ts;
2206 	int res;
2207 	long val;
2208 	u_long u_val;
2209 	int err;
2210 
2211 
2212 	err = 0;
2213 	memset((char *)&fudgedata, 0, sizeof fudgedata);
2214 	fudgedata.clockadr = pcmd->argval[0].netnum;
2215 
2216 	if (STREQ(pcmd->argval[1].string, "time1")) {
2217 		fudgedata.which = htonl(FUDGE_TIME1);
2218 		if (!atolfp(pcmd->argval[2].string, &ts))
2219 		    err = 1;
2220 		else
2221 		    NTOHL_FP(&ts, &fudgedata.fudgetime);
2222 	} else if (STREQ(pcmd->argval[1].string, "time2")) {
2223 		fudgedata.which = htonl(FUDGE_TIME2);
2224 		if (!atolfp(pcmd->argval[2].string, &ts))
2225 		    err = 1;
2226 		else
2227 		    NTOHL_FP(&ts, &fudgedata.fudgetime);
2228 	} else if (STREQ(pcmd->argval[1].string, "val1")) {
2229 		fudgedata.which = htonl(FUDGE_VAL1);
2230 		if (!atoint(pcmd->argval[2].string, &val))
2231 		    err = 1;
2232 		else
2233 		    fudgedata.fudgeval_flags = htonl(val);
2234 	} else if (STREQ(pcmd->argval[1].string, "val2")) {
2235 		fudgedata.which = htonl(FUDGE_VAL2);
2236 		if (!atoint(pcmd->argval[2].string, &val))
2237 		    err = 1;
2238 		else
2239 		    fudgedata.fudgeval_flags = htonl((u_int32)val);
2240 	} else if (STREQ(pcmd->argval[1].string, "flags")) {
2241 		fudgedata.which = htonl(FUDGE_FLAGS);
2242 		if (!hextoint(pcmd->argval[2].string, &u_val))
2243 		    err = 1;
2244 		else
2245 		    fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf));
2246 	} else {
2247 		(void) fprintf(stderr, "What fudge is %s?\n",
2248 			       pcmd->argval[1].string);
2249 		return;
2250 	}
2251 
2252 	if (err) {
2253 		(void) fprintf(stderr, "Unknown fudge parameter %s\n",
2254 			       pcmd->argval[2].string);
2255 		return;
2256 	}
2257 
2258 
2259 	res = doquery(IMPL_XNTPD, REQ_SET_CLKFUDGE, 1, 1,
2260 		      sizeof(struct conf_fudge), (char *)&fudgedata, &items,
2261 		      &itemsize, &dummy, 0);
2262 
2263 	if (res == 0)
2264 	    (void) fprintf(fp, "done!\n");
2265 	return;
2266 }
2267 
2268 /*
2269  * clkbug - get and print clock debugging information
2270  */
2271 static void
2272 clkbug(
2273 	struct parse *pcmd,
2274 	FILE *fp
2275 	)
2276 {
2277 	register int i;
2278 	register int n;
2279 	register u_int32 s;
2280 	struct info_clkbug *cl;
2281 	/* 8 is the maximum number of clocks which will fit in a packet */
2282 	u_long clist[min(MAXARGS, 8)];
2283 	u_int32 ltemp;
2284 	int qitems;
2285 	int items;
2286 	int itemsize;
2287 	int res;
2288 	int needsp;
2289 	l_fp ts;
2290 
2291 	for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++)
2292 	    clist[qitems] = pcmd->argval[qitems].netnum;
2293 
2294 	res = doquery(IMPL_XNTPD, REQ_GET_CLKBUGINFO, 0, qitems,
2295 		      sizeof(u_int32), (char *)clist, &items,
2296 		      &itemsize, (char **)&cl, 0);
2297 
2298 	if (res != 0 && items == 0)
2299 	    return;
2300 
2301 	if (!checkitems(items, fp))
2302 	    return;
2303 
2304 	if (!checkitemsize(itemsize, sizeof(struct info_clkbug)))
2305 	    return;
2306 
2307 	while (items-- > 0) {
2308 		(void) fprintf(fp, "clock address:        %s\n",
2309 			       numtoa(cl->clockadr));
2310 		n = (int)cl->nvalues;
2311 		(void) fprintf(fp, "values: %d", n);
2312 		s = ntohs(cl->svalues);
2313 		if (n > NUMCBUGVALUES)
2314 		    n = NUMCBUGVALUES;
2315 		for (i = 0; i < n; i++) {
2316 			ltemp = ntohl(cl->values[i]);
2317 			ltemp &= 0xffffffff;	/* HMS: This does nothing now */
2318 			if ((i & 0x3) == 0)
2319 			    (void) fprintf(fp, "\n");
2320 			if (s & (1 << i))
2321 			    (void) fprintf(fp, "%12ld", (u_long)ltemp);
2322 			else
2323 			    (void) fprintf(fp, "%12lu", (u_long)ltemp);
2324 		}
2325 		(void) fprintf(fp, "\n");
2326 
2327 		n = (int)cl->ntimes;
2328 		(void) fprintf(fp, "times: %d", n);
2329 		s = ntohl(cl->stimes);
2330 		if (n > NUMCBUGTIMES)
2331 		    n = NUMCBUGTIMES;
2332 		needsp = 0;
2333 		for (i = 0; i < n; i++) {
2334 			if ((i & 0x1) == 0) {
2335 			    (void) fprintf(fp, "\n");
2336 			} else {
2337 				for (;needsp > 0; needsp--)
2338 				    putc(' ', fp);
2339 			}
2340 			NTOHL_FP(&cl->times[i], &ts);
2341 			if (s & (1 << i)) {
2342 				(void) fprintf(fp, "%17s",
2343 					       lfptoa(&ts, 6));
2344 				needsp = 22;
2345 			} else {
2346 				(void) fprintf(fp, "%37s",
2347 					       uglydate(&ts));
2348 				needsp = 2;
2349 			}
2350 		}
2351 		(void) fprintf(fp, "\n");
2352 		if (items > 0) {
2353 			cl++;
2354 			(void) fprintf(fp, "\n");
2355 		}
2356 	}
2357 }
2358 
2359 
2360 /*
2361  * kerninfo - display the kernel pll/pps variables
2362  */
2363 static void
2364 kerninfo(
2365 	struct parse *pcmd,
2366 	FILE *fp
2367 	)
2368 {
2369 	struct info_kernel *ik;
2370 	int items;
2371 	int itemsize;
2372 	int res;
2373 	unsigned status;
2374 	double tscale = 1e-6;
2375 
2376 	res = doquery(IMPL_XNTPD, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
2377 		      &items, &itemsize, (char **)&ik, 0);
2378 	if (res != 0 && items == 0)
2379 	    return;
2380 	if (!check1item(items, fp))
2381 	    return;
2382 	if (!checkitemsize(itemsize, sizeof(struct info_kernel)))
2383 	    return;
2384 
2385 	status = ntohs(ik->status) & 0xffff;
2386 	/*
2387 	 * pll variables. We know more than we should about the NANO bit.
2388 	 */
2389 #ifdef STA_NANO
2390 	if (status & STA_NANO)
2391 		tscale = 1e-9;
2392 #endif
2393 	(void)fprintf(fp, "pll offset:           %g s\n",
2394 	    (long)ntohl(ik->offset) * tscale);
2395 	(void)fprintf(fp, "pll frequency:        %s ppm\n",
2396 	    fptoa((s_fp)ntohl(ik->freq), 3));
2397 	(void)fprintf(fp, "maximum error:        %g s\n",
2398 	    (u_long)ntohl(ik->maxerror) * 1e-6);
2399 	(void)fprintf(fp, "estimated error:      %g s\n",
2400 	    (u_long)ntohl(ik->esterror) * 1e-6);
2401 	(void)fprintf(fp, "status:               %04x ", status);
2402 #ifdef STA_PLL
2403 	if (status & STA_PLL) (void)fprintf(fp, " pll");
2404 #endif
2405 #ifdef STA_PPSFREQ
2406 	if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq");
2407 #endif
2408 #ifdef STA_PPSTIME
2409 	if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime");
2410 #endif
2411 #ifdef STA_FLL
2412 	if (status & STA_FLL) (void)fprintf(fp, " fll");
2413 #endif
2414 #ifdef STA_INS
2415 	if (status & STA_INS) (void)fprintf(fp, " ins");
2416 #endif
2417 #ifdef STA_DEL
2418 	if (status & STA_DEL) (void)fprintf(fp, " del");
2419 #endif
2420 #ifdef STA_UNSYNC
2421 	if (status & STA_UNSYNC) (void)fprintf(fp, " unsync");
2422 #endif
2423 #ifdef STA_FREQHOLD
2424 	if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold");
2425 #endif
2426 #ifdef STA_PPSSIGNAL
2427 	if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal");
2428 #endif
2429 #ifdef STA_PPSJITTER
2430 	if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter");
2431 #endif
2432 #ifdef STA_PPSWANDER
2433 	if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander");
2434 #endif
2435 #ifdef STA_PPSERROR
2436 	if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror");
2437 #endif
2438 #ifdef STA_CLOCKERR
2439 	if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr");
2440 #endif
2441 #ifdef STA_NANO
2442 	if (status & STA_NANO) (void)fprintf(fp, " nano");
2443 #endif
2444 #ifdef STA_MODE
2445 	if (status & STA_MODE) (void)fprintf(fp, " mode=fll");
2446 #endif
2447 #ifdef STA_CLK
2448 	if (status & STA_CLK) (void)fprintf(fp, " src=B");
2449 #endif
2450 	(void)fprintf(fp, "\n");
2451 	(void)fprintf(fp, "pll time constant:    %ld\n",
2452 	    (u_long)ntohl(ik->constant));
2453 	(void)fprintf(fp, "precision:            %g s\n",
2454 	    (u_long)ntohl(ik->precision) * tscale);
2455 	(void)fprintf(fp, "frequency tolerance:  %s ppm\n",
2456 	    fptoa((s_fp)ntohl(ik->tolerance), 0));
2457 
2458 	/*
2459 	 * For backwards compatibility (ugh), we find the pps variables
2460 	 * only if the shift member is nonzero.
2461 	 */
2462 	if (!ik->shift)
2463 	    return;
2464 
2465 	/*
2466 	 * pps variables
2467 	 */
2468 	(void)fprintf(fp, "pps frequency:        %s ppm\n",
2469 	    fptoa((s_fp)ntohl(ik->ppsfreq), 3));
2470 	(void)fprintf(fp, "pps stability:        %s ppm\n",
2471 	    fptoa((s_fp)ntohl(ik->stabil), 3));
2472 	(void)fprintf(fp, "pps jitter:           %g s\n",
2473 	    (u_long)ntohl(ik->jitter) * tscale);
2474 	(void)fprintf(fp, "calibration interval: %d s\n",
2475 		      1 << ntohs(ik->shift));
2476 	(void)fprintf(fp, "calibration cycles:   %ld\n",
2477 		      (u_long)ntohl(ik->calcnt));
2478 	(void)fprintf(fp, "jitter exceeded:      %ld\n",
2479 		      (u_long)ntohl(ik->jitcnt));
2480 	(void)fprintf(fp, "stability exceeded:   %ld\n",
2481 		      (u_long)ntohl(ik->stbcnt));
2482 	(void)fprintf(fp, "calibration errors:   %ld\n",
2483 		      (u_long)ntohl(ik->errcnt));
2484 }
2485