PageRenderTime 142ms CodeModel.GetById 27ms app.highlight 100ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/ntp/ntpdc/ntpdc_ops.c

https://bitbucket.org/freebsd/freebsd-head/
C | 3204 lines | 2646 code | 348 blank | 210 comment | 641 complexity | 33377576bde5c816cdfcd6b3cbb75390 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
   3 */
   4
   5#ifdef HAVE_CONFIG_H
   6# include <config.h>
   7#endif
   8
   9#include <stdio.h>
  10#include <stddef.h>
  11
  12#include "ntpdc.h"
  13#include "ntp_control.h"
  14#include "ntp_refclock.h"
  15#include "ntp_stdlib.h"
  16
  17#include <ctype.h>
  18#ifdef HAVE_SYS_TIMEX_H
  19# include <sys/timex.h>
  20#endif
  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 */
  30static	int	checkitems	P((int, FILE *));
  31static	int	checkitemsize	P((int, int));
  32static	int	check1item	P((int, FILE *));
  33static	void	peerlist	P((struct parse *, FILE *));
  34static	void	peers		P((struct parse *, FILE *));
  35static void	doconfig	P((struct parse *pcmd, FILE *fp, int mode, int refc));
  36static	void	dmpeers		P((struct parse *, FILE *));
  37static	void	dopeers		P((struct parse *, FILE *, int));
  38static	void	printpeer	P((struct info_peer *, FILE *));
  39static	void	showpeer	P((struct parse *, FILE *));
  40static	void	peerstats	P((struct parse *, FILE *));
  41static	void	loopinfo	P((struct parse *, FILE *));
  42static	void	sysinfo		P((struct parse *, FILE *));
  43static	void	sysstats	P((struct parse *, FILE *));
  44static	void	iostats		P((struct parse *, FILE *));
  45static	void	memstats	P((struct parse *, FILE *));
  46static	void	timerstats	P((struct parse *, FILE *));
  47static	void	addpeer		P((struct parse *, FILE *));
  48static	void	addserver	P((struct parse *, FILE *));
  49static	void	addrefclock	P((struct parse *, FILE *));
  50static	void	broadcast	P((struct parse *, FILE *));
  51static	void	doconfig	P((struct parse *, FILE *, int, int));
  52static	void	unconfig	P((struct parse *, FILE *));
  53static	void	set		P((struct parse *, FILE *));
  54static	void	sys_clear	P((struct parse *, FILE *));
  55static	void	doset		P((struct parse *, FILE *, int));
  56static	void	reslist		P((struct parse *, FILE *));
  57static	void	new_restrict	P((struct parse *, FILE *));
  58static	void	unrestrict	P((struct parse *, FILE *));
  59static	void	delrestrict	P((struct parse *, FILE *));
  60static	void	do_restrict	P((struct parse *, FILE *, int));
  61static	void	monlist		P((struct parse *, FILE *));
  62static	void	reset		P((struct parse *, FILE *));
  63static	void	preset		P((struct parse *, FILE *));
  64static	void	readkeys	P((struct parse *, FILE *));
  65static	void	trustkey	P((struct parse *, FILE *));
  66static	void	untrustkey	P((struct parse *, FILE *));
  67static	void	do_trustkey	P((struct parse *, FILE *, int));
  68static	void	authinfo	P((struct parse *, FILE *));
  69static	void	traps		P((struct parse *, FILE *));
  70static	void	addtrap		P((struct parse *, FILE *));
  71static	void	clrtrap		P((struct parse *, FILE *));
  72static	void	do_addclr_trap	P((struct parse *, FILE *, int));
  73static	void	requestkey	P((struct parse *, FILE *));
  74static	void	controlkey	P((struct parse *, FILE *));
  75static	void	do_changekey	P((struct parse *, FILE *, int));
  76static	void	ctlstats	P((struct parse *, FILE *));
  77static	void	clockstat	P((struct parse *, FILE *));
  78static	void	fudge		P((struct parse *, FILE *));
  79static	void	clkbug		P((struct parse *, FILE *));
  80static	void	kerninfo	P((struct parse *, FILE *));
  81static  void    get_if_stats    P((struct parse *, FILE *));
  82static  void    do_if_reload    P((struct parse *, FILE *));
  83
  84/*
  85 * Commands we understand.  Ntpdc imports this.
  86 */
  87struct xcmd opcmds[] = {
  88	{ "listpeers",	peerlist,	{ OPT|IP_VERSION, NO, NO, NO },
  89	  { "-4|-6", "", "", "" },
  90	  "display list of peers the server knows about [IP Version]" },
  91	{ "peers",	peers,	{ OPT|IP_VERSION, NO, NO, NO },
  92	  { "-4|-6", "", "", "" },
  93	  "display peer summary information [IP Version]" },
  94	{ "dmpeers",	dmpeers,	{ OPT|IP_VERSION, NO, NO, NO },
  95	  { "-4|-6", "", "", "" },
  96	  "display peer summary info the way Dave Mills likes it (IP Version)" },
  97	{ "showpeer",	showpeer, 	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD},
  98	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  99	  "display detailed information for one or more peers" },
 100	{ "pstats",	peerstats,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
 101	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
 102	  "display statistical information for one or more peers" },
 103	{ "loopinfo",	loopinfo,	{ OPT|NTP_STR, NO, NO, NO },
 104	  { "oneline|multiline", "", "", "" },
 105	  "display loop filter information" },
 106	{ "sysinfo",	sysinfo,	{ NO, NO, NO, NO },
 107	  { "", "", "", "" },
 108	  "display local server information" },
 109	{ "sysstats",	sysstats,	{ NO, NO, NO, NO },
 110	  { "", "", "", "" },
 111	  "display local server statistics" },
 112	{ "memstats",	memstats,	{ NO, NO, NO, NO },
 113	  { "", "", "", "" },
 114	  "display peer memory usage statistics" },
 115	{ "iostats",	iostats,	{ NO, NO, NO, NO },
 116	  { "", "", "", "" },
 117	  "display I/O subsystem statistics" },
 118	{ "timerstats",	timerstats,	{ NO, NO, NO, NO },
 119	  { "", "", "", "" },
 120	  "display event timer subsystem statistics" },
 121	{ "addpeer",	addpeer,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 122	  { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
 123	  "configure a new peer association" },
 124	{ "addserver",	addserver,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 125	  { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
 126	  "configure a new server" },
 127	{ "addrefclock",addrefclock,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR },
 128	  { "addr", "mode", "minpoll|prefer", "minpoll|prefer" },
 129	  "configure a new server" },
 130	{ "broadcast",	broadcast,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 131	  { "addr", "keyid", "version", "minpoll" },
 132	  "configure broadcasting time service" },
 133	{ "unconfig",	unconfig,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
 134	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
 135	  "unconfigure existing peer assocations" },
 136	{ "enable",	set,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 137	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
 138	  "set a system flag (auth, bclient, monitor, pll, kernel, stats)" },
 139        { "disable",	sys_clear,      { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 140	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
 141	  "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" },
 142	{ "reslist",	reslist,	{OPT|IP_VERSION, NO, NO, NO },
 143	  { "-4|-6", "", "", "" },
 144	  "display the server's restrict list" },
 145	{ "restrict",	new_restrict,	{ NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
 146	  { "address", "mask",
 147	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
 148	    "..." },
 149	  "create restrict entry/add flags to entry" },
 150	{ "unrestrict", unrestrict,	{ NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
 151	  { "address", "mask",
 152	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
 153	    "..." },
 154	  "remove flags from a restrict entry" },
 155	{ "delrestrict", delrestrict,	{ NTP_ADD, NTP_ADD, OPT|NTP_STR, NO },
 156	  { "address", "mask", "ntpport", "" },
 157	  "delete a restrict entry" },
 158	{ "monlist",	monlist,	{ OPT|NTP_INT, NO, NO, NO },
 159	  { "version", "", "", "" },
 160	  "display data the server's monitor routines have collected" },
 161	{ "reset",	reset,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
 162	  { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
 163	  "reset various subsystem statistics counters" },
 164	{ "preset",	preset,		{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
 165	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
 166	  "reset stat counters associated with particular peer(s)" },
 167	{ "readkeys",	readkeys,	{ NO, NO, NO, NO },
 168	  { "", "", "", "" },
 169	  "request a reread of the keys file and re-init of system keys" },
 170	{ "trustedkey",	trustkey,	{ NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
 171	  { "keyid", "keyid", "keyid", "keyid" },
 172	  "add one or more key ID's to the trusted list" },
 173	{ "untrustedkey", untrustkey,	{ NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
 174	  { "keyid", "keyid", "keyid", "keyid" },
 175	  "remove one or more key ID's from the trusted list" },
 176	{ "authinfo",	authinfo,	{ NO, NO, NO, NO },
 177	  { "", "", "", "" },
 178	  "display the state of the authentication code" },
 179	{ "traps",	traps,		{ NO, NO, NO, NO },
 180	  { "", "", "", "" },
 181	  "display the traps set in the server" },
 182	{ "addtrap",	addtrap,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
 183	  { "address", "port", "interface", "" },
 184	  "configure a trap in the server" },
 185	{ "clrtrap",	clrtrap,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
 186	  { "address", "port", "interface", "" },
 187	  "remove a trap (configured or otherwise) from the server" },
 188	{ "requestkey",	requestkey,	{ NTP_UINT, NO, NO, NO },
 189	  { "keyid", "", "", "" },
 190	  "change the keyid the server uses to authenticate requests" },
 191	{ "controlkey",	controlkey,	{ NTP_UINT, NO, NO, NO },
 192	  { "keyid", "", "", "" },
 193	  "change the keyid the server uses to authenticate control messages" },
 194	{ "ctlstats",	ctlstats,	{ NO, NO, NO, NO },
 195	  { "", "", "", "" },
 196	  "display packet count statistics from the control module" },
 197	{ "clockstat",	clockstat,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
 198	  { "address", "address", "address", "address" },
 199	  "display clock status information" },
 200	{ "fudge",	fudge,		{ NTP_ADD, NTP_STR, NTP_STR, NO },
 201	  { "address", "time1|time2|val1|val2|flags", "value", "" },
 202	  "set/change one of a clock's fudge factors" },
 203	{ "clkbug",	clkbug,		{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
 204	  { "address", "address", "address", "address" },
 205	  "display clock debugging information" },
 206	{ "kerninfo",	kerninfo,	{ NO, NO, NO, NO },
 207	  { "", "", "", "" },
 208	  "display the kernel pll/pps variables" },
 209	{ "ifstats",	get_if_stats,	{ NO, NO, NO, NO },
 210	  { "", "", "", "" },
 211	  "list interface statistics" },
 212	{ "ifreload",	do_if_reload,	{ NO, NO, NO, NO },
 213	  { "", "", "", "" },
 214	  "reload interface configuration" },
 215	{ 0,		0,		{ NO, NO, NO, NO },
 216	  { "", "", "", "" }, "" }
 217};
 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 */
 228static int
 229checkitems(
 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 */
 245static int
 246checkitemsize(
 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 */
 264static int
 265check1item(
 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*/
 288static void
 289peerlist(
 290	struct parse *pcmd,
 291	FILE *fp
 292	)
 293{
 294	struct info_peer_list *plist;
 295	struct sockaddr_storage paddr;
 296	int items;
 297	int itemsize;
 298	int res;
 299
 300again:
 301	res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
 302		      &itemsize, (void *)&plist, 0, 
 303		      sizeof(struct info_peer_list));
 304	
 305	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 306		impl_ver = IMPL_XNTPD_OLD;
 307		goto again;
 308	}
 309
 310	if (res != 0)
 311	    return;
 312
 313	if (!checkitems(items, fp))
 314	    return;
 315
 316	if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) &&
 317	    !checkitemsize(itemsize, v4sizeof(struct info_peer_list)))
 318	    return;
 319
 320	while (items > 0) {
 321		memset((char *)&paddr, 0, sizeof(paddr));
 322		if (plist->v6_flag != 0) {
 323			GET_INADDR6(paddr) = plist->addr6;
 324			paddr.ss_family = AF_INET6;
 325		} else {
 326			GET_INADDR(paddr) = plist->addr;
 327			paddr.ss_family = AF_INET;
 328		}
 329#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 330		paddr.ss_len = SOCKLEN(&paddr);
 331#endif
 332		if ((pcmd->nargs == 0) ||
 333		    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
 334		    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
 335			(void) fprintf(fp, "%-9s %s\n",
 336				modetoa(plist->hmode),
 337				nntohost(&paddr));
 338		plist++;
 339		items--;
 340	}
 341}
 342
 343
 344/*
 345 * peers - show peer summary
 346 */
 347static void
 348peers(
 349	struct parse *pcmd,
 350	FILE *fp
 351	)
 352{
 353	dopeers(pcmd, fp, 0);
 354}
 355
 356/*
 357 * dmpeers - show peer summary, Dave Mills style
 358 */
 359static void
 360dmpeers(
 361	struct parse *pcmd,
 362	FILE *fp
 363	)
 364{
 365	dopeers(pcmd, fp, 1);
 366}
 367
 368
 369/*
 370 * peers - show peer summary
 371 */
 372/*ARGSUSED*/
 373static void
 374dopeers(
 375	struct parse *pcmd,
 376	FILE *fp,
 377	int dmstyle
 378	)
 379{
 380	struct info_peer_summary *plist;
 381	struct sockaddr_storage dstadr;
 382	struct sockaddr_storage srcadr;
 383	int items;
 384	int itemsize;
 385	int ntp_poll;
 386	int res;
 387	int c;
 388	l_fp tempts;
 389
 390again:
 391	res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
 392		      &items, &itemsize, (void *)&plist, 0, 
 393		      sizeof(struct info_peer_summary));
 394	
 395	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 396		impl_ver = IMPL_XNTPD_OLD;
 397		goto again;
 398	}
 399
 400	if (res != 0)
 401	    return;
 402
 403	if (!checkitems(items, fp))
 404	    return;
 405
 406	if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) &&
 407	    !checkitemsize(itemsize, v4sizeof(struct info_peer_summary)))
 408		return;
 409
 410	(void) fprintf(fp,
 411		       "     remote           local      st poll reach  delay   offset    disp\n");
 412	(void) fprintf(fp,
 413		       "=======================================================================\n");
 414	while (items > 0) {
 415		if (!dmstyle) {
 416			if (plist->flags & INFO_FLAG_SYSPEER)
 417			    c = '*';
 418			else if (plist->hmode == MODE_ACTIVE)
 419			    c = '+';
 420			else if (plist->hmode == MODE_PASSIVE)
 421			    c = '-';
 422			else if (plist->hmode == MODE_CLIENT)
 423			    c = '=';
 424			else if (plist->hmode == MODE_BROADCAST)
 425			    c = '^';
 426			else if (plist->hmode == MODE_BCLIENT)
 427			    c = '~';
 428			else
 429			    c = ' ';
 430		} else {
 431			if (plist->flags & INFO_FLAG_SYSPEER)
 432			    c = '*';
 433			else if (plist->flags & INFO_FLAG_SHORTLIST)
 434			    c = '+';
 435			else if (plist->flags & INFO_FLAG_SEL_CANDIDATE)
 436			    c = '.';
 437			else
 438			    c = ' ';
 439		}
 440		NTOHL_FP(&(plist->offset), &tempts);
 441		ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
 442				  NTP_MINPOLL);
 443		memset((char *)&dstadr, 0, sizeof(dstadr));
 444		memset((char *)&srcadr, 0, sizeof(srcadr));
 445		if (plist->v6_flag != 0) {
 446			GET_INADDR6(dstadr) = plist->dstadr6;
 447			GET_INADDR6(srcadr) = plist->srcadr6;
 448			srcadr.ss_family = AF_INET6;
 449			dstadr.ss_family = AF_INET6;
 450		} else {
 451			GET_INADDR(dstadr) = plist->dstadr;
 452			GET_INADDR(srcadr) = plist->srcadr;
 453			srcadr.ss_family = AF_INET;
 454			dstadr.ss_family = AF_INET;
 455		}
 456#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 457		srcadr.ss_len = SOCKLEN(&srcadr);
 458		dstadr.ss_len = SOCKLEN(&dstadr);
 459#endif
 460		if ((pcmd->nargs == 0) ||
 461		    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
 462		    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
 463			(void) fprintf(fp,
 464			    "%c%-15.15s %-15.15s %2d %4d  %3o %7.7s %9.9s %7.7s\n",
 465			    c, nntohost(&srcadr), stoa(&dstadr),
 466			    plist->stratum, ntp_poll, plist->reach,
 467			    fptoa(NTOHS_FP(plist->delay), 5),
 468			    lfptoa(&tempts, 6),
 469			    ufptoa(NTOHS_FP(plist->dispersion), 5));
 470		plist++;
 471		items--;
 472	}
 473}
 474
 475/* Convert a refid & stratum (in host order) to a string */
 476static char*
 477refid_string(
 478	u_int32 refid,
 479	int stratum
 480	)
 481{
 482	if (stratum <= 1) {
 483		static char junk[5];
 484		junk[4] = 0;
 485		memmove(junk, (char *)&refid, 4);
 486		return junk;
 487	}
 488
 489	return numtoa(refid);
 490}
 491
 492static void
 493print_pflag(
 494	    FILE *fp,
 495	    u_int32 flags
 496	    )
 497{
 498     const char *str;
 499
 500     if (flags == 0) {
 501		(void) fprintf(fp, " none\n");
 502	} else {
 503		str = "";
 504		if (flags & INFO_FLAG_SYSPEER) {
 505			(void) fprintf(fp, " system_peer");
 506			str = ",";
 507		}
 508		if (flags & INFO_FLAG_CONFIG) {
 509			(void) fprintf(fp, "%s config", str);
 510			str = ",";
 511		}
 512		if (flags & INFO_FLAG_REFCLOCK) {
 513			(void) fprintf(fp, "%s refclock", str);
 514			str = ",";
 515		}
 516		if (flags & INFO_FLAG_AUTHENABLE) {
 517			(void) fprintf(fp, "%s auth", str);
 518			str = ",";
 519		}
 520		if (flags & INFO_FLAG_BCLIENT) {
 521			(void) fprintf(fp, "%s bclient", str);
 522			str = ",";
 523		}
 524		if (flags & INFO_FLAG_PREFER) {
 525			(void) fprintf(fp, "%s prefer", str);
 526			str = ",";
 527		}
 528		if (flags & INFO_FLAG_IBURST) {
 529			(void) fprintf(fp, "%s iburst", str);
 530			str = ",";
 531		}
 532		if (flags & INFO_FLAG_BURST) {
 533			(void) fprintf(fp, "%s burst", str);
 534		}
 535		(void) fprintf(fp, "\n");
 536	}
 537}
 538/*
 539 * printpeer - print detail information for a peer
 540 */
 541static void
 542printpeer(
 543	register struct info_peer *pp,
 544	FILE *fp
 545	)
 546{
 547	register int i;
 548	l_fp tempts;
 549	struct sockaddr_storage srcadr, dstadr;
 550	
 551	memset((char *)&srcadr, 0, sizeof(srcadr));
 552	memset((char *)&dstadr, 0, sizeof(dstadr));
 553	if (pp->v6_flag != 0) {
 554		srcadr.ss_family = AF_INET6;
 555		dstadr.ss_family = AF_INET6;
 556		GET_INADDR6(srcadr) = pp->srcadr6;
 557		GET_INADDR6(dstadr) = pp->dstadr6;
 558	} else {
 559		srcadr.ss_family = AF_INET;
 560		dstadr.ss_family = AF_INET;
 561		GET_INADDR(srcadr) = pp->srcadr;
 562		GET_INADDR(dstadr) = pp->dstadr;
 563	}
 564#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 565	srcadr.ss_len = SOCKLEN(&srcadr);
 566	dstadr.ss_len = SOCKLEN(&dstadr);
 567#endif
 568	(void) fprintf(fp, "remote %s, local %s\n",
 569		       stoa(&srcadr), stoa(&dstadr));
 570	(void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n",
 571		       modetoa(pp->hmode), modetoa(pp->pmode),
 572		       pp->stratum, pp->precision);
 573	
 574	(void) fprintf(fp,
 575		       "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
 576		       pp->leap & 0x2 ? '1' : '0',
 577		       pp->leap & 0x1 ? '1' : '0',
 578		       refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
 579		       ufptoa(NTOHS_FP(pp->rootdispersion), 5));
 580	
 581	(void) fprintf(fp,
 582		       "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
 583		       pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
 584
 585	(void) fprintf(fp,
 586		       "reach %03o, unreach %d, flash 0x%04x, ",
 587		       pp->reach, pp->unreach, pp->flash2);
 588
 589	(void) fprintf(fp, "boffset %s, ttl/mode %d\n",
 590		       fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
 591	
 592	(void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
 593	print_pflag(fp, pp->flags); 
 594
 595	NTOHL_FP(&pp->reftime, &tempts);
 596	(void) fprintf(fp, "reference time:      %s\n",
 597		       prettydate(&tempts));
 598	NTOHL_FP(&pp->org, &tempts);
 599	(void) fprintf(fp, "originate timestamp: %s\n",
 600		       prettydate(&tempts));
 601	NTOHL_FP(&pp->rec, &tempts);
 602	(void) fprintf(fp, "receive timestamp:   %s\n",
 603		       prettydate(&tempts));
 604	NTOHL_FP(&pp->xmt, &tempts);
 605	(void) fprintf(fp, "transmit timestamp:  %s\n",
 606		       prettydate(&tempts));
 607	
 608	(void) fprintf(fp, "filter delay: ");
 609	for (i = 0; i < NTP_SHIFT; i++) {
 610		(void) fprintf(fp, " %-8.8s",
 611			       fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
 612		if (i == (NTP_SHIFT>>1)-1)
 613		    (void) fprintf(fp, "\n              ");
 614	}
 615	(void) fprintf(fp, "\n");
 616
 617	(void) fprintf(fp, "filter offset:");
 618	for (i = 0; i < NTP_SHIFT; i++) {
 619		NTOHL_FP(&pp->filtoffset[i], &tempts);
 620		(void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
 621		if (i == (NTP_SHIFT>>1)-1)
 622		    (void) fprintf(fp, "\n              ");
 623	}
 624	(void) fprintf(fp, "\n");
 625
 626	(void) fprintf(fp, "filter order: ");
 627	for (i = 0; i < NTP_SHIFT; i++) {
 628		(void) fprintf(fp, " %-8d", pp->order[i]);
 629		if (i == (NTP_SHIFT>>1)-1)
 630		    (void) fprintf(fp, "\n              ");
 631	}
 632	(void) fprintf(fp, "\n");
 633	
 634
 635	NTOHL_FP(&pp->offset, &tempts);
 636	(void) fprintf(fp,
 637		       "offset %s, delay %s, error bound %s, filter error %s\n",
 638		       lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
 639		       ufptoa(NTOHS_FP(pp->dispersion), 5),
 640		       ufptoa(NTOHS_FP(pp->selectdisp), 5));
 641}
 642
 643
 644/*
 645 * showpeer - show detailed information for a peer
 646 */
 647static void
 648showpeer(
 649	struct parse *pcmd,
 650	FILE *fp
 651	)
 652{
 653	struct info_peer *pp;
 654	/* 4 is the maximum number of peers which will fit in a packet */
 655	struct info_peer_list *pl, plist[min(MAXARGS, 4)];
 656	int qitems;
 657	int items;
 658	int itemsize;
 659	int res;
 660	int sendsize;
 661
 662again:
 663	if (impl_ver == IMPL_XNTPD)
 664		sendsize = sizeof(struct info_peer_list);
 665	else
 666		sendsize = v4sizeof(struct info_peer_list);
 667
 668	for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) {
 669		if (pcmd->argval[qitems].netnum.ss_family == AF_INET) {
 670			pl->addr = GET_INADDR(pcmd->argval[qitems].netnum);
 671			if (impl_ver == IMPL_XNTPD)
 672				pl->v6_flag = 0;
 673		} else {
 674			if (impl_ver == IMPL_XNTPD_OLD) {
 675				fprintf(stderr,
 676				    "***Server doesn't understand IPv6 addresses\n");
 677				return;
 678			}
 679			pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum);
 680			pl->v6_flag = 1;
 681		}
 682		pl->port = (u_short)s_port;
 683		pl->hmode = pl->flags = 0;
 684		pl = (struct info_peer_list *)((char *)pl + sendsize);
 685	}
 686
 687	res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems,
 688		      sendsize, (char *)plist, &items,
 689		      &itemsize, (void *)&pp, 0, sizeof(struct info_peer));
 690	
 691	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 692		impl_ver = IMPL_XNTPD_OLD;
 693		goto again;
 694	}
 695
 696	if (res != 0)
 697	    return;
 698
 699	if (!checkitems(items, fp))
 700	    return;
 701
 702	if (!checkitemsize(itemsize, sizeof(struct info_peer)) &&
 703	    !checkitemsize(itemsize, v4sizeof(struct info_peer)))
 704	    return;
 705
 706	while (items-- > 0) {
 707		printpeer(pp, fp);
 708		if (items > 0)
 709		    (void) fprintf(fp, "\n");
 710		pp++;
 711	}
 712}
 713
 714
 715/*
 716 * peerstats - return statistics for a peer
 717 */
 718static void
 719peerstats(
 720	struct parse *pcmd,
 721	FILE *fp
 722	)
 723{
 724	struct info_peer_stats *pp;
 725	/* 4 is the maximum number of peers which will fit in a packet */
 726	struct info_peer_list *pl, plist[min(MAXARGS, 4)];
 727	struct sockaddr_storage src, dst;
 728	int qitems;
 729	int items;
 730	int itemsize;
 731	int res;
 732	int sendsize;
 733
 734again:
 735	if (impl_ver == IMPL_XNTPD)
 736		sendsize = sizeof(struct info_peer_list);
 737	else
 738		sendsize = v4sizeof(struct info_peer_list);
 739
 740	memset((char *)plist, 0, sizeof(struct info_peer_list) * min(MAXARGS, 4));
 741	for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) {
 742		if (pcmd->argval[qitems].netnum.ss_family == AF_INET) {
 743			pl->addr = GET_INADDR(pcmd->argval[qitems].netnum);
 744			if (impl_ver == IMPL_XNTPD)
 745				pl->v6_flag = 0;
 746		} else {
 747			if (impl_ver == IMPL_XNTPD_OLD) {
 748				fprintf(stderr,
 749				    "***Server doesn't understand IPv6 addresses\n");
 750				return;
 751			}
 752			pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum);
 753			pl->v6_flag = 1;
 754		}
 755		pl->port = (u_short)s_port;
 756		pl->hmode = plist[qitems].flags = 0;
 757		pl = (struct info_peer_list *)((char *)pl + sendsize);
 758	}
 759
 760	res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems,
 761		      sendsize, (char *)plist, &items,
 762		      &itemsize, (void *)&pp, 0, 
 763		      sizeof(struct info_peer_stats));
 764	
 765	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 766		impl_ver = IMPL_XNTPD_OLD;
 767		goto again;
 768	}
 769
 770	if (res != 0)
 771	    return;
 772
 773	if (!checkitems(items, fp))
 774	    return;
 775
 776	if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) &&
 777	    !checkitemsize(itemsize, v4sizeof(struct info_peer_stats)))
 778	    return;
 779
 780	while (items-- > 0) {
 781		memset((char *)&src, 0, sizeof(src));
 782		memset((char *)&dst, 0, sizeof(dst));
 783		if (pp->v6_flag != 0) {
 784			GET_INADDR6(src) = pp->srcadr6;
 785			GET_INADDR6(dst) = pp->dstadr6;
 786			src.ss_family = AF_INET6;
 787			dst.ss_family = AF_INET6;
 788		} else {
 789			GET_INADDR(src) = pp->srcadr;
 790			GET_INADDR(dst) = pp->dstadr;
 791			src.ss_family = AF_INET;
 792			dst.ss_family = AF_INET;
 793		}
 794#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 795		src.ss_len = SOCKLEN(&src);
 796		dst.ss_len = SOCKLEN(&dst);
 797#endif
 798		(void) fprintf(fp, "remote host:          %s\n",
 799			       nntohost(&src));
 800		(void) fprintf(fp, "local interface:      %s\n",
 801			       stoa(&dst));
 802		(void) fprintf(fp, "time last received:   %lds\n",
 803			       (long)ntohl(pp->timereceived));
 804		(void) fprintf(fp, "time until next send: %lds\n",
 805			       (long)ntohl(pp->timetosend));
 806		(void) fprintf(fp, "reachability change:  %lds\n",
 807			       (long)ntohl(pp->timereachable));
 808		(void) fprintf(fp, "packets sent:         %ld\n",
 809			       (long)ntohl(pp->sent));
 810		(void) fprintf(fp, "packets received:     %ld\n",
 811			       (long)ntohl(pp->processed));
 812		(void) fprintf(fp, "bad authentication:   %ld\n",
 813			       (long)ntohl(pp->badauth));
 814		(void) fprintf(fp, "bogus origin:         %ld\n",
 815			       (long)ntohl(pp->bogusorg));
 816		(void) fprintf(fp, "duplicate:            %ld\n",
 817			       (long)ntohl(pp->oldpkt));
 818		(void) fprintf(fp, "bad dispersion:       %ld\n",
 819			       (long)ntohl(pp->seldisp));
 820		(void) fprintf(fp, "bad reference time:   %ld\n",
 821			       (long)ntohl(pp->selbroken));
 822		(void) fprintf(fp, "candidate order:      %d\n",
 823			       (int)pp->candidate);
 824		if (items > 0)
 825		    (void) fprintf(fp, "\n");
 826		(void) fprintf(fp, "flags:	");
 827		print_pflag(fp, ntohs(pp->flags));
 828	        pp++;
 829	}
 830}
 831
 832
 833/*
 834 * loopinfo - show loop filter information
 835 */
 836static void
 837loopinfo(
 838	struct parse *pcmd,
 839	FILE *fp
 840	)
 841{
 842	struct info_loop *il;
 843	int items;
 844	int itemsize;
 845	int oneline = 0;
 846	int res;
 847	l_fp tempts;
 848
 849	if (pcmd->nargs > 0) {
 850		if (STREQ(pcmd->argval[0].string, "oneline"))
 851		    oneline = 1;
 852		else if (STREQ(pcmd->argval[0].string, "multiline"))
 853		    oneline = 0;
 854		else {
 855			(void) fprintf(stderr, "How many lines?\n");
 856			return;
 857		}
 858	}
 859
 860again:
 861	res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
 862		      &items, &itemsize, (void *)&il, 0, 
 863		      sizeof(struct info_loop));
 864	
 865	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 866		impl_ver = IMPL_XNTPD_OLD;
 867		goto again;
 868	}
 869
 870	if (res != 0)
 871	    return;
 872
 873	if (!check1item(items, fp))
 874	    return;
 875
 876	if (!checkitemsize(itemsize, sizeof(struct info_loop)))
 877	    return;
 878
 879	if (oneline) {
 880		l_fp temp2ts;
 881
 882		NTOHL_FP(&il->last_offset, &tempts);
 883		NTOHL_FP(&il->drift_comp, &temp2ts);
 884
 885		(void) fprintf(fp,
 886			       "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
 887			       lfptoa(&tempts, 6),
 888			       lfptoa(&temp2ts, 3),
 889			       (long)(int32_t)ntohl((u_long)il->compliance),
 890			       (u_long)ntohl((u_long)il->watchdog_timer));
 891	} else {
 892		NTOHL_FP(&il->last_offset, &tempts);
 893		(void) fprintf(fp, "offset:               %s s\n",
 894			       lfptoa(&tempts, 6));
 895		NTOHL_FP(&il->drift_comp, &tempts);
 896		(void) fprintf(fp, "frequency:            %s ppm\n",
 897			       lfptoa(&tempts, 3));
 898		(void) fprintf(fp, "poll adjust:          %ld\n",
 899			       (long)(int32_t)ntohl(il->compliance));
 900		(void) fprintf(fp, "watchdog timer:       %ld s\n",
 901			       (u_long)ntohl(il->watchdog_timer));
 902	}
 903}
 904
 905
 906/*
 907 * sysinfo - show current system state
 908 */
 909/*ARGSUSED*/
 910static void
 911sysinfo(
 912	struct parse *pcmd,
 913	FILE *fp
 914	)
 915{
 916	struct info_sys *is;
 917	struct sockaddr_storage peeraddr;
 918	int items;
 919	int itemsize;
 920	int res;
 921	l_fp tempts;
 922
 923again:
 924	res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
 925		      &items, &itemsize, (void *)&is, 0,
 926		      sizeof(struct info_sys));
 927	
 928	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 929		impl_ver = IMPL_XNTPD_OLD;
 930		goto again;
 931	}
 932
 933	if (res != 0)
 934	    return;
 935
 936	if (!check1item(items, fp))
 937	    return;
 938
 939	if (!checkitemsize(itemsize, sizeof(struct info_sys)) &&
 940	    !checkitemsize(itemsize, v4sizeof(struct info_sys)))
 941	    return;
 942
 943	memset((char *)&peeraddr, 0, sizeof(peeraddr));
 944	if (is->v6_flag != 0) {
 945		GET_INADDR6(peeraddr) = is->peer6;
 946		peeraddr.ss_family = AF_INET6;
 947	} else {
 948		GET_INADDR(peeraddr) = is->peer;
 949		peeraddr.ss_family = AF_INET;
 950	}
 951#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 952	peeraddr.ss_len = SOCKLEN(&peeraddr);
 953#endif
 954	(void) fprintf(fp, "system peer:          %s\n", nntohost(&peeraddr));
 955	(void) fprintf(fp, "system peer mode:     %s\n", modetoa(is->peer_mode));
 956	(void) fprintf(fp, "leap indicator:       %c%c\n",
 957		       is->leap & 0x2 ? '1' : '0',
 958		       is->leap & 0x1 ? '1' : '0');
 959	(void) fprintf(fp, "stratum:              %d\n", (int)is->stratum);
 960	(void) fprintf(fp, "precision:            %d\n", (int)is->precision);
 961	(void) fprintf(fp, "root distance:        %s s\n",
 962		       fptoa(NTOHS_FP(is->rootdelay), 5));
 963	(void) fprintf(fp, "root dispersion:      %s s\n",
 964		       ufptoa(NTOHS_FP(is->rootdispersion), 5));
 965	(void) fprintf(fp, "reference ID:         [%s]\n",
 966		       refid_string(is->refid, is->stratum));
 967	NTOHL_FP(&is->reftime, &tempts);
 968	(void) fprintf(fp, "reference time:       %s\n", prettydate(&tempts));
 969
 970	(void) fprintf(fp, "system flags:         ");
 971	if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
 972	    INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL |
 973	    INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
 974		(void) fprintf(fp, "none\n");
 975	} else {
 976		if (is->flags & INFO_FLAG_BCLIENT)
 977		    (void) fprintf(fp, "bclient ");
 978		if (is->flags & INFO_FLAG_AUTHENTICATE)
 979		    (void) fprintf(fp, "auth ");
 980		if (is->flags & INFO_FLAG_MONITOR)
 981		    (void) fprintf(fp, "monitor ");
 982		if (is->flags & INFO_FLAG_NTP)
 983		    (void) fprintf(fp, "ntp ");
 984		if (is->flags & INFO_FLAG_KERNEL)
 985		    (void) fprintf(fp, "kernel ");
 986		if (is->flags & INFO_FLAG_FILEGEN)
 987		    (void) fprintf(fp, "stats ");
 988		if (is->flags & INFO_FLAG_CAL)
 989		    (void) fprintf(fp, "calibrate ");
 990		if (is->flags & INFO_FLAG_PPS_SYNC)
 991		    (void) fprintf(fp, "pps ");
 992		(void) fprintf(fp, "\n");
 993	}
 994	(void) fprintf(fp, "jitter:               %s s\n",
 995		       fptoa(ntohl(is->frequency), 6));
 996	(void) fprintf(fp, "stability:            %s ppm\n",
 997		       ufptoa(ntohl(is->stability), 3));
 998	(void) fprintf(fp, "broadcastdelay:       %s s\n",
 999		       fptoa(NTOHS_FP(is->bdelay), 6));
1000	NTOHL_FP(&is->authdelay, &tempts);
1001	(void) fprintf(fp, "authdelay:            %s s\n", lfptoa(&tempts, 6));
1002}
1003
1004
1005/*
1006 * sysstats - print system statistics
1007 */
1008/*ARGSUSED*/
1009static void
1010sysstats(
1011	struct parse *pcmd,
1012	FILE *fp
1013	)
1014{
1015	struct info_sys_stats *ss;
1016	int items;
1017	int itemsize;
1018	int res;
1019
1020again:
1021	res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
1022		      &items, &itemsize, (void *)&ss, 0, 
1023		      sizeof(struct info_sys_stats));
1024	
1025	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1026		impl_ver = IMPL_XNTPD_OLD;
1027		goto again;
1028	}
1029
1030	if (res != 0)
1031	    return;
1032
1033	if (!check1item(items, fp))
1034	    return;
1035
1036	if (itemsize != sizeof(struct info_sys_stats) &&
1037	    itemsize != sizeof(struct old_info_sys_stats)) {
1038		/* issue warning according to new structure size */
1039		checkitemsize(itemsize, sizeof(struct info_sys_stats));
1040		return;
1041	}
1042	fprintf(fp, "time since restart:     %ld\n",
1043	       (u_long)ntohl(ss->timeup));
1044	fprintf(fp, "time since reset:       %ld\n",
1045		(u_long)ntohl(ss->timereset));
1046        fprintf(fp, "packets received:       %ld\n",
1047		(u_long)ntohl(ss->received));
1048	fprintf(fp, "packets processed:      %ld\n",
1049		(u_long)ntohl(ss->processed));
1050	fprintf(fp, "current version:        %ld\n",
1051	       (u_long)ntohl(ss->newversionpkt));
1052	fprintf(fp, "previous version:       %ld\n",
1053	       (u_long)ntohl(ss->oldversionpkt));
1054	fprintf(fp, "bad version:            %ld\n",
1055	       (u_long)ntohl(ss->unknownversion));
1056	fprintf(fp, "access denied:          %ld\n",
1057		(u_long)ntohl(ss->denied));
1058	fprintf(fp, "bad length or format:   %ld\n",
1059	       (u_long)ntohl(ss->badlength));
1060	fprintf(fp, "bad authentication:     %ld\n",
1061	       (u_long)ntohl(ss->badauth));
1062	if (itemsize != sizeof(struct info_sys_stats))
1063	    return;
1064	
1065	fprintf(fp, "rate exceeded:          %ld\n",
1066	       (u_long)ntohl(ss->limitrejected));
1067}
1068
1069
1070
1071/*
1072 * iostats - print I/O statistics
1073 */
1074/*ARGSUSED*/
1075static void
1076iostats(
1077	struct parse *pcmd,
1078	FILE *fp
1079	)
1080{
1081	struct info_io_stats *io;
1082	int items;
1083	int itemsize;
1084	int res;
1085
1086again:
1087	res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, (char *)NULL,
1088		      &items, &itemsize, (void *)&io, 0, 
1089		      sizeof(struct info_io_stats));
1090	
1091	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1092		impl_ver = IMPL_XNTPD_OLD;
1093		goto again;
1094	}
1095
1096	if (res != 0)
1097	    return;
1098
1099	if (!check1item(items, fp))
1100	    return;
1101
1102	if (!checkitemsize(itemsize, sizeof(struct info_io_stats)))
1103	    return;
1104
1105	(void) fprintf(fp, "time since reset:     %ld\n",
1106		       (u_long)ntohl(io->timereset));
1107	(void) fprintf(fp, "receive buffers:      %d\n",
1108		       ntohs(io->totalrecvbufs));
1109	(void) fprintf(fp, "free receive buffers: %d\n",
1110		       ntohs(io->freerecvbufs));
1111	(void) fprintf(fp, "used receive buffers: %d\n",
1112		       ntohs(io->fullrecvbufs));
1113	(void) fprintf(fp, "low water refills:    %d\n",
1114		       ntohs(io->lowwater));
1115	(void) fprintf(fp, "dropped packets:      %ld\n",
1116		       (u_long)ntohl(io->dropped));
1117	(void) fprintf(fp, "ignored packets:      %ld\n",
1118		       (u_long)ntohl(io->ignored));
1119	(void) fprintf(fp, "received packets:     %ld\n",
1120		       (u_long)ntohl(io->received));
1121	(void) fprintf(fp, "packets sent:         %ld\n",
1122		       (u_long)ntohl(io->sent));
1123	(void) fprintf(fp, "packets not sent:     %ld\n",
1124		       (u_long)ntohl(io->notsent));
1125	(void) fprintf(fp, "interrupts handled:   %ld\n",
1126		       (u_long)ntohl(io->interrupts));
1127	(void) fprintf(fp, "received by int:      %ld\n",
1128		       (u_long)ntohl(io->int_received));
1129}
1130
1131
1132/*
1133 * memstats - print peer memory statistics
1134 */
1135/*ARGSUSED*/
1136static void
1137memstats(
1138	struct parse *pcmd,
1139	FILE *fp
1140	)
1141{
1142	struct info_mem_stats *mem;
1143	int i;
1144	int items;
1145	int itemsize;
1146	int res;
1147
1148again:
1149	res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, (char *)NULL,
1150		      &items, &itemsize, (void *)&mem, 0, 
1151		      sizeof(struct info_mem_stats));
1152	
1153	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1154		impl_ver = IMPL_XNTPD_OLD;
1155		goto again;
1156	}
1157
1158	if (res != 0)
1159	    return;
1160
1161	if (!check1item(items, fp))
1162	    return;
1163
1164	if (!checkitemsize(itemsize, sizeof(struct info_mem_stats)))
1165	    return;
1166
1167	(void) fprintf(fp, "time since reset:     %ld\n",
1168		       (u_long)ntohl(mem->timereset));
1169	(void) fprintf(fp, "total peer memory:    %d\n",
1170		       ntohs(mem->totalpeermem));
1171	(void) fprintf(fp, "free peer memory:     %d\n",
1172		       ntohs(mem->freepeermem));
1173	(void) fprintf(fp, "calls to findpeer:    %ld\n",
1174		       (u_long)ntohl(mem->findpeer_calls));
1175	(void) fprintf(fp, "new peer allocations: %ld\n",
1176		       (u_long)ntohl(mem->allocations));
1177	(void) fprintf(fp, "peer demobilizations: %ld\n",
1178		       (u_long)ntohl(mem->demobilizations));
1179
1180	(void) fprintf(fp, "hash table counts:   ");
1181	for (i = 0; i < NTP_HASH_SIZE; i++) {
1182		(void) fprintf(fp, "%4d", (int)mem->hashcount[i]);
1183		if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1)) {
1184			(void) fprintf(fp, "\n                     ");
1185		}
1186	}
1187	(void) fprintf(fp, "\n");
1188}
1189
1190
1191
1192/*
1193 * timerstats - print timer statistics
1194 */
1195/*ARGSUSED*/
1196static void
1197timerstats(
1198	struct parse *pcmd,
1199	FILE *fp
1200	)
1201{
1202	struct info_timer_stats *tim;
1203	int items;
1204	int itemsize;
1205	int res;
1206
1207again:
1208	res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL,
1209		      &items, &itemsize, (void *)&tim, 0, 
1210		      sizeof(struct info_timer_stats));
1211	
1212	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1213		impl_ver = IMPL_XNTPD_OLD;
1214		goto again;
1215	}
1216
1217	if (res != 0)
1218	    return;
1219
1220	if (!check1item(items, fp))
1221	    return;
1222
1223	if (!checkitemsize(itemsize, sizeof(struct info_timer_stats)))
1224	    return;
1225
1226	(void) fprintf(fp, "time since reset:  %ld\n",
1227		       (u_long)ntohl(tim->timereset));
1228	(void) fprintf(fp, "alarms handled:    %ld\n",
1229		       (u_long)ntohl(tim->alarms));
1230	(void) fprintf(fp, "alarm overruns:    %ld\n",
1231		       (u_long)ntohl(tim->overflows));
1232	(void) fprintf(fp, "calls to transmit: %ld\n",
1233		       (u_long)ntohl(tim->xmtcalls));
1234}
1235
1236
1237/*
1238 * addpeer - configure an active mode association
1239 */
1240static void
1241addpeer(
1242	struct parse *pcmd,
1243	FILE *fp
1244	)
1245{
1246	doconfig(pcmd, fp, MODE_ACTIVE, 0);
1247}
1248
1249
1250/*
1251 * addserver - configure a client mode association
1252 */
1253static void
1254addserver(
1255	struct parse *pcmd,
1256	FILE *fp
1257	)
1258{
1259	doconfig(pcmd, fp, MODE_CLIENT, 0);
1260}
1261
1262/*
1263 * addrefclock - configure a reference clock association
1264 */
1265static void
1266addrefclock(
1267	struct parse *pcmd,
1268	FILE *fp
1269	)
1270{
1271	doconfig(pcmd, fp, MODE_CLIENT, 1);
1272}
1273
1274/*
1275 * broadcast - configure a broadcast mode association
1276 */
1277static void
1278broadcast(
1279	struct parse *pcmd,
1280	FILE *fp
1281	)
1282{
1283	doconfig(pcmd, fp, MODE_BROADCAST, 0);
1284}
1285
1286
1287/*
1288 * config - configure a new peer association
1289 */
1290static void
1291doconfig(
1292	struct parse *pcmd,
1293	FILE *fp,
1294	int mode,
1295        int refc
1296	)
1297{
1298	struct conf_peer cpeer;
1299	int items;
1300	int itemsize;
1301	char *dummy;
1302	u_long keyid;
1303	u_int version;
1304	u_char minpoll;
1305	u_char maxpoll;
1306	u_int flags;
1307	u_char cmode;
1308	int res;
1309	int sendsize;
1310	int numtyp;
1311
1312again:
1313	keyid = 0;
1314	version = 3;
1315	flags = 0;
1316	res = 0;
1317	cmode = 0;
1318	minpoll = NTP_MINDPOLL;
1319	maxpoll = NTP_MAXDPOLL;
1320	numtyp = 1;
1321	if (refc)
1322	     numtyp = 5;
1323
1324	if (impl_ver == IMPL_XNTPD)
1325		sendsize = sizeof(struct conf_peer);
1326	else
1327		sendsize = v4sizeof(struct conf_peer);
1328
1329	items = 1;
1330	while (pcmd->nargs > items) {
1331		if (STREQ(pcmd->argval[items].string, "prefer"))
1332		    flags |= CONF_FLAG_PREFER;
1333		else if (STREQ(pcmd->argval[items].string, "burst"))
1334		    flags |= CONF_FLAG_BURST;
1335		else if (STREQ(pcmd->argval[items].string, "dynamic"))
1336		    (void) fprintf(fp, "Warning: the \"dynamic\" keyword has been obsoleted and will be removed in the next release\n"); 
1337		else if (STREQ(pcmd->argval[items].string, "iburst"))
1338		    flags |= CONF_FLAG_IBURST;
1339		else if (!refc && STREQ(pcmd->argval[items].string, "keyid"))
1340		    numtyp = 1;
1341		else if (!refc && STREQ(pcmd->argval[items].string, "version"))
1342		    numtyp = 2;
1343		else if (STREQ(pcmd->argval[items].string, "minpoll"))
1344		    numtyp = 3;
1345		else if (STREQ(pcmd->argval[items].string, "maxpoll"))
1346		    numtyp = 4;
1347		else {
1348		        long val;
1349			if (!atoint(pcmd->argval[items].string, &val))
1350			     numtyp = 0;				  
1351			switch (numtyp) {
1352			case 1:
1353			     keyid = val;
1354			     numtyp = 2;				  
1355			     break;
1356			     
1357			case 2:
1358			     version = (u_int) val;
1359			     numtyp = 0;				  
1360			     break;
1361
1362			case 3:
1363			     minpoll = (u_char)val;
1364			     numtyp = 0;				  
1365			     break;
1366
1367			case 4:
1368			     maxpoll = (u_char)val;
1369			     numtyp = 0;				  
1370			     break;
1371
1372			case 5:
1373			     cmode = (u_char)val;
1374			     numtyp = 0;				  
1375			     break;
1376
1377			default:
1378			     (void) fprintf(fp, "*** '%s' not understood\n",
1379					    pcmd->argval[items].string);
1380			     res++;
1381			     numtyp = 0;				  
1382			}
1383			if (val < 0) {
1384			     (void) fprintf(stderr,
1385				     "***Value '%s' should be unsigned\n",
1386				      pcmd->argval[items].string);
1387			     res++;
1388			}
1389		   }
1390	     items++;
1391	}
1392	if (keyid > 0)
1393	     flags |= CONF_FLAG_AUTHENABLE;
1394	if (version > NTP_VERSION ||
1395	    version < NTP_OLDVERSION) {
1396	     (void)fprintf(fp, "***invalid version number: %u\n",
1397			   version);
1398	     res++;
1399	}
1400	if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 
1401	    maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 
1402	    minpoll > maxpoll) {
1403	     (void) fprintf(fp, "***min/max-poll must be within %d..%d\n",
1404			    NTP_MINPOLL, NTP_MAXPOLL);
1405	     res++;
1406	}					
1407
1408	if (res)
1409	    return;
1410
1411	memset((void *)&cpeer, 0, sizeof(cpeer));
1412
1413	if (pcmd->argval[0].netnum.ss_family == AF_INET) {
1414		cpeer.peeraddr = GET_INADDR(pcmd->argval[0].netnum);
1415		if (impl_ver == IMPL_XNTPD)
1416			cpeer.v6_flag = 0;
1417	} else {
1418		if (impl_ver == IMPL_XNTPD_OLD) {
1419			fprintf(stderr,
1420			    "***Server doesn't understand IPv6 addresses\n");
1421			return;
1422		}
1423		cpeer.peeraddr6 = GET_INADDR6(pcmd->argval[0].netnum);
1424		cpeer.v6_flag = 1;
1425	}
1426	cpeer.hmode = (u_char) mode;
1427	cpeer.keyid = keyid;
1428	cpeer.version = (u_char) version;
1429	cpeer.minpoll = minpoll;
1430	cpeer.maxpoll = maxpoll;
1431	cpeer.flags = (u_char)flags;
1432	cpeer.ttl = cmode;
1433
1434	res = doquery(impl_ver, REQ_CONFIG, 1, 1,
1435		      sendsize, (char *)&cpeer, &items,
1436		      &itemsize, &dummy, 0, sizeof(struct conf_peer));
1437	
1438	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1439		impl_ver = IMPL_XNTPD_OLD;
1440		goto again;
1441	}
1442
1443	if (res == INFO_ERR_FMT) {
1444		(void) fprintf(fp,
1445		    "***Retrying command with old conf_peer size\n");
1446		res = doquery(impl_ver, REQ_CONFIG, 1, 1,
1447			      sizeof(struct old_conf_peer), (char *)&cpeer,
1448			      &items, &itemsize, &dummy, 0,
1449			      sizeof(struct conf_peer));
1450	}
1451	if (res == 0)
1452	    (void) fprintf(fp, "done!\n");
1453	return;
1454}
1455
1456
1457/*
1458 * unconfig - unconfigure some associations
1459 */
1460static void
1461unconfig(
1462	struct parse *pcmd,
1463	FILE *fp
1464	)
1465{
1466	/* 8 is the maximum number of peers which will fit in a packet */
1467	struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
1468	int qitems;
1469	int items;
1470	int itemsize;
1471	char *dummy;
1472	int res;
1473	int sendsize;
1474
1475again:
1476	if (impl_ver == IMPL_XNTPD)
1477		sendsize = sizeof(struct conf_unpeer);
1478	else
1479		sendsize = v4sizeof(struct conf_unpeer);
1480
1481	for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 8); qitems++) {
1482		if (pcmd->argval[0].netnum.ss_family == AF_INET) {
1483			pl->peeraddr = GET_INADDR(pcmd->argval[qitems].netnum);
1484			if (impl_ver == IMPL_XNTPD)
1485				pl->v6_flag = 0;
1486		} else {
1487			if (impl_ver == IMPL_XNTPD_OLD) {
1488				fprintf(stderr,
1489				    "***Server doesn't understand IPv6 addresses\n");
1490				return;
1491			}
1492			pl->peeraddr6 =
1493			    GET_INADDR6(pcmd->argval[qitems].netnum);
1494			pl->v6_flag = 1;
1495		}
1496		pl = (struct conf_unpeer *)((char *)pl + sendsize);
1497	}
1498
1499	res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems,
1500		      sendsize, (char *)plist, &items,
1501		      &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
1502	
1503	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1504		impl_ver = IMPL_XNTPD_OLD;
1505		goto again;
1506	}
1507
1508	if (res == 0)
1509	    (void) fprintf(fp, "done!\n");
1510}
1511
1512
1513/*
1514 * set - set some system flags
1515 */
1516static void
1517set(
1518	struct parse *pcmd,
1519	FILE *fp
1520	)
1521{
1522	doset(pcmd, fp, REQ_SET_SYS_FLAG);
1523}
1524
1525
1526/*
1527 * clear - clear some system flags
1528 */
1529static void
1530sys_clear(
1531	struct parse *pcmd,
1532	FILE *fp
1533	)
1534{
1535	doset(pcmd, fp, REQ_CLR_SYS_FLAG);
1536}
1537
1538
1539/*
1540 * doset - set/clear system flags
1541 */
1542static void
1543doset(
1544	struct parse *pcmd,
1545	FILE *fp,
1546	int req
1547	)
1548{
1549	/* 8 is the maximum number of peers which will fit in a packet */
1550	struct conf_sys_flags sys;
1551	int items;
1552	int itemsize;
1553	char *dummy;
1554	int res;
1555
1556	sys.flags = 0;
1557	res = 0;
1558	for (items = 0; items < pcmd->nargs; items++) {
1559		if (STREQ(pcmd->argval[items].string, "auth"))
1560			sys.flags |= SYS_FLAG_AUTH;
1561		else if (STREQ(pcmd->argval[items].string, "bclient"))
1562			sys.flags |= SYS_FLAG_BCLIENT;
1563		else if (STREQ(pcmd->argval[items].string, "calibrate"))
1564			sys.flags |= SYS_FLAG_CAL;
1565		else if (STREQ(pcmd->argval[items].string, "kernel"))
1566			sys.flags |= SYS_FLAG_KERNEL;
1567		else if (STREQ(pcmd->argval[items].string, "monitor"))
1568			sys.flags |= SYS_FLAG_MONITOR;
1569		else if (STREQ(pcmd->argval[items].string, "ntp"))
1570			sys.flags |= SYS_FLAG_NTP;
1571		else if (STREQ(pcmd->argval[items].string, "pps"))
1572			sys.flags |= SYS_FLAG_PPS;
1573		else if (STREQ(pcmd->argval[items].string, "stats"))
1574			sys.flags |= SYS_FLAG_FILEGEN;
1575		else {
1576			(void) fprintf(fp, "Unknown flag %s\n",
1577			    pcmd->argval[items].string);
1578			res = 1;
1579		}
1580	}
1581
1582	sys.flags = htonl(sys.flags);
1583	if (res || sys.flags == 0)
1584	    return;
1585
1586again:
1587	res = doquery(impl_ver, req, 1, 1,
1588		      sizeof(struct conf_sys_flags), (char *)&sys, &items,
1589		      &itemsize, &dummy, 0, sizeof(struct conf_sys_flags));
1590	
1591	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1592		impl_ver = IMPL_XNTPD_OLD;
1593		goto again;
1594	}
1595
1596	if (res == 0)
1597	    (void) fprintf(fp, "done!\n");
1598}
1599
1600
1601/*
1602 * data for printing/interrpreting the restrict flags
1603 */
1604struct resflags {
1605  const char *str;
1606	int bit;
1607};
1608
1609/* XXX: HMS: we apparently don't report set bits we do not recognize. */
1610
1611static struct resflags resflagsV2[] = {
1612	{ "ignore",	0x001 },
1613	{ "noserve",	0x002 },
1614	{ "notrust",	0x004 },
1615	{ "noquery",	0x008 },
1616	{ "nomodify",	0x010 },
1617	{ "nopeer",	0x020 },
1618	{ "notrap",	0x040 },
1619	{ "lptrap",	0x080 },
1620	{ "limited",	0x100 },
1621	{ "",		0 }
1622};
1623
1624static struct resflags resflagsV3[] = {
1625	{ "ignore",	RES_IGNORE },
1626	{ "noserve",	RES_DONTSERVE },
1627	{ "notrust",	RES_DONTTRUST },
1628	{ "noquery",	RES_NOQUERY },
1629	{ "nomodify",	RES_NOMODIFY },
1630	{ "nopeer",	RES_NOPEER },
1631	{ "notrap",	RES_NOTRAP },
1632	{ "lptrap",	RES_LPTRAP },
1633	{ "limited",	RES_LIMITED },
1634	{ "version",	RES_VERSION },
1635	{ "kod",	RES_DEMOBILIZE },
1636	{ "timeout",	RES_TIMEOUT },
1637
1638	{ "",		0 }
1639};
1640
1641static struct resflags resmflags[] = {
1642	{ "ntpport",	RESM_NTPONLY },
1643	{ "interface",	RESM_INTERFACE },
1644	{ "",		0 }
1645};
1646
1647
1648/*
1649 * reslist - obtain and print the server's restrict list
1650 */
1651/*ARGSUSED*/
1652static void
1653reslist(
1654	struct parse *pcmd,
1655	FILE *fp
1656	)
1657{
1658	struct info_restrict *rl;
1659	struct sockaddr_storage resaddr;
1660	struct sockaddr_storage maskaddr;
1661	int items;
1662	int itemsize;
1663	int res;
1664	int skip;
1665	char *addr;
1666	char *mask;
1667	struct resflags *rf;
1668	u_int32 count;
1669	u_short flags;
1670	u_short mflags;
1671	char flagstr[300];
1672	static const char *comma = ", ";
1673
1674again:
1675	res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
1676		      &items, &itemsize, (void *)&rl, 0, 
1677		      sizeof(struct info_restrict));
1678	
1679	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1680		impl_ver = IMPL_XNTPD_OLD;
1681		goto again;
1682	}
1683
1684	if (res != 0)
1685	    return;
1686
1687	if (!checkitems(items, fp))
1688	    return;
1689
1690	if (!checkitemsize(itemsize, sizeof(struct info_restrict)) &&
1691	    !checkitemsize(itemsize, v4sizeof(struct info_restrict)))
1692	    return;
1693
1694	(void) fprintf(fp,
1695	       "   address          mask            count        flags\n");
1696	(void) fprintf(fp,
1697		       "=====================================================================\n");
1698
1699	while (items > 0) {
1700		memset((char *)&resaddr, 0, sizeof(resaddr));
1701		memset((char *)&maskaddr, 0, sizeof(maskaddr));
1702		if (rl->v6_flag != 0) {
1703			GET_INADDR6(resaddr) = rl->addr6;
1704			GET_INADDR6(maskaddr) = rl->mask6;
1705			resaddr.ss_family = AF_INET6;
1706			maskaddr.ss_family = AF_INET6;
1707#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1708			resaddr.ss_len = SOCKLEN(&resaddr);
1709#endif
1710			addr = nntohost(&resaddr);
1711		} else {
1712			GET_INADDR(resaddr) = rl->addr;
1713			GET_INADDR(maskaddr) = rl->mask;
1714			resaddr.ss_family = AF_INET;
1715			maskaddr.ss_family = AF_INET;
1716#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1717			resaddr.ss_len = SOCKLEN(&resaddr);
1718#endif
1719			if ((rl->mask == (u_int32)0xffffffff))
1720		    		addr = nntohost(&resaddr);
1721			else
1722				addr = stoa(&resaddr);
1723		}
1724		mask = stoa(&maskaddr);
1725		skip = 1;
1726		if ((pcmd->nargs == 0) ||
1727		    ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) ||
1728		    ((pcmd->argval->ival == 4) && (rl->v6_flag == 0)))
1729			skip = 0;
1730		count = ntohl(rl->count);
1731		flags = ntohs(rl->flags);
1732		mflags = ntohs(rl->mflags);
1733		flagstr[0] = '\0';
1734
1735		res = 1;
1736		rf = &resmflags[0];
1737		while (rf->bit != 0) {
1738			if (mflags & rf->bit) {
1739				if (!res)
1740				    (void) strcat(flagstr, comma);
1741				res = 0;
1742				(void) strcat(flagstr, rf->str);
1743			}
1744			rf++;
1745		}
1746
1747		rf = (impl_ver == IMPL_XNTPD_OLD)
1748		     ? &resflagsV2[0]
1749		     : &resflagsV3[0]
1750		     ;
1751		while (rf->bit != 0) {
1752			if (flags & rf->bit) {
1753				if (!res)
1754				    (void) strcat(flagstr, comma);
1755				res = 0;
1756				(void) strcat(flagstr, rf->str);
1757			}
1758			rf++;
1759		}
1760
1761		if (flagstr[0] == '\0')
1762		    (void) strcpy(flagstr, "none");
1763
1764		if (!skip)
1765			(void) fprintf(fp, "%-15.15s %-15.15s %9ld  %s\n",
1766					addr, mask, (u_long)count, flagstr);
1767		rl++;
1768		items--;
1769	}
1770}
1771
1772
1773
1774/*
1775 * new_restrict - create/add a set of restrictions
1776 */
1777static void
1778new_restrict(
1779	struct parse *pcmd,
1780	FILE *fp
1781	)
1782{
1783	do_restrict(pcmd, fp, REQ_RESADDFLAGS);
1784}
1785
1786
1787/*
1788 * unrestrict - remove restriction flags from existing entry
1789 */
1790static void
1791unrestrict(
1792	struct parse *pcmd,
1793	FILE *fp
1794	)
1795{
1796	do_restrict(pcmd, fp, REQ_RESSUBFLAGS);
1797}
1798
1799
1800/*
1801 * delrestrict - delete an existing restriction
1802 */
1803static void
1804delrestrict(
1805	struct parse *pcmd,
1806	FILE *fp
1807	)
1808{
1809	do_restrict(pcmd, fp, REQ_UNRESTRICT);
1810}
1811
1812
1813/*
1814 * do_restrict - decode commandline restrictions and make the request
1815 */
1816static void
1817do_restrict(
1818	struct parse *pcmd,
1819	FILE *fp,
1820	int req_code
1821	)
1822{
1823	struct conf_restrict cres;
1824	int items;
1825	int itemsize;
1826	char *dummy;
1827	u_int32 num;
1828	u_long bit;
1829	int i;
1830	int res;
1831	int err;
1832	int sendsize;
1833
1834	/* Initialize cres */
1835	cres.addr = 0;
1836	cres.mask = 0;
1837	cres.flags = 0;
1838	cres.mflags = 0;
1839	cres.v6_flag = 0;
1840
1841again:
1842	if (impl_ver == IMPL_XNTPD)
1843		sendsize = sizeof(struct conf_restrict);
1844	else
1845		sendsize = v4sizeof(struct conf_restrict);
1846
1847	if (pcmd->argval[0].netnum.ss_family == AF_INET) {
1848		cres.addr = GET_INADDR(pcmd->argval[0].netnum);
1849		cres.mask = GET_INADDR(pcmd->argval[1].netnum);
1850		if (impl_ver == IMPL_XNTPD)
1851			cres.v6_flag = 0;
1852	} else {
1853		if (impl_ver == IMPL_XNTPD_OLD) {
1854			fprintf(stderr,
1855			    "***Server doesn't understand IPv6 addresses\n");
1856			return;
1857		}
1858		cres.addr6 = GET_INADDR6(pcmd->argval[0].netnum);
1859		cres.v6_flag = 1;
1860	}
1861	cres.flags = 0;
1862	cres.mflags = 0;
1863	err = 0;
1864	for (res = 2; res < pcmd->nargs; res++) {
1865		if (STREQ(pcmd->argval[res].string, "ntpport")) {
1866			cres.mflags |= RESM_NTPONLY;
1867		} else {
1868			for (i = 0; resflagsV3[i].bit != 0; i++) {
1869				if (STREQ(pcmd->argval[res].string,
1870					  resflagsV3[i].str))
1871				    break;
1872			}
1873			if (resflagsV3[i].bit != 0) {
1874				cres.flags |= resflagsV3[i].bit;
1875				if (req_code == REQ_UNRESTRICT) {
1876					(void) fprintf(fp,
1877						       "Flag %s inappropriate\n",
1878						       resflagsV3[i].str);
1879					err++;
1880				}
1881			} else {
1882				(void) fprintf(fp, "Unknown flag %s\n",
1883					       pcmd->argval[res].string);
1884				err++;
1885			}
1886		}
1887	}
1888	cres.flags = htons(cres.flags);
1889	cres.mflags = htons(cres.mflags);
1890
1891	/*
1892	 * Make sure mask for default address is zero.  Otherwise,
1893	 * make sure mask bits are contiguous.
1894	 */
1895	if (pcmd->argval[0].netnum.ss_family == AF_INET) {
1896		if (cres.addr == 0) {
1897			cres.mask = 0;
1898		} else {
1899			num = ntohl(cres.mask);
1900			for (bit = 0x80000000; bit != 0; bit >>= 1)
1901			    if ((num & bit) == 0)
1902				break;
1903			for ( ; bit != 0; bit >>= 1)
1904			    if ((num & bit) != 0)
1905				break;
1906			if (bit != 0) {
1907				(void) fprintf(fp, "Invalid mask %s\n",
1908					       numtoa(cres.mask));
1909				err++;
1910			}
1911		}
1912	} else {
1913		/* XXX IPv6 sanity checking stuff */
1914	}
1915
1916	if (err)
1917	    return;
1918
1919	res = doquery(impl_ver, req_code, 1, 1,
1920		      sendsize, (char *)&cres, &items,
1921		      &itemsize, &dummy, 0, sizeof(struct conf_restrict));
1922	
1923	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
1924		impl_ver = IMPL_XNTPD_OLD;
1925		goto again;
1926	}
1927
1928	if (res == 0)
1929	    (void) fprintf(fp, "done!\n");
1930	return;
1931}
1932
1933
1934/*
1935 * monlist - obtain and print the server's monitor data
1936 */
1937/*ARGSUSED*/
1938static void
1939monlist(
1940	struct parse *pcmd,
1941	FILE *fp
1942	)
1943{
1944	char *struct_star;
1945	

Large files files are truncated, but you can click here to view the full file