File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpdc / ntpdc_ops.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * ntpdc_ops.c - subroutines which are called to perform operations by
    3:  *		 ntpdc
    4:  */
    5: 
    6: #ifdef HAVE_CONFIG_H
    7: # include <config.h>
    8: #endif
    9: 
   10: #include <stdio.h>
   11: #include <stddef.h>
   12: 
   13: #include "ntpdc.h"
   14: #include "ntp_net.h"
   15: #include "ntp_control.h"
   16: #include "ntp_refclock.h"
   17: #include "ntp_stdlib.h"
   18: 
   19: #include <ctype.h>
   20: #ifdef HAVE_SYS_TIMEX_H
   21: # include <sys/timex.h>
   22: #endif
   23: #if !defined(__bsdi__) && !defined(apollo)
   24: #ifdef HAVE_NETINET_IN_H
   25: #include <netinet/in.h>
   26: #endif
   27: #endif
   28: 
   29: #include <arpa/inet.h>
   30: 
   31: /*
   32:  * utility functions
   33:  */
   34: static	int	checkitems	(int, FILE *);
   35: static	int	checkitemsize	(int, int);
   36: static	int	check1item	(int, FILE *);
   37: 
   38: /*
   39:  * Declarations for command handlers in here
   40:  */
   41: static	void	peerlist	(struct parse *, FILE *);
   42: static	void	peers		(struct parse *, FILE *);
   43: static void	doconfig	(struct parse *pcmd, FILE *fp, int mode, int refc);
   44: static	void	dmpeers		(struct parse *, FILE *);
   45: static	void	dopeers		(struct parse *, FILE *, int);
   46: static	void	printpeer	(struct info_peer *, FILE *);
   47: static	void	showpeer	(struct parse *, FILE *);
   48: static	void	peerstats	(struct parse *, FILE *);
   49: static	void	loopinfo	(struct parse *, FILE *);
   50: static	void	sysinfo		(struct parse *, FILE *);
   51: static	void	sysstats	(struct parse *, FILE *);
   52: static	void	iostats		(struct parse *, FILE *);
   53: static	void	memstats	(struct parse *, FILE *);
   54: static	void	timerstats	(struct parse *, FILE *);
   55: static	void	addpeer		(struct parse *, FILE *);
   56: static	void	addserver	(struct parse *, FILE *);
   57: static	void	addrefclock	(struct parse *, FILE *);
   58: static	void	broadcast	(struct parse *, FILE *);
   59: static	void	doconfig	(struct parse *, FILE *, int, int);
   60: static	void	unconfig	(struct parse *, FILE *);
   61: static	void	set		(struct parse *, FILE *);
   62: static	void	sys_clear	(struct parse *, FILE *);
   63: static	void	doset		(struct parse *, FILE *, int);
   64: static	void	reslist		(struct parse *, FILE *);
   65: static	void	new_restrict	(struct parse *, FILE *);
   66: static	void	unrestrict	(struct parse *, FILE *);
   67: static	void	delrestrict	(struct parse *, FILE *);
   68: static	void	do_restrict	(struct parse *, FILE *, int);
   69: static	void	monlist		(struct parse *, FILE *);
   70: static	void	reset		(struct parse *, FILE *);
   71: static	void	preset		(struct parse *, FILE *);
   72: static	void	readkeys	(struct parse *, FILE *);
   73: static	void	trustkey	(struct parse *, FILE *);
   74: static	void	untrustkey	(struct parse *, FILE *);
   75: static	void	do_trustkey	(struct parse *, FILE *, int);
   76: static	void	authinfo	(struct parse *, FILE *);
   77: static	void	traps		(struct parse *, FILE *);
   78: static	void	addtrap		(struct parse *, FILE *);
   79: static	void	clrtrap		(struct parse *, FILE *);
   80: static	void	do_addclr_trap	(struct parse *, FILE *, int);
   81: static	void	requestkey	(struct parse *, FILE *);
   82: static	void	controlkey	(struct parse *, FILE *);
   83: static	void	do_changekey	(struct parse *, FILE *, int);
   84: static	void	ctlstats	(struct parse *, FILE *);
   85: static	void	clockstat	(struct parse *, FILE *);
   86: static	void	fudge		(struct parse *, FILE *);
   87: static	void	clkbug		(struct parse *, FILE *);
   88: static	void	kerninfo	(struct parse *, FILE *);
   89: static  void    get_if_stats    (struct parse *, FILE *);
   90: static  void    do_if_reload    (struct parse *, FILE *);
   91: 
   92: /*
   93:  * Commands we understand.  Ntpdc imports this.
   94:  */
   95: struct xcmd opcmds[] = {
   96: 	{ "listpeers",	peerlist,	{ OPT|IP_VERSION, NO, NO, NO },
   97: 	  { "-4|-6", "", "", "" },
   98: 	  "display list of peers the server knows about [IP Version]" },
   99: 	{ "peers",	peers,	{ OPT|IP_VERSION, NO, NO, NO },
  100: 	  { "-4|-6", "", "", "" },
  101: 	  "display peer summary information [IP Version]" },
  102: 	{ "dmpeers",	dmpeers,	{ OPT|IP_VERSION, NO, NO, NO },
  103: 	  { "-4|-6", "", "", "" },
  104: 	  "display peer summary info the way Dave Mills likes it (IP Version)" },
  105: 	{ "showpeer",	showpeer, 	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD},
  106: 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  107: 	  "display detailed information for one or more peers" },
  108: 	{ "pstats",	peerstats,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  109: 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  110: 	  "display statistical information for one or more peers" },
  111: 	{ "loopinfo",	loopinfo,	{ OPT|NTP_STR, NO, NO, NO },
  112: 	  { "oneline|multiline", "", "", "" },
  113: 	  "display loop filter information" },
  114: 	{ "sysinfo",	sysinfo,	{ NO, NO, NO, NO },
  115: 	  { "", "", "", "" },
  116: 	  "display local server information" },
  117: 	{ "sysstats",	sysstats,	{ NO, NO, NO, NO },
  118: 	  { "", "", "", "" },
  119: 	  "display local server statistics" },
  120: 	{ "memstats",	memstats,	{ NO, NO, NO, NO },
  121: 	  { "", "", "", "" },
  122: 	  "display peer memory usage statistics" },
  123: 	{ "iostats",	iostats,	{ NO, NO, NO, NO },
  124: 	  { "", "", "", "" },
  125: 	  "display I/O subsystem statistics" },
  126: 	{ "timerstats",	timerstats,	{ NO, NO, NO, NO },
  127: 	  { "", "", "", "" },
  128: 	  "display event timer subsystem statistics" },
  129: 	{ "addpeer",	addpeer,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  130: 	  { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
  131: 	  "configure a new peer association" },
  132: 	{ "addserver",	addserver,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  133: 	  { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
  134: 	  "configure a new server" },
  135: 	{ "addrefclock",addrefclock,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR },
  136: 	  { "addr", "mode", "minpoll|prefer", "minpoll|prefer" },
  137: 	  "configure a new server" },
  138: 	{ "broadcast",	broadcast,	{ NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  139: 	  { "addr", "keyid", "version", "minpoll" },
  140: 	  "configure broadcasting time service" },
  141: 	{ "unconfig",	unconfig,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  142: 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  143: 	  "unconfigure existing peer assocations" },
  144: 	{ "enable",	set,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  145: 	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
  146: 	  "set a system flag (auth, bclient, monitor, pll, kernel, stats)" },
  147:         { "disable",	sys_clear,      { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  148: 	  { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
  149: 	  "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" },
  150: 	{ "reslist",	reslist,	{OPT|IP_VERSION, NO, NO, NO },
  151: 	  { "-4|-6", "", "", "" },
  152: 	  "display the server's restrict list" },
  153: 	{ "restrict",	new_restrict,	{ NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
  154: 	  { "address", "mask",
  155: 	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
  156: 	    "..." },
  157: 	  "create restrict entry/add flags to entry" },
  158: 	{ "unrestrict", unrestrict,	{ NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
  159: 	  { "address", "mask",
  160: 	    "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
  161: 	    "..." },
  162: 	  "remove flags from a restrict entry" },
  163: 	{ "delrestrict", delrestrict,	{ NTP_ADD, NTP_ADD, OPT|NTP_STR, NO },
  164: 	  { "address", "mask", "ntpport", "" },
  165: 	  "delete a restrict entry" },
  166: 	{ "monlist",	monlist,	{ OPT|NTP_INT, NO, NO, NO },
  167: 	  { "version", "", "", "" },
  168: 	  "display data the server's monitor routines have collected" },
  169: 	{ "reset",	reset,		{ NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  170: 	  { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
  171: 	  "reset various subsystem statistics counters" },
  172: 	{ "preset",	preset,		{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  173: 	  { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  174: 	  "reset stat counters associated with particular peer(s)" },
  175: 	{ "readkeys",	readkeys,	{ NO, NO, NO, NO },
  176: 	  { "", "", "", "" },
  177: 	  "request a reread of the keys file and re-init of system keys" },
  178: 	{ "trustedkey",	trustkey,	{ NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
  179: 	  { "keyid", "keyid", "keyid", "keyid" },
  180: 	  "add one or more key ID's to the trusted list" },
  181: 	{ "untrustedkey", untrustkey,	{ NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
  182: 	  { "keyid", "keyid", "keyid", "keyid" },
  183: 	  "remove one or more key ID's from the trusted list" },
  184: 	{ "authinfo",	authinfo,	{ NO, NO, NO, NO },
  185: 	  { "", "", "", "" },
  186: 	  "display the state of the authentication code" },
  187: 	{ "traps",	traps,		{ NO, NO, NO, NO },
  188: 	  { "", "", "", "" },
  189: 	  "display the traps set in the server" },
  190: 	{ "addtrap",	addtrap,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
  191: 	  { "address", "port", "interface", "" },
  192: 	  "configure a trap in the server" },
  193: 	{ "clrtrap",	clrtrap,	{ NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
  194: 	  { "address", "port", "interface", "" },
  195: 	  "remove a trap (configured or otherwise) from the server" },
  196: 	{ "requestkey",	requestkey,	{ NTP_UINT, NO, NO, NO },
  197: 	  { "keyid", "", "", "" },
  198: 	  "change the keyid the server uses to authenticate requests" },
  199: 	{ "controlkey",	controlkey,	{ NTP_UINT, NO, NO, NO },
  200: 	  { "keyid", "", "", "" },
  201: 	  "change the keyid the server uses to authenticate control messages" },
  202: 	{ "ctlstats",	ctlstats,	{ NO, NO, NO, NO },
  203: 	  { "", "", "", "" },
  204: 	  "display packet count statistics from the control module" },
  205: 	{ "clockstat",	clockstat,	{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  206: 	  { "address", "address", "address", "address" },
  207: 	  "display clock status information" },
  208: 	{ "fudge",	fudge,		{ NTP_ADD, NTP_STR, NTP_STR, NO },
  209: 	  { "address", "time1|time2|val1|val2|flags", "value", "" },
  210: 	  "set/change one of a clock's fudge factors" },
  211: 	{ "clkbug",	clkbug,		{ NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  212: 	  { "address", "address", "address", "address" },
  213: 	  "display clock debugging information" },
  214: 	{ "kerninfo",	kerninfo,	{ NO, NO, NO, NO },
  215: 	  { "", "", "", "" },
  216: 	  "display the kernel pll/pps variables" },
  217: 	{ "ifstats",	get_if_stats,	{ NO, NO, NO, NO },
  218: 	  { "", "", "", "" },
  219: 	  "list interface statistics" },
  220: 	{ "ifreload",	do_if_reload,	{ NO, NO, NO, NO },
  221: 	  { "", "", "", "" },
  222: 	  "reload interface configuration" },
  223: 	{ 0,		0,		{ NO, NO, NO, NO },
  224: 	  { "", "", "", "" }, "" }
  225: };
  226: 
  227: /*
  228:  * For quick string comparisons
  229:  */
  230: #define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
  231: 
  232: /*
  233:  * SET_SS_LEN_IF_PRESENT - used by SET_ADDR, SET_ADDRS macros
  234:  */
  235: 
  236: #ifdef ISC_PLATFORM_HAVESALEN
  237: #define SET_SS_LEN_IF_PRESENT(psau)				\
  238: 	do {							\
  239: 		(psau)->sa.sa_len = SOCKLEN(psau);		\
  240: 	} while (0)
  241: #else
  242: #define SET_SS_LEN_IF_PRESENT(psau)	do { } while (0)
  243: #endif
  244: 
  245: /*
  246:  * SET_ADDR - setup address for v4/v6 as needed
  247:  */
  248: #define SET_ADDR(address, v6flag, v4addr, v6addr)		\
  249: do {								\
  250: 	memset(&(address), 0, sizeof(address));			\
  251: 	if (v6flag) {						\
  252: 		AF(&(address)) = AF_INET6;			\
  253: 		SOCK_ADDR6(&(address)) = (v6addr);		\
  254: 	} else {						\
  255: 		AF(&(address)) = AF_INET;			\
  256: 		NSRCADR(&(address)) = (v4addr);			\
  257: 	}							\
  258: 	SET_SS_LEN_IF_PRESENT(&(address));			\
  259: } while (0)
  260: 
  261: 
  262: /*
  263:  * SET_ADDRS - setup source and destination addresses for 
  264:  * v4/v6 as needed
  265:  */
  266: #define SET_ADDRS(a1, a2, info, a1prefix, a2prefix)		\
  267: do {								\
  268: 	memset(&(a1), 0, sizeof(a1));				\
  269: 	memset(&(a2), 0, sizeof(a2));				\
  270: 	if ((info)->v6_flag) {					\
  271: 		AF(&(a1)) = AF_INET6;				\
  272: 		AF(&(a2)) = AF_INET6;				\
  273: 		SOCK_ADDR6(&(a1)) = (info)->a1prefix##6;	\
  274: 		SOCK_ADDR6(&(a2)) = (info)->a2prefix##6;	\
  275: 	} else {						\
  276: 		AF(&(a1)) = AF_INET;				\
  277: 		AF(&(a2)) = AF_INET;				\
  278: 		NSRCADR(&(a1)) = (info)->a1prefix;		\
  279: 		NSRCADR(&(a2)) = (info)->a2prefix;		\
  280: 	}							\
  281: 	SET_SS_LEN_IF_PRESENT(&(a1));				\
  282: 	SET_SS_LEN_IF_PRESENT(&(a2));				\
  283: } while (0)
  284: 
  285: 
  286: /*
  287:  * SET_ADDRS - setup source and destination addresses for 
  288:  * v4/v6 as needed
  289:  */
  290: #if 0
  291: #define SET_ADDR_MASK(address, addrmask, info)			\
  292: do {								\
  293: 	memset(&(address), 0, sizeof(address));			\
  294: 	memset(&(mask), 0, sizeof(mask));			\
  295: 	if ((info)->v6_flag) {					\
  296: 		AF(&(address)) = AF_INET6;			\
  297: 		AF(&(addrmask)) = AF_INET6;			\
  298: 		SOCK_ADDR6(&(address)) = (info)->addr6;		\
  299: 		SOCK_ADDR6(&(addrmask)) = (info)->mask6;	\
  300: 	} else {						\
  301: 		AF(&(address)) = AF_INET;			\
  302: 		AF(&(addrmask)) = AF_INET;			\
  303: 		NSRCADR(&(address)) = (info)->addr;		\
  304: 		NSRCADR(&(addrmask)) = (info)->mask;		\
  305: 	}							\
  306: 	SET_SS_LEN_IF_PRESENT(&(address));			\
  307: 	SET_SS_LEN_IF_PRESENT(&(addrmask));			\
  308: } while (0)
  309: #endif
  310: 
  311: /*
  312:  * checkitems - utility to print a message if no items were returned
  313:  */
  314: static int
  315: checkitems(
  316: 	int items,
  317: 	FILE *fp
  318: 	)
  319: {
  320: 	if (items == 0) {
  321: 		(void) fprintf(fp, "No data returned in response to query\n");
  322: 		return 0;
  323: 	}
  324: 	return 1;
  325: }
  326: 
  327: 
  328: /*
  329:  * checkitemsize - utility to print a message if the item size is wrong
  330:  */
  331: static int
  332: checkitemsize(
  333: 	int itemsize,
  334: 	int expected
  335: 	)
  336: {
  337: 	if (itemsize != expected) {
  338: 		(void) fprintf(stderr,
  339: 			       "***Incorrect item size returned by remote host (%d should be %d)\n",
  340: 			       itemsize, expected);
  341: 		return 0;
  342: 	}
  343: 	return 1;
  344: }
  345: 
  346: 
  347: /*
  348:  * check1item - check to make sure we have exactly one item
  349:  */
  350: static int
  351: check1item(
  352: 	int items,
  353: 	FILE *fp
  354: 	)
  355: {
  356: 	if (items == 0) {
  357: 		(void) fprintf(fp, "No data returned in response to query\n");
  358: 		return 0;
  359: 	}
  360: 	if (items > 1) {
  361: 		(void) fprintf(fp, "Expected one item in response, got %d\n",
  362: 			       items);
  363: 		return 0;
  364: 	}
  365: 	return 1;
  366: }
  367: 
  368: 
  369: /*
  370:  * peerlist - get a short list of peers
  371:  */
  372: /*ARGSUSED*/
  373: static void
  374: peerlist(
  375: 	struct parse *pcmd,
  376: 	FILE *fp
  377: 	)
  378: {
  379: 	struct info_peer_list *plist;
  380: 	sockaddr_u paddr;
  381: 	int items;
  382: 	int itemsize;
  383: 	int res;
  384: 
  385: again:
  386: 	res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
  387: 		      &itemsize, (void *)&plist, 0, 
  388: 		      sizeof(struct info_peer_list));
  389: 	
  390: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  391: 		impl_ver = IMPL_XNTPD_OLD;
  392: 		goto again;
  393: 	}
  394: 
  395: 	if (res != 0)
  396: 	    return;
  397: 
  398: 	if (!checkitems(items, fp))
  399: 	    return;
  400: 
  401: 	if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) &&
  402: 	    !checkitemsize(itemsize, v4sizeof(struct info_peer_list)))
  403: 	    return;
  404: 
  405: 	while (items > 0) {
  406: 		SET_ADDR(paddr, plist->v6_flag, plist->addr, plist->addr6);
  407: 		if ((pcmd->nargs == 0) ||
  408: 		    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
  409: 		    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
  410: 			(void) fprintf(fp, "%-9s %s\n",
  411: 				modetoa(plist->hmode),
  412: 				nntohost(&paddr));
  413: 		plist++;
  414: 		items--;
  415: 	}
  416: }
  417: 
  418: 
  419: /*
  420:  * peers - show peer summary
  421:  */
  422: static void
  423: peers(
  424: 	struct parse *pcmd,
  425: 	FILE *fp
  426: 	)
  427: {
  428: 	dopeers(pcmd, fp, 0);
  429: }
  430: 
  431: /*
  432:  * dmpeers - show peer summary, Dave Mills style
  433:  */
  434: static void
  435: dmpeers(
  436: 	struct parse *pcmd,
  437: 	FILE *fp
  438: 	)
  439: {
  440: 	dopeers(pcmd, fp, 1);
  441: }
  442: 
  443: 
  444: /*
  445:  * peers - show peer summary
  446:  */
  447: /*ARGSUSED*/
  448: static void
  449: dopeers(
  450: 	struct parse *pcmd,
  451: 	FILE *fp,
  452: 	int dmstyle
  453: 	)
  454: {
  455: 	struct info_peer_summary *plist;
  456: 	sockaddr_u dstadr;
  457: 	sockaddr_u srcadr;
  458: 	int items;
  459: 	int itemsize;
  460: 	int ntp_poll;
  461: 	int res;
  462: 	int c;
  463: 	l_fp tempts;
  464: 
  465: again:
  466: 	res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
  467: 		      &items, &itemsize, (void *)&plist, 0, 
  468: 		      sizeof(struct info_peer_summary));
  469: 	
  470: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  471: 		impl_ver = IMPL_XNTPD_OLD;
  472: 		goto again;
  473: 	}
  474: 
  475: 	if (res != 0)
  476: 	    return;
  477: 
  478: 	if (!checkitems(items, fp))
  479: 	    return;
  480: 
  481: 	if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) &&
  482: 	    !checkitemsize(itemsize, v4sizeof(struct info_peer_summary)))
  483: 		return;
  484: 
  485: 	(void) fprintf(fp,
  486: 		       "     remote           local      st poll reach  delay   offset    disp\n");
  487: 	(void) fprintf(fp,
  488: 		       "=======================================================================\n");
  489: 	while (items > 0) {
  490: 		if (!dmstyle) {
  491: 			if (plist->flags & INFO_FLAG_SYSPEER)
  492: 			    c = '*';
  493: 			else if (plist->hmode == MODE_ACTIVE)
  494: 			    c = '+';
  495: 			else if (plist->hmode == MODE_PASSIVE)
  496: 			    c = '-';
  497: 			else if (plist->hmode == MODE_CLIENT)
  498: 			    c = '=';
  499: 			else if (plist->hmode == MODE_BROADCAST)
  500: 			    c = '^';
  501: 			else if (plist->hmode == MODE_BCLIENT)
  502: 			    c = '~';
  503: 			else
  504: 			    c = ' ';
  505: 		} else {
  506: 			if (plist->flags & INFO_FLAG_SYSPEER)
  507: 			    c = '*';
  508: 			else if (plist->flags & INFO_FLAG_SHORTLIST)
  509: 			    c = '+';
  510: 			else if (plist->flags & INFO_FLAG_SEL_CANDIDATE)
  511: 			    c = '.';
  512: 			else
  513: 			    c = ' ';
  514: 		}
  515: 		NTOHL_FP(&(plist->offset), &tempts);
  516: 		ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
  517: 				  NTP_MINPOLL);
  518: 		SET_ADDRS(dstadr, srcadr, plist, dstadr, srcadr);
  519: 		if ((pcmd->nargs == 0) ||
  520: 		    ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
  521: 		    ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
  522: 			(void) fprintf(fp,
  523: 			    "%c%-15.15s %-15.15s %2u %4d  %3o %7.7s %9.9s %7.7s\n",
  524: 			    c, nntohost(&srcadr), stoa(&dstadr),
  525: 			    plist->stratum, ntp_poll, plist->reach,
  526: 			    fptoa(NTOHS_FP(plist->delay), 5),
  527: 			    lfptoa(&tempts, 6),
  528: 			    ufptoa(NTOHS_FP(plist->dispersion), 5));
  529: 		plist++;
  530: 		items--;
  531: 	}
  532: }
  533: 
  534: /* Convert a refid & stratum (in host order) to a string */
  535: static char*
  536: refid_string(
  537: 	u_int32 refid,
  538: 	int stratum
  539: 	)
  540: {
  541: 	if (stratum <= 1) {
  542: 		static char junk[5];
  543: 		junk[4] = 0;
  544: 		memmove(junk, (char *)&refid, 4);
  545: 		return junk;
  546: 	}
  547: 
  548: 	return numtoa(refid);
  549: }
  550: 
  551: static void
  552: print_pflag(
  553: 	    FILE *fp,
  554: 	    u_int32 flags
  555: 	    )
  556: {
  557:      const char *str;
  558: 
  559:      if (flags == 0) {
  560: 		(void) fprintf(fp, " none\n");
  561: 	} else {
  562: 		str = "";
  563: 		if (flags & INFO_FLAG_SYSPEER) {
  564: 			(void) fprintf(fp, " system_peer");
  565: 			str = ",";
  566: 		}
  567: 		if (flags & INFO_FLAG_CONFIG) {
  568: 			(void) fprintf(fp, "%s config", str);
  569: 			str = ",";
  570: 		}
  571: 		if (flags & INFO_FLAG_REFCLOCK) {
  572: 			(void) fprintf(fp, "%s refclock", str);
  573: 			str = ",";
  574: 		}
  575: 		if (flags & INFO_FLAG_AUTHENABLE) {
  576: 			(void) fprintf(fp, "%s auth", str);
  577: 			str = ",";
  578: 		}
  579: 		if (flags & INFO_FLAG_BCLIENT) {
  580: 			(void) fprintf(fp, "%s bclient", str);
  581: 			str = ",";
  582: 		}
  583: 		if (flags & INFO_FLAG_PREFER) {
  584: 			(void) fprintf(fp, "%s prefer", str);
  585: 			str = ",";
  586: 		}
  587: 		if (flags & INFO_FLAG_IBURST) {
  588: 			(void) fprintf(fp, "%s iburst", str);
  589: 			str = ",";
  590: 		}
  591: 		if (flags & INFO_FLAG_BURST) {
  592: 			(void) fprintf(fp, "%s burst", str);
  593: 		}
  594: 		(void) fprintf(fp, "\n");
  595: 	}
  596: }
  597: /*
  598:  * printpeer - print detail information for a peer
  599:  */
  600: static void
  601: printpeer(
  602: 	register struct info_peer *pp,
  603: 	FILE *fp
  604: 	)
  605: {
  606: 	register int i;
  607: 	l_fp tempts;
  608: 	sockaddr_u srcadr, dstadr;
  609: 	
  610: 	SET_ADDRS(dstadr, srcadr, pp, dstadr, srcadr);
  611: 	
  612: 	(void) fprintf(fp, "remote %s, local %s\n",
  613: 		       stoa(&srcadr), stoa(&dstadr));
  614: 	(void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n",
  615: 		       modetoa(pp->hmode), modetoa(pp->pmode),
  616: 		       pp->stratum, pp->precision);
  617: 	
  618: 	(void) fprintf(fp,
  619: 		       "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
  620: 		       pp->leap & 0x2 ? '1' : '0',
  621: 		       pp->leap & 0x1 ? '1' : '0',
  622: 		       refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
  623: 		       ufptoa(NTOHS_FP(pp->rootdispersion), 5));
  624: 	
  625: 	(void) fprintf(fp,
  626: 		       "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
  627: 		       pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
  628: 
  629: 	(void) fprintf(fp,
  630: 		       "reach %03o, unreach %d, flash 0x%04x, ",
  631: 		       pp->reach, pp->unreach, pp->flash2);
  632: 
  633: 	(void) fprintf(fp, "boffset %s, ttl/mode %d\n",
  634: 		       fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
  635: 	
  636: 	(void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
  637: 	print_pflag(fp, pp->flags); 
  638: 
  639: 	NTOHL_FP(&pp->reftime, &tempts);
  640: 	(void) fprintf(fp, "reference time:      %s\n",
  641: 		       prettydate(&tempts));
  642: 	NTOHL_FP(&pp->org, &tempts);
  643: 	(void) fprintf(fp, "originate timestamp: %s\n",
  644: 		       prettydate(&tempts));
  645: 	NTOHL_FP(&pp->rec, &tempts);
  646: 	(void) fprintf(fp, "receive timestamp:   %s\n",
  647: 		       prettydate(&tempts));
  648: 	NTOHL_FP(&pp->xmt, &tempts);
  649: 	(void) fprintf(fp, "transmit timestamp:  %s\n",
  650: 		       prettydate(&tempts));
  651: 	
  652: 	(void) fprintf(fp, "filter delay: ");
  653: 	for (i = 0; i < NTP_SHIFT; i++) {
  654: 		(void) fprintf(fp, " %-8.8s",
  655: 			       fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
  656: 		if (i == (NTP_SHIFT>>1)-1)
  657: 		    (void) fprintf(fp, "\n              ");
  658: 	}
  659: 	(void) fprintf(fp, "\n");
  660: 
  661: 	(void) fprintf(fp, "filter offset:");
  662: 	for (i = 0; i < NTP_SHIFT; i++) {
  663: 		NTOHL_FP(&pp->filtoffset[i], &tempts);
  664: 		(void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
  665: 		if (i == (NTP_SHIFT>>1)-1)
  666: 		    (void) fprintf(fp, "\n              ");
  667: 	}
  668: 	(void) fprintf(fp, "\n");
  669: 
  670: 	(void) fprintf(fp, "filter order: ");
  671: 	for (i = 0; i < NTP_SHIFT; i++) {
  672: 		(void) fprintf(fp, " %-8d", pp->order[i]);
  673: 		if (i == (NTP_SHIFT>>1)-1)
  674: 		    (void) fprintf(fp, "\n              ");
  675: 	}
  676: 	(void) fprintf(fp, "\n");
  677: 	
  678: 
  679: 	NTOHL_FP(&pp->offset, &tempts);
  680: 	(void) fprintf(fp,
  681: 		       "offset %s, delay %s, error bound %s, filter error %s\n",
  682: 		       lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
  683: 		       ufptoa(NTOHS_FP(pp->dispersion), 5),
  684: 		       ufptoa(NTOHS_FP(pp->selectdisp), 5));
  685: }
  686: 
  687: 
  688: /*
  689:  * showpeer - show detailed information for a peer
  690:  */
  691: static void
  692: showpeer(
  693: 	struct parse *pcmd,
  694: 	FILE *fp
  695: 	)
  696: {
  697: 	struct info_peer *pp;
  698: 	/* 4 is the maximum number of peers which will fit in a packet */
  699: 	struct info_peer_list *pl, plist[min(MAXARGS, 4)];
  700: 	int qitemlim;
  701: 	int qitems;
  702: 	int items;
  703: 	int itemsize;
  704: 	int res;
  705: 	int sendsize;
  706: 
  707: again:
  708: 	if (impl_ver == IMPL_XNTPD)
  709: 		sendsize = sizeof(struct info_peer_list);
  710: 	else
  711: 		sendsize = v4sizeof(struct info_peer_list);
  712: 
  713: 	qitemlim = min(pcmd->nargs, COUNTOF(plist));
  714: 	for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
  715: 		if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
  716: 			pl->addr = NSRCADR(&pcmd->argval[qitems].netnum);
  717: 			if (impl_ver == IMPL_XNTPD)
  718: 				pl->v6_flag = 0;
  719: 		} else {
  720: 			if (impl_ver == IMPL_XNTPD_OLD) {
  721: 				fprintf(stderr,
  722: 				    "***Server doesn't understand IPv6 addresses\n");
  723: 				return;
  724: 			}
  725: 			pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum);
  726: 			pl->v6_flag = 1;
  727: 		}
  728: 		pl->port = (u_short)s_port;
  729: 		pl->hmode = pl->flags = 0;
  730: 		pl = (struct info_peer_list *)((char *)pl + sendsize);
  731: 	}
  732: 
  733: 	res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems,
  734: 		      sendsize, (char *)plist, &items,
  735: 		      &itemsize, (void *)&pp, 0, sizeof(struct info_peer));
  736: 	
  737: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  738: 		impl_ver = IMPL_XNTPD_OLD;
  739: 		goto again;
  740: 	}
  741: 
  742: 	if (res != 0)
  743: 	    return;
  744: 
  745: 	if (!checkitems(items, fp))
  746: 	    return;
  747: 
  748: 	if (!checkitemsize(itemsize, sizeof(struct info_peer)) &&
  749: 	    !checkitemsize(itemsize, v4sizeof(struct info_peer)))
  750: 	    return;
  751: 
  752: 	while (items-- > 0) {
  753: 		printpeer(pp, fp);
  754: 		if (items > 0)
  755: 		    (void) fprintf(fp, "\n");
  756: 		pp++;
  757: 	}
  758: }
  759: 
  760: 
  761: /*
  762:  * peerstats - return statistics for a peer
  763:  */
  764: static void
  765: peerstats(
  766: 	struct parse *pcmd,
  767: 	FILE *fp
  768: 	)
  769: {
  770: 	struct info_peer_stats *pp;
  771: 	/* 4 is the maximum number of peers which will fit in a packet */
  772: 	struct info_peer_list *pl, plist[min(MAXARGS, 4)];
  773: 	sockaddr_u src, dst;
  774: 	int qitemlim;
  775: 	int qitems;
  776: 	int items;
  777: 	int itemsize;
  778: 	int res;
  779: 	int sendsize;
  780: 
  781: again:
  782: 	if (impl_ver == IMPL_XNTPD)
  783: 		sendsize = sizeof(struct info_peer_list);
  784: 	else
  785: 		sendsize = v4sizeof(struct info_peer_list);
  786: 
  787: 	memset(plist, 0, sizeof(plist));
  788: 
  789: 	qitemlim = min(pcmd->nargs, COUNTOF(plist));
  790: 	for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
  791: 		if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
  792: 			pl->addr = NSRCADR(&pcmd->argval[qitems].netnum);
  793: 			if (impl_ver == IMPL_XNTPD)
  794: 				pl->v6_flag = 0;
  795: 		} else {
  796: 			if (impl_ver == IMPL_XNTPD_OLD) {
  797: 				fprintf(stderr,
  798: 				    "***Server doesn't understand IPv6 addresses\n");
  799: 				return;
  800: 			}
  801: 			pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum);
  802: 			pl->v6_flag = 1;
  803: 		}
  804: 		pl->port = (u_short)s_port;
  805: 		pl->hmode = plist[qitems].flags = 0;
  806: 		pl = (struct info_peer_list *)((char *)pl + sendsize);
  807: 	}
  808: 
  809: 	res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems,
  810: 		      sendsize, (char *)plist, &items,
  811: 		      &itemsize, (void *)&pp, 0, 
  812: 		      sizeof(struct info_peer_stats));
  813: 	
  814: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  815: 		impl_ver = IMPL_XNTPD_OLD;
  816: 		goto again;
  817: 	}
  818: 
  819: 	if (res != 0)
  820: 	    return;
  821: 
  822: 	if (!checkitems(items, fp))
  823: 	    return;
  824: 
  825: 	if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) &&
  826: 	    !checkitemsize(itemsize, v4sizeof(struct info_peer_stats)))
  827: 	    return;
  828: 
  829: 	while (items-- > 0) {
  830: 		ZERO_SOCK(&dst);
  831: 		ZERO_SOCK(&src);
  832: 		if (pp->v6_flag != 0) {
  833: 			AF(&dst) = AF_INET6;
  834: 			AF(&src) = AF_INET6;
  835: 			SOCK_ADDR6(&dst) = pp->dstadr6;
  836: 			SOCK_ADDR6(&src) = pp->srcadr6;
  837: 		} else {
  838: 			AF(&dst) = AF_INET;
  839: 			AF(&src) = AF_INET;
  840: 			NSRCADR(&dst) = pp->dstadr;
  841: 			NSRCADR(&src) = pp->srcadr;
  842: 		}
  843: #ifdef ISC_PLATFORM_HAVESALEN
  844: 		src.sa.sa_len = SOCKLEN(&src);
  845: 		dst.sa.sa_len = SOCKLEN(&dst);
  846: #endif
  847: 		fprintf(fp, "remote host:          %s\n",
  848: 			nntohost(&src));
  849: 		fprintf(fp, "local interface:      %s\n",
  850: 			stoa(&dst));
  851: 		fprintf(fp, "time last received:   %lus\n",
  852: 			(u_long)ntohl(pp->timereceived));
  853: 		fprintf(fp, "time until next send: %lus\n",
  854: 			(u_long)ntohl(pp->timetosend));
  855: 		fprintf(fp, "reachability change:  %lus\n",
  856: 			(u_long)ntohl(pp->timereachable));
  857: 		fprintf(fp, "packets sent:         %lu\n",
  858: 			(u_long)ntohl(pp->sent));
  859: 		fprintf(fp, "packets received:     %lu\n",
  860: 			(u_long)ntohl(pp->processed));
  861: 		fprintf(fp, "bad authentication:   %lu\n",
  862: 			(u_long)ntohl(pp->badauth));
  863: 		fprintf(fp, "bogus origin:         %lu\n",
  864: 			(u_long)ntohl(pp->bogusorg));
  865: 		fprintf(fp, "duplicate:            %lu\n",
  866: 			(u_long)ntohl(pp->oldpkt));
  867: 		fprintf(fp, "bad dispersion:       %lu\n",
  868: 			(u_long)ntohl(pp->seldisp));
  869: 		fprintf(fp, "bad reference time:   %lu\n",
  870: 			(u_long)ntohl(pp->selbroken));
  871: 		fprintf(fp, "candidate order:      %u\n",
  872: 			pp->candidate);
  873: 		if (items > 0)
  874: 			fprintf(fp, "\n");
  875: 		fprintf(fp, "flags:	");
  876: 		print_pflag(fp, ntohs(pp->flags));
  877: 		pp++;
  878: 	}
  879: }
  880: 
  881: 
  882: /*
  883:  * loopinfo - show loop filter information
  884:  */
  885: static void
  886: loopinfo(
  887: 	struct parse *pcmd,
  888: 	FILE *fp
  889: 	)
  890: {
  891: 	struct info_loop *il;
  892: 	int items;
  893: 	int itemsize;
  894: 	int oneline = 0;
  895: 	int res;
  896: 	l_fp tempts;
  897: 
  898: 	if (pcmd->nargs > 0) {
  899: 		if (STREQ(pcmd->argval[0].string, "oneline"))
  900: 		    oneline = 1;
  901: 		else if (STREQ(pcmd->argval[0].string, "multiline"))
  902: 		    oneline = 0;
  903: 		else {
  904: 			(void) fprintf(stderr, "How many lines?\n");
  905: 			return;
  906: 		}
  907: 	}
  908: 
  909: again:
  910: 	res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
  911: 		      &items, &itemsize, (void *)&il, 0, 
  912: 		      sizeof(struct info_loop));
  913: 	
  914: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  915: 		impl_ver = IMPL_XNTPD_OLD;
  916: 		goto again;
  917: 	}
  918: 
  919: 	if (res != 0)
  920: 	    return;
  921: 
  922: 	if (!check1item(items, fp))
  923: 	    return;
  924: 
  925: 	if (!checkitemsize(itemsize, sizeof(struct info_loop)))
  926: 	    return;
  927: 
  928: 	if (oneline) {
  929: 		l_fp temp2ts;
  930: 
  931: 		NTOHL_FP(&il->last_offset, &tempts);
  932: 		NTOHL_FP(&il->drift_comp, &temp2ts);
  933: 
  934: 		(void) fprintf(fp,
  935: 			       "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
  936: 			       lfptoa(&tempts, 6),
  937: 			       lfptoa(&temp2ts, 3),
  938: 			       (long)(int32)ntohl((u_long)il->compliance),
  939: 			       (u_long)ntohl((u_long)il->watchdog_timer));
  940: 	} else {
  941: 		NTOHL_FP(&il->last_offset, &tempts);
  942: 		(void) fprintf(fp, "offset:               %s s\n",
  943: 			       lfptoa(&tempts, 6));
  944: 		NTOHL_FP(&il->drift_comp, &tempts);
  945: 		(void) fprintf(fp, "frequency:            %s ppm\n",
  946: 			       lfptoa(&tempts, 3));
  947: 		(void) fprintf(fp, "poll adjust:          %ld\n",
  948: 			       (long)(int32)ntohl(il->compliance));
  949: 		(void) fprintf(fp, "watchdog timer:       %ld s\n",
  950: 			       (u_long)ntohl(il->watchdog_timer));
  951: 	}
  952: }
  953: 
  954: 
  955: /*
  956:  * sysinfo - show current system state
  957:  */
  958: /*ARGSUSED*/
  959: static void
  960: sysinfo(
  961: 	struct parse *pcmd,
  962: 	FILE *fp
  963: 	)
  964: {
  965: 	struct info_sys *is;
  966: 	sockaddr_u peeraddr;
  967: 	int items;
  968: 	int itemsize;
  969: 	int res;
  970: 	l_fp tempts;
  971: 
  972: again:
  973: 	res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
  974: 		      &items, &itemsize, (void *)&is, 0,
  975: 		      sizeof(struct info_sys));
  976: 	
  977: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  978: 		impl_ver = IMPL_XNTPD_OLD;
  979: 		goto again;
  980: 	}
  981: 
  982: 	if (res != 0)
  983: 	    return;
  984: 
  985: 	if (!check1item(items, fp))
  986: 	    return;
  987: 
  988: 	if (!checkitemsize(itemsize, sizeof(struct info_sys)) &&
  989: 	    !checkitemsize(itemsize, v4sizeof(struct info_sys)))
  990: 	    return;
  991: 
  992: 	SET_ADDR(peeraddr, is->v6_flag, is->peer, is->peer6);
  993: 
  994: 	(void) fprintf(fp, "system peer:          %s\n", nntohost(&peeraddr));
  995: 	(void) fprintf(fp, "system peer mode:     %s\n", modetoa(is->peer_mode));
  996: 	(void) fprintf(fp, "leap indicator:       %c%c\n",
  997: 		       is->leap & 0x2 ? '1' : '0',
  998: 		       is->leap & 0x1 ? '1' : '0');
  999: 	(void) fprintf(fp, "stratum:              %d\n", (int)is->stratum);
 1000: 	(void) fprintf(fp, "precision:            %d\n", (int)is->precision);
 1001: 	(void) fprintf(fp, "root distance:        %s s\n",
 1002: 		       fptoa(NTOHS_FP(is->rootdelay), 5));
 1003: 	(void) fprintf(fp, "root dispersion:      %s s\n",
 1004: 		       ufptoa(NTOHS_FP(is->rootdispersion), 5));
 1005: 	(void) fprintf(fp, "reference ID:         [%s]\n",
 1006: 		       refid_string(is->refid, is->stratum));
 1007: 	NTOHL_FP(&is->reftime, &tempts);
 1008: 	(void) fprintf(fp, "reference time:       %s\n", prettydate(&tempts));
 1009: 
 1010: 	(void) fprintf(fp, "system flags:         ");
 1011: 	if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
 1012: 	    INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL |
 1013: 	    INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
 1014: 		(void) fprintf(fp, "none\n");
 1015: 	} else {
 1016: 		if (is->flags & INFO_FLAG_BCLIENT)
 1017: 		    (void) fprintf(fp, "bclient ");
 1018: 		if (is->flags & INFO_FLAG_AUTHENTICATE)
 1019: 		    (void) fprintf(fp, "auth ");
 1020: 		if (is->flags & INFO_FLAG_MONITOR)
 1021: 		    (void) fprintf(fp, "monitor ");
 1022: 		if (is->flags & INFO_FLAG_NTP)
 1023: 		    (void) fprintf(fp, "ntp ");
 1024: 		if (is->flags & INFO_FLAG_KERNEL)
 1025: 		    (void) fprintf(fp, "kernel ");
 1026: 		if (is->flags & INFO_FLAG_FILEGEN)
 1027: 		    (void) fprintf(fp, "stats ");
 1028: 		if (is->flags & INFO_FLAG_CAL)
 1029: 		    (void) fprintf(fp, "calibrate ");
 1030: 		if (is->flags & INFO_FLAG_PPS_SYNC)
 1031: 		    (void) fprintf(fp, "pps ");
 1032: 		(void) fprintf(fp, "\n");
 1033: 	}
 1034: 	(void) fprintf(fp, "jitter:               %s s\n",
 1035: 		       fptoa(ntohl(is->frequency), 6));
 1036: 	(void) fprintf(fp, "stability:            %s ppm\n",
 1037: 		       ufptoa(ntohl(is->stability), 3));
 1038: 	(void) fprintf(fp, "broadcastdelay:       %s s\n",
 1039: 		       fptoa(NTOHS_FP(is->bdelay), 6));
 1040: 	NTOHL_FP(&is->authdelay, &tempts);
 1041: 	(void) fprintf(fp, "authdelay:            %s s\n", lfptoa(&tempts, 6));
 1042: }
 1043: 
 1044: 
 1045: /*
 1046:  * sysstats - print system statistics
 1047:  */
 1048: /*ARGSUSED*/
 1049: static void
 1050: sysstats(
 1051: 	struct parse *pcmd,
 1052: 	FILE *fp
 1053: 	)
 1054: {
 1055: 	struct info_sys_stats *ss;
 1056: 	int items;
 1057: 	int itemsize;
 1058: 	int res;
 1059: 
 1060: again:
 1061: 	res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
 1062: 		      &items, &itemsize, (void *)&ss, 0, 
 1063: 		      sizeof(struct info_sys_stats));
 1064: 	
 1065: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1066: 		impl_ver = IMPL_XNTPD_OLD;
 1067: 		goto again;
 1068: 	}
 1069: 
 1070: 	if (res != 0)
 1071: 	    return;
 1072: 
 1073: 	if (!check1item(items, fp))
 1074: 	    return;
 1075: 
 1076: 	if (itemsize != sizeof(struct info_sys_stats) &&
 1077: 	    itemsize != sizeof(struct old_info_sys_stats)) {
 1078: 		/* issue warning according to new structure size */
 1079: 		checkitemsize(itemsize, sizeof(struct info_sys_stats));
 1080: 		return;
 1081: 	}
 1082: 	fprintf(fp, "time since restart:     %lu\n",
 1083: 		(u_long)ntohl(ss->timeup));
 1084: 	fprintf(fp, "time since reset:       %lu\n",
 1085: 		(u_long)ntohl(ss->timereset));
 1086: 	fprintf(fp, "packets received:       %lu\n",
 1087: 		(u_long)ntohl(ss->received));
 1088: 	fprintf(fp, "packets processed:      %lu\n",
 1089: 		(u_long)ntohl(ss->processed));
 1090: 	fprintf(fp, "current version:        %lu\n",
 1091: 		(u_long)ntohl(ss->newversionpkt));
 1092: 	fprintf(fp, "previous version:       %lu\n",
 1093: 		(u_long)ntohl(ss->oldversionpkt));
 1094: 	fprintf(fp, "declined:               %lu\n",
 1095: 		(u_long)ntohl(ss->unknownversion));
 1096: 	fprintf(fp, "access denied:          %lu\n",
 1097: 		(u_long)ntohl(ss->denied));
 1098: 	fprintf(fp, "bad length or format:   %lu\n",
 1099: 		(u_long)ntohl(ss->badlength));
 1100: 	fprintf(fp, "bad authentication:     %lu\n",
 1101: 		(u_long)ntohl(ss->badauth));
 1102: 	if (itemsize != sizeof(struct info_sys_stats))
 1103: 	    return;
 1104: 	
 1105: 	fprintf(fp, "rate exceeded:          %lu\n",
 1106: 	       (u_long)ntohl(ss->limitrejected));
 1107: }
 1108: 
 1109: 
 1110: 
 1111: /*
 1112:  * iostats - print I/O statistics
 1113:  */
 1114: /*ARGSUSED*/
 1115: static void
 1116: iostats(
 1117: 	struct parse *pcmd,
 1118: 	FILE *fp
 1119: 	)
 1120: {
 1121: 	struct info_io_stats *io;
 1122: 	int items;
 1123: 	int itemsize;
 1124: 	int res;
 1125: 
 1126: again:
 1127: 	res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, NULL, &items,
 1128: 		      &itemsize, (void *)&io, 0, sizeof(*io));
 1129: 	
 1130: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1131: 		impl_ver = IMPL_XNTPD_OLD;
 1132: 		goto again;
 1133: 	}
 1134: 
 1135: 	if (res != 0)
 1136: 		return;
 1137: 
 1138: 	if (!check1item(items, fp))
 1139: 		return;
 1140: 
 1141: 	if (!checkitemsize(itemsize, sizeof(*io)))
 1142: 		return;
 1143: 
 1144: 	fprintf(fp, "time since reset:     %lu\n",
 1145: 		(u_long)ntohl(io->timereset));
 1146: 	fprintf(fp, "receive buffers:      %u\n",
 1147: 		(u_int)ntohs(io->totalrecvbufs));
 1148: 	fprintf(fp, "free receive buffers: %u\n",
 1149: 		(u_int)ntohs(io->freerecvbufs));
 1150: 	fprintf(fp, "used receive buffers: %u\n",
 1151: 		(u_int)ntohs(io->fullrecvbufs));
 1152: 	fprintf(fp, "low water refills:    %u\n",
 1153: 		(u_int)ntohs(io->lowwater));
 1154: 	fprintf(fp, "dropped packets:      %lu\n",
 1155: 		(u_long)ntohl(io->dropped));
 1156: 	fprintf(fp, "ignored packets:      %lu\n",
 1157: 		(u_long)ntohl(io->ignored));
 1158: 	fprintf(fp, "received packets:     %lu\n",
 1159: 		(u_long)ntohl(io->received));
 1160: 	fprintf(fp, "packets sent:         %lu\n",
 1161: 		(u_long)ntohl(io->sent));
 1162: 	fprintf(fp, "packets not sent:     %lu\n",
 1163: 		(u_long)ntohl(io->notsent));
 1164: 	fprintf(fp, "interrupts handled:   %lu\n",
 1165: 		(u_long)ntohl(io->interrupts));
 1166: 	fprintf(fp, "received by int:      %lu\n",
 1167: 		(u_long)ntohl(io->int_received));
 1168: }
 1169: 
 1170: 
 1171: /*
 1172:  * memstats - print peer memory statistics
 1173:  */
 1174: /*ARGSUSED*/
 1175: static void
 1176: memstats(
 1177: 	struct parse *pcmd,
 1178: 	FILE *fp
 1179: 	)
 1180: {
 1181: 	struct info_mem_stats *mem;
 1182: 	int i;
 1183: 	int items;
 1184: 	int itemsize;
 1185: 	int res;
 1186: 
 1187: again:
 1188: 	res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, NULL, &items,
 1189: 		      &itemsize, (void *)&mem, 0, sizeof(*mem));
 1190: 	
 1191: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1192: 		impl_ver = IMPL_XNTPD_OLD;
 1193: 		goto again;
 1194: 	}
 1195: 
 1196: 	if (res != 0)
 1197: 		return;
 1198: 
 1199: 	if (!check1item(items, fp))
 1200: 		return;
 1201: 
 1202: 	if (!checkitemsize(itemsize, sizeof(*mem)))
 1203: 		return;
 1204: 
 1205: 	fprintf(fp, "time since reset:     %lu\n",
 1206: 		(u_long)ntohl(mem->timereset));
 1207: 	fprintf(fp, "total peer memory:    %u\n",
 1208: 		(u_int)ntohs(mem->totalpeermem));
 1209: 	fprintf(fp, "free peer memory:     %u\n",
 1210: 		(u_int)ntohs(mem->freepeermem));
 1211: 	fprintf(fp, "calls to findpeer:    %lu\n",
 1212: 		(u_long)ntohl(mem->findpeer_calls));
 1213: 	fprintf(fp, "new peer allocations: %lu\n",
 1214: 		(u_long)ntohl(mem->allocations));
 1215: 	fprintf(fp, "peer demobilizations: %lu\n",
 1216: 		(u_long)ntohl(mem->demobilizations));
 1217: 
 1218: 	fprintf(fp, "hash table counts:   ");
 1219: 	for (i = 0; i < NTP_HASH_SIZE; i++) {
 1220: 		fprintf(fp, "%4d", (int)mem->hashcount[i]);
 1221: 		if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1))
 1222: 			fprintf(fp, "\n                     ");
 1223: 	}
 1224: 	fprintf(fp, "\n");
 1225: }
 1226: 
 1227: 
 1228: 
 1229: /*
 1230:  * timerstats - print timer statistics
 1231:  */
 1232: /*ARGSUSED*/
 1233: static void
 1234: timerstats(
 1235: 	struct parse *pcmd,
 1236: 	FILE *fp
 1237: 	)
 1238: {
 1239: 	struct info_timer_stats *tim;
 1240: 	int items;
 1241: 	int itemsize;
 1242: 	int res;
 1243: 
 1244: again:
 1245: 	res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, NULL, &items,
 1246: 		      &itemsize, (void *)&tim, 0, sizeof(*tim));
 1247: 	
 1248: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1249: 		impl_ver = IMPL_XNTPD_OLD;
 1250: 		goto again;
 1251: 	}
 1252: 
 1253: 	if (res != 0)
 1254: 		return;
 1255: 
 1256: 	if (!check1item(items, fp))
 1257: 		return;
 1258: 
 1259: 	if (!checkitemsize(itemsize, sizeof(*tim)))
 1260: 		return;
 1261: 
 1262: 	fprintf(fp, "time since reset:  %lu\n",
 1263: 		(u_long)ntohl(tim->timereset));
 1264: 	fprintf(fp, "alarms handled:    %lu\n",
 1265: 		(u_long)ntohl(tim->alarms));
 1266: 	fprintf(fp, "alarm overruns:    %lu\n",
 1267: 		(u_long)ntohl(tim->overflows));
 1268: 	fprintf(fp, "calls to transmit: %lu\n",
 1269: 		(u_long)ntohl(tim->xmtcalls));
 1270: }
 1271: 
 1272: 
 1273: /*
 1274:  * addpeer - configure an active mode association
 1275:  */
 1276: static void
 1277: addpeer(
 1278: 	struct parse *pcmd,
 1279: 	FILE *fp
 1280: 	)
 1281: {
 1282: 	doconfig(pcmd, fp, MODE_ACTIVE, 0);
 1283: }
 1284: 
 1285: 
 1286: /*
 1287:  * addserver - configure a client mode association
 1288:  */
 1289: static void
 1290: addserver(
 1291: 	struct parse *pcmd,
 1292: 	FILE *fp
 1293: 	)
 1294: {
 1295: 	doconfig(pcmd, fp, MODE_CLIENT, 0);
 1296: }
 1297: 
 1298: /*
 1299:  * addrefclock - configure a reference clock association
 1300:  */
 1301: static void
 1302: addrefclock(
 1303: 	struct parse *pcmd,
 1304: 	FILE *fp
 1305: 	)
 1306: {
 1307: 	doconfig(pcmd, fp, MODE_CLIENT, 1);
 1308: }
 1309: 
 1310: /*
 1311:  * broadcast - configure a broadcast mode association
 1312:  */
 1313: static void
 1314: broadcast(
 1315: 	struct parse *pcmd,
 1316: 	FILE *fp
 1317: 	)
 1318: {
 1319: 	doconfig(pcmd, fp, MODE_BROADCAST, 0);
 1320: }
 1321: 
 1322: 
 1323: /*
 1324:  * config - configure a new peer association
 1325:  */
 1326: static void
 1327: doconfig(
 1328: 	struct parse *pcmd,
 1329: 	FILE *fp,
 1330: 	int mode,
 1331: 	int refc
 1332: 	)
 1333: {
 1334: 	struct conf_peer cpeer;
 1335: 	int items;
 1336: 	int itemsize;
 1337: 	char *dummy;
 1338: 	u_long keyid;
 1339: 	u_int version;
 1340: 	u_char minpoll;
 1341: 	u_char maxpoll;
 1342: 	u_int flags;
 1343: 	u_char cmode;
 1344: 	int res;
 1345: 	int sendsize;
 1346: 	int numtyp;
 1347: 	long val;
 1348: 
 1349: again:
 1350: 	keyid = 0;
 1351: 	version = 3;
 1352: 	flags = 0;
 1353: 	res = FALSE;
 1354: 	cmode = 0;
 1355: 	minpoll = NTP_MINDPOLL;
 1356: 	maxpoll = NTP_MAXDPOLL;
 1357: 	numtyp = 1;
 1358: 	if (refc)
 1359: 		numtyp = 5;
 1360: 
 1361: 	if (impl_ver == IMPL_XNTPD)
 1362: 		sendsize = sizeof(struct conf_peer);
 1363: 	else
 1364: 		sendsize = v4sizeof(struct conf_peer);
 1365: 
 1366: 	items = 1;
 1367: 	while (pcmd->nargs > items) {
 1368: 		if (STREQ(pcmd->argval[items].string, "prefer"))
 1369: 			flags |= CONF_FLAG_PREFER;
 1370: 		else if (STREQ(pcmd->argval[items].string, "burst"))
 1371: 			flags |= CONF_FLAG_BURST;
 1372: 		else if (STREQ(pcmd->argval[items].string, "iburst"))
 1373: 			flags |= CONF_FLAG_IBURST;
 1374: 		else if (!refc && STREQ(pcmd->argval[items].string, "keyid"))
 1375: 			numtyp = 1;
 1376: 		else if (!refc && STREQ(pcmd->argval[items].string, "version"))
 1377: 			numtyp = 2;
 1378: 		else if (STREQ(pcmd->argval[items].string, "minpoll"))
 1379: 			numtyp = 3;
 1380: 		else if (STREQ(pcmd->argval[items].string, "maxpoll"))
 1381: 			numtyp = 4;
 1382: 		else {
 1383: 			if (!atoint(pcmd->argval[items].string, &val))
 1384: 				numtyp = 0;
 1385: 			switch (numtyp) {
 1386: 			case 1:
 1387: 				keyid = val;
 1388: 				numtyp = 2;
 1389: 				break;
 1390: 
 1391: 			case 2:
 1392: 				version = (u_int)val;
 1393: 				numtyp = 0;
 1394: 				break;
 1395: 
 1396: 			case 3:
 1397: 				minpoll = (u_char)val;
 1398: 				numtyp = 0;
 1399: 				break;
 1400: 
 1401: 			case 4:
 1402: 				maxpoll = (u_char)val;
 1403: 				numtyp = 0;
 1404: 				break;
 1405: 
 1406: 			case 5:
 1407: 				cmode = (u_char)val;
 1408: 				numtyp = 0;
 1409: 				break;
 1410: 
 1411: 			default:
 1412: 				fprintf(fp, "*** '%s' not understood\n",
 1413: 					pcmd->argval[items].string);
 1414: 				res = TRUE;
 1415: 				numtyp = 0;
 1416: 			}
 1417: 			if (val < 0) {
 1418: 				fprintf(stderr,
 1419: 					"*** Value '%s' should be unsigned\n",
 1420: 					pcmd->argval[items].string);
 1421: 				res = TRUE;
 1422: 			}
 1423: 		}
 1424: 		items++;
 1425: 	}
 1426: 	if (keyid > 0)
 1427: 		flags |= CONF_FLAG_AUTHENABLE;
 1428: 	if (version > NTP_VERSION || version < NTP_OLDVERSION) {
 1429: 		fprintf(fp, "***invalid version number: %u\n",
 1430: 			version);
 1431: 		res = TRUE;
 1432: 	}
 1433: 	if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 
 1434: 	    maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 
 1435: 	    minpoll > maxpoll) {
 1436: 		fprintf(fp, "***min/max-poll must be within %d..%d\n",
 1437: 			NTP_MINPOLL, NTP_MAXPOLL);
 1438: 		res = TRUE;
 1439: 	}					
 1440: 
 1441: 	if (res)
 1442: 		return;
 1443: 
 1444: 	memset(&cpeer, 0, sizeof(cpeer));
 1445: 
 1446: 	if (IS_IPV4(&pcmd->argval[0].netnum)) {
 1447: 		cpeer.peeraddr = NSRCADR(&pcmd->argval[0].netnum);
 1448: 		if (impl_ver == IMPL_XNTPD)
 1449: 			cpeer.v6_flag = 0;
 1450: 	} else {
 1451: 		if (impl_ver == IMPL_XNTPD_OLD) {
 1452: 			fprintf(stderr,
 1453: 			    "***Server doesn't understand IPv6 addresses\n");
 1454: 			return;
 1455: 		}
 1456: 		cpeer.peeraddr6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
 1457: 		cpeer.v6_flag = 1;
 1458: 	}
 1459: 	cpeer.hmode = (u_char) mode;
 1460: 	cpeer.keyid = keyid;
 1461: 	cpeer.version = (u_char) version;
 1462: 	cpeer.minpoll = minpoll;
 1463: 	cpeer.maxpoll = maxpoll;
 1464: 	cpeer.flags = (u_char)flags;
 1465: 	cpeer.ttl = cmode;
 1466: 
 1467: 	res = doquery(impl_ver, REQ_CONFIG, 1, 1,
 1468: 		      sendsize, (char *)&cpeer, &items,
 1469: 		      &itemsize, &dummy, 0, sizeof(struct conf_peer));
 1470: 	
 1471: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1472: 		impl_ver = IMPL_XNTPD_OLD;
 1473: 		goto again;
 1474: 	}
 1475: 
 1476: 	if (res == INFO_ERR_FMT) {
 1477: 		(void) fprintf(fp,
 1478: 		    "***Retrying command with old conf_peer size\n");
 1479: 		res = doquery(impl_ver, REQ_CONFIG, 1, 1,
 1480: 			      sizeof(struct old_conf_peer), (char *)&cpeer,
 1481: 			      &items, &itemsize, &dummy, 0,
 1482: 			      sizeof(struct conf_peer));
 1483: 	}
 1484: 	if (res == 0)
 1485: 	    (void) fprintf(fp, "done!\n");
 1486: 	return;
 1487: }
 1488: 
 1489: 
 1490: /*
 1491:  * unconfig - unconfigure some associations
 1492:  */
 1493: static void
 1494: unconfig(
 1495: 	struct parse *pcmd,
 1496: 	FILE *fp
 1497: 	)
 1498: {
 1499: 	/* 8 is the maximum number of peers which will fit in a packet */
 1500: 	struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
 1501: 	int qitemlim;
 1502: 	int qitems;
 1503: 	int items;
 1504: 	int itemsize;
 1505: 	char *dummy;
 1506: 	int res;
 1507: 	int sendsize;
 1508: 
 1509: again:
 1510: 	if (impl_ver == IMPL_XNTPD)
 1511: 		sendsize = sizeof(struct conf_unpeer);
 1512: 	else
 1513: 		sendsize = v4sizeof(struct conf_unpeer);
 1514: 
 1515: 	qitemlim = min(pcmd->nargs, COUNTOF(plist));
 1516: 	for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
 1517: 		if (IS_IPV4(&pcmd->argval[0].netnum)) {
 1518: 			pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum);
 1519: 			if (impl_ver == IMPL_XNTPD)
 1520: 				pl->v6_flag = 0;
 1521: 		} else {
 1522: 			if (impl_ver == IMPL_XNTPD_OLD) {
 1523: 				fprintf(stderr,
 1524: 				    "***Server doesn't understand IPv6 addresses\n");
 1525: 				return;
 1526: 			}
 1527: 			pl->peeraddr6 =
 1528: 			    SOCK_ADDR6(&pcmd->argval[qitems].netnum);
 1529: 			pl->v6_flag = 1;
 1530: 		}
 1531: 		pl = (struct conf_unpeer *)((char *)pl + sendsize);
 1532: 	}
 1533: 
 1534: 	res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems,
 1535: 		      sendsize, (char *)plist, &items,
 1536: 		      &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
 1537: 	
 1538: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1539: 		impl_ver = IMPL_XNTPD_OLD;
 1540: 		goto again;
 1541: 	}
 1542: 
 1543: 	if (res == 0)
 1544: 	    (void) fprintf(fp, "done!\n");
 1545: }
 1546: 
 1547: 
 1548: /*
 1549:  * set - set some system flags
 1550:  */
 1551: static void
 1552: set(
 1553: 	struct parse *pcmd,
 1554: 	FILE *fp
 1555: 	)
 1556: {
 1557: 	doset(pcmd, fp, REQ_SET_SYS_FLAG);
 1558: }
 1559: 
 1560: 
 1561: /*
 1562:  * clear - clear some system flags
 1563:  */
 1564: static void
 1565: sys_clear(
 1566: 	struct parse *pcmd,
 1567: 	FILE *fp
 1568: 	)
 1569: {
 1570: 	doset(pcmd, fp, REQ_CLR_SYS_FLAG);
 1571: }
 1572: 
 1573: 
 1574: /*
 1575:  * doset - set/clear system flags
 1576:  */
 1577: static void
 1578: doset(
 1579: 	struct parse *pcmd,
 1580: 	FILE *fp,
 1581: 	int req
 1582: 	)
 1583: {
 1584: 	struct conf_sys_flags sys;
 1585: 	int items;
 1586: 	int itemsize;
 1587: 	char *dummy;
 1588: 	int res;
 1589: 
 1590: 	sys.flags = 0;
 1591: 	res = 0;
 1592: 	for (items = 0; items < pcmd->nargs; items++) {
 1593: 		if (STREQ(pcmd->argval[items].string, "auth"))
 1594: 			sys.flags |= SYS_FLAG_AUTH;
 1595: 		else if (STREQ(pcmd->argval[items].string, "bclient"))
 1596: 			sys.flags |= SYS_FLAG_BCLIENT;
 1597: 		else if (STREQ(pcmd->argval[items].string, "calibrate"))
 1598: 			sys.flags |= SYS_FLAG_CAL;
 1599: 		else if (STREQ(pcmd->argval[items].string, "kernel"))
 1600: 			sys.flags |= SYS_FLAG_KERNEL;
 1601: 		else if (STREQ(pcmd->argval[items].string, "monitor"))
 1602: 			sys.flags |= SYS_FLAG_MONITOR;
 1603: 		else if (STREQ(pcmd->argval[items].string, "ntp"))
 1604: 			sys.flags |= SYS_FLAG_NTP;
 1605: 		else if (STREQ(pcmd->argval[items].string, "pps"))
 1606: 			sys.flags |= SYS_FLAG_PPS;
 1607: 		else if (STREQ(pcmd->argval[items].string, "stats"))
 1608: 			sys.flags |= SYS_FLAG_FILEGEN;
 1609: 		else {
 1610: 			(void) fprintf(fp, "Unknown flag %s\n",
 1611: 			    pcmd->argval[items].string);
 1612: 			res = 1;
 1613: 		}
 1614: 	}
 1615: 
 1616: 	sys.flags = htonl(sys.flags);
 1617: 	if (res || sys.flags == 0)
 1618: 	    return;
 1619: 
 1620: again:
 1621: 	res = doquery(impl_ver, req, 1, 1,
 1622: 		      sizeof(struct conf_sys_flags), (char *)&sys, &items,
 1623: 		      &itemsize, &dummy, 0, sizeof(struct conf_sys_flags));
 1624: 	
 1625: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1626: 		impl_ver = IMPL_XNTPD_OLD;
 1627: 		goto again;
 1628: 	}
 1629: 
 1630: 	if (res == 0)
 1631: 	    (void) fprintf(fp, "done!\n");
 1632: }
 1633: 
 1634: 
 1635: /*
 1636:  * data for printing/interrpreting the restrict flags
 1637:  */
 1638: struct resflags {
 1639:   const char *str;
 1640: 	int bit;
 1641: };
 1642: 
 1643: /* XXX: HMS: we apparently don't report set bits we do not recognize. */
 1644: 
 1645: static struct resflags resflagsV2[] = {
 1646: 	{ "ignore",	0x001 },
 1647: 	{ "noserve",	0x002 },
 1648: 	{ "notrust",	0x004 },
 1649: 	{ "noquery",	0x008 },
 1650: 	{ "nomodify",	0x010 },
 1651: 	{ "nopeer",	0x020 },
 1652: 	{ "notrap",	0x040 },
 1653: 	{ "lptrap",	0x080 },
 1654: 	{ "limited",	0x100 },
 1655: 	{ "",		0 }
 1656: };
 1657: 
 1658: static struct resflags resflagsV3[] = {
 1659: 	{ "ignore",	RES_IGNORE },
 1660: 	{ "noserve",	RES_DONTSERVE },
 1661: 	{ "notrust",	RES_DONTTRUST },
 1662: 	{ "noquery",	RES_NOQUERY },
 1663: 	{ "nomodify",	RES_NOMODIFY },
 1664: 	{ "nopeer",	RES_NOPEER },
 1665: 	{ "notrap",	RES_NOTRAP },
 1666: 	{ "lptrap",	RES_LPTRAP },
 1667: 	{ "limited",	RES_LIMITED },
 1668: 	{ "version",	RES_VERSION },
 1669: 	{ "kod",	RES_KOD },
 1670: 	{ "timeout",	RES_TIMEOUT },
 1671: 
 1672: 	{ "",		0 }
 1673: };
 1674: 
 1675: static struct resflags resmflags[] = {
 1676: 	{ "ntpport",	RESM_NTPONLY },
 1677: 	{ "interface",	RESM_INTERFACE },
 1678: 	{ "",		0 }
 1679: };
 1680: 
 1681: 
 1682: /*
 1683:  * reslist - obtain and print the server's restrict list
 1684:  */
 1685: /*ARGSUSED*/
 1686: static void
 1687: reslist(
 1688: 	struct parse *pcmd,
 1689: 	FILE *fp
 1690: 	)
 1691: {
 1692: 	struct info_restrict *rl;
 1693: 	sockaddr_u resaddr;
 1694: 	sockaddr_u maskaddr;
 1695: 	int items;
 1696: 	int itemsize;
 1697: 	int res;
 1698: 	int skip;
 1699: 	char *addr;
 1700: 	char *mask;
 1701: 	struct resflags *rf;
 1702: 	u_int32 count;
 1703: 	u_short flags;
 1704: 	u_short mflags;
 1705: 	char flagstr[300];
 1706: 	static const char *comma = ", ";
 1707: 
 1708: again:
 1709: 	res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
 1710: 		      &items, &itemsize, (void *)&rl, 0, 
 1711: 		      sizeof(struct info_restrict));
 1712: 	
 1713: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1714: 		impl_ver = IMPL_XNTPD_OLD;
 1715: 		goto again;
 1716: 	}
 1717: 
 1718: 	if (res != 0)
 1719: 	    return;
 1720: 
 1721: 	if (!checkitems(items, fp))
 1722: 	    return;
 1723: 
 1724: 	if (!checkitemsize(itemsize, sizeof(struct info_restrict)) &&
 1725: 	    !checkitemsize(itemsize, v4sizeof(struct info_restrict)))
 1726: 	    return;
 1727: 
 1728: 	(void) fprintf(fp,
 1729: 	       "   address          mask            count        flags\n");
 1730: 	(void) fprintf(fp,
 1731: 		       "=====================================================================\n");
 1732: 
 1733: 	while (items > 0) {
 1734: 		SET_ADDRS(resaddr, maskaddr, rl, addr, mask);
 1735: 		if (rl->v6_flag != 0) {
 1736: 			addr = nntohost(&resaddr);
 1737: 		} else {
 1738: 			if ((rl->mask == (u_int32)0xffffffff))
 1739: 				addr = nntohost(&resaddr);
 1740: 			else
 1741: 				addr = stoa(&resaddr);
 1742: 		}
 1743: 		mask = stoa(&maskaddr);
 1744: 		skip = 1;
 1745: 		if ((pcmd->nargs == 0) ||
 1746: 		    ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) ||
 1747: 		    ((pcmd->argval->ival == 4) && (rl->v6_flag == 0)))
 1748: 			skip = 0;
 1749: 		count = ntohl(rl->count);
 1750: 		flags = ntohs(rl->flags);
 1751: 		mflags = ntohs(rl->mflags);
 1752: 		flagstr[0] = '\0';
 1753: 
 1754: 		res = 1;
 1755: 		rf = &resmflags[0];
 1756: 		while (rf->bit != 0) {
 1757: 			if (mflags & rf->bit) {
 1758: 				if (!res)
 1759: 				    (void) strcat(flagstr, comma);
 1760: 				res = 0;
 1761: 				(void) strcat(flagstr, rf->str);
 1762: 			}
 1763: 			rf++;
 1764: 		}
 1765: 
 1766: 		rf = (impl_ver == IMPL_XNTPD_OLD)
 1767: 		     ? &resflagsV2[0]
 1768: 		     : &resflagsV3[0]
 1769: 		     ;
 1770: 		while (rf->bit != 0) {
 1771: 			if (flags & rf->bit) {
 1772: 				if (!res)
 1773: 				    (void) strcat(flagstr, comma);
 1774: 				res = 0;
 1775: 				(void) strcat(flagstr, rf->str);
 1776: 			}
 1777: 			rf++;
 1778: 		}
 1779: 
 1780: 		if (flagstr[0] == '\0')
 1781: 			strcpy(flagstr, "none");
 1782: 
 1783: 		if (!skip)
 1784: 			fprintf(fp, "%-15.15s %-15.15s %9lu  %s\n",
 1785: 				addr, mask, (u_long)count, flagstr);
 1786: 		rl++;
 1787: 		items--;
 1788: 	}
 1789: }
 1790: 
 1791: 
 1792: 
 1793: /*
 1794:  * new_restrict - create/add a set of restrictions
 1795:  */
 1796: static void
 1797: new_restrict(
 1798: 	struct parse *pcmd,
 1799: 	FILE *fp
 1800: 	)
 1801: {
 1802: 	do_restrict(pcmd, fp, REQ_RESADDFLAGS);
 1803: }
 1804: 
 1805: 
 1806: /*
 1807:  * unrestrict - remove restriction flags from existing entry
 1808:  */
 1809: static void
 1810: unrestrict(
 1811: 	struct parse *pcmd,
 1812: 	FILE *fp
 1813: 	)
 1814: {
 1815: 	do_restrict(pcmd, fp, REQ_RESSUBFLAGS);
 1816: }
 1817: 
 1818: 
 1819: /*
 1820:  * delrestrict - delete an existing restriction
 1821:  */
 1822: static void
 1823: delrestrict(
 1824: 	struct parse *pcmd,
 1825: 	FILE *fp
 1826: 	)
 1827: {
 1828: 	do_restrict(pcmd, fp, REQ_UNRESTRICT);
 1829: }
 1830: 
 1831: 
 1832: /*
 1833:  * do_restrict - decode commandline restrictions and make the request
 1834:  */
 1835: static void
 1836: do_restrict(
 1837: 	struct parse *pcmd,
 1838: 	FILE *fp,
 1839: 	int req_code
 1840: 	)
 1841: {
 1842: 	struct conf_restrict cres;
 1843: 	int items;
 1844: 	int itemsize;
 1845: 	char *dummy;
 1846: 	u_int32 num;
 1847: 	u_long bit;
 1848: 	int i;
 1849: 	int res;
 1850: 	int err;
 1851: 	int sendsize;
 1852: 
 1853: 	/* Initialize cres */
 1854: 	cres.addr = 0;
 1855: 	cres.mask = 0;
 1856: 	cres.flags = 0;
 1857: 	cres.mflags = 0;
 1858: 	cres.v6_flag = 0;
 1859: 
 1860: again:
 1861: 	if (impl_ver == IMPL_XNTPD)
 1862: 		sendsize = sizeof(struct conf_restrict);
 1863: 	else
 1864: 		sendsize = v4sizeof(struct conf_restrict);
 1865: 
 1866: 	if (IS_IPV4(&pcmd->argval[0].netnum)) {
 1867: 		cres.addr = NSRCADR(&pcmd->argval[0].netnum);
 1868: 		cres.mask = NSRCADR(&pcmd->argval[1].netnum);
 1869: 		if (impl_ver == IMPL_XNTPD)
 1870: 			cres.v6_flag = 0;
 1871: 	} else {
 1872: 		if (impl_ver == IMPL_XNTPD_OLD) {
 1873: 			fprintf(stderr,
 1874: 				"***Server doesn't understand IPv6 addresses\n");
 1875: 			return;
 1876: 		}
 1877: 		cres.addr6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
 1878: 		cres.v6_flag = 1;
 1879: 	}
 1880: 	cres.flags = 0;
 1881: 	cres.mflags = 0;
 1882: 	err = FALSE;
 1883: 	for (res = 2; res < pcmd->nargs; res++) {
 1884: 		if (STREQ(pcmd->argval[res].string, "ntpport")) {
 1885: 			cres.mflags |= RESM_NTPONLY;
 1886: 		} else {
 1887: 			for (i = 0; resflagsV3[i].bit != 0; i++) {
 1888: 				if (STREQ(pcmd->argval[res].string,
 1889: 					  resflagsV3[i].str))
 1890: 					break;
 1891: 			}
 1892: 			if (resflagsV3[i].bit != 0) {
 1893: 				cres.flags |= resflagsV3[i].bit;
 1894: 				if (req_code == REQ_UNRESTRICT) {
 1895: 					fprintf(fp,
 1896: 						"Flag %s inappropriate\n",
 1897: 						resflagsV3[i].str);
 1898: 					err = TRUE;
 1899: 				}
 1900: 			} else {
 1901: 				fprintf(fp, "Unknown flag %s\n",
 1902: 					pcmd->argval[res].string);
 1903: 				err = TRUE;
 1904: 			}
 1905: 		}
 1906: 	}
 1907: 	cres.flags = htons(cres.flags);
 1908: 	cres.mflags = htons(cres.mflags);
 1909: 
 1910: 	/*
 1911: 	 * Make sure mask for default address is zero.  Otherwise,
 1912: 	 * make sure mask bits are contiguous.
 1913: 	 */
 1914: 	if (IS_IPV4(&pcmd->argval[0].netnum)) {
 1915: 		if (cres.addr == 0) {
 1916: 			cres.mask = 0;
 1917: 		} else {
 1918: 			num = ntohl(cres.mask);
 1919: 			for (bit = 0x80000000; bit != 0; bit >>= 1)
 1920: 				if ((num & bit) == 0)
 1921: 					break;
 1922: 			for ( ; bit != 0; bit >>= 1)
 1923: 				if ((num & bit) != 0)
 1924: 					break;
 1925: 			if (bit != 0) {
 1926: 				fprintf(fp, "Invalid mask %s\n",
 1927: 					numtoa(cres.mask));
 1928: 				err = TRUE;
 1929: 			}
 1930: 		}
 1931: 	} else {
 1932: 		/* XXX IPv6 sanity checking stuff */
 1933: 	}
 1934: 
 1935: 	if (err)
 1936: 		return;
 1937: 
 1938: 	res = doquery(impl_ver, req_code, 1, 1, sendsize, (char *)&cres,
 1939: 		      &items, &itemsize, &dummy, 0, sizeof(cres));
 1940: 	
 1941: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1942: 		impl_ver = IMPL_XNTPD_OLD;
 1943: 		goto again;
 1944: 	}
 1945: 
 1946: 	if (res == 0)
 1947: 	    (void) fprintf(fp, "done!\n");
 1948: 	return;
 1949: }
 1950: 
 1951: 
 1952: /*
 1953:  * monlist - obtain and print the server's monitor data
 1954:  */
 1955: /*ARGSUSED*/
 1956: static void
 1957: monlist(
 1958: 	struct parse *pcmd,
 1959: 	FILE *fp
 1960: 	)
 1961: {
 1962: 	char *struct_star;
 1963: 	sockaddr_u addr;
 1964: 	sockaddr_u dstadr;
 1965: 	int items;
 1966: 	int itemsize;
 1967: 	int res;
 1968: 	int version = -1;
 1969: 
 1970: 	if (pcmd->nargs > 0) {
 1971: 		version = pcmd->argval[0].ival;
 1972: 	}
 1973: 
 1974: again:
 1975: 	res = doquery(impl_ver,
 1976: 		      (version == 1 || version == -1) ? REQ_MON_GETLIST_1 :
 1977: 		      REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
 1978: 		      &items, &itemsize, &struct_star,
 1979: 		      (version < 0) ? (1 << INFO_ERR_REQ) : 0, 
 1980: 		      sizeof(struct info_monitor_1));
 1981: 
 1982: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 1983: 		impl_ver = IMPL_XNTPD_OLD;
 1984: 		goto again;
 1985: 	}
 1986: 
 1987: 	if (res == INFO_ERR_REQ && version < 0) 
 1988: 	    res = doquery(impl_ver, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
 1989: 			  &items, &itemsize, &struct_star, 0, 
 1990: 			  sizeof(struct info_monitor));
 1991: 	
 1992: 	if (res != 0)
 1993: 	    return;
 1994: 
 1995: 	if (!checkitems(items, fp))
 1996: 	    return;
 1997: 
 1998: 	if (itemsize == sizeof(struct info_monitor_1) ||
 1999: 	    itemsize == v4sizeof(struct info_monitor_1)) {
 2000: 		struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star;
 2001: 
 2002: 		(void) fprintf(fp,
 2003: 			       "remote address          port local address      count m ver rstr avgint  lstint\n");
 2004: 		(void) fprintf(fp,
 2005: 			       "===============================================================================\n");
 2006: 		while (items > 0) {
 2007: 			SET_ADDRS(dstadr, addr, ml, daddr, addr);
 2008: 			if ((pcmd->nargs == 0) ||
 2009: 			    ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
 2010: 			    ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
 2011: 				fprintf(fp, 
 2012: 				    "%-22.22s %5d %-15s %8lu %1u %1u %6lx %6lu %7lu\n",
 2013: 				    nntohost(&addr), 
 2014: 				    ntohs(ml->port),
 2015: 				    stoa(&dstadr),
 2016: 				    (u_long)ntohl(ml->count),
 2017: 				    ml->mode,
 2018: 				    ml->version,
 2019: 				    (u_long)ntohl(ml->restr),
 2020: 				    (u_long)ntohl(ml->lasttime),
 2021: 				    (u_long)ntohl(ml->firsttime));
 2022: 			ml++;
 2023: 			items--;
 2024: 		}
 2025: 	} else if (itemsize == sizeof(struct info_monitor) ||
 2026: 	    itemsize == v4sizeof(struct info_monitor)) {
 2027: 		struct info_monitor *ml = (struct info_monitor *) struct_star;
 2028: 
 2029: 		(void) fprintf(fp,
 2030: 			       "     address               port     count mode ver rstr avgint  lstint\n");
 2031: 		(void) fprintf(fp,
 2032: 			       "===============================================================================\n");
 2033: 		while (items > 0) {
 2034: 			SET_ADDR(dstadr, ml->v6_flag, ml->addr, ml->addr6);
 2035: 			if ((pcmd->nargs == 0) ||
 2036: 			    ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
 2037: 			    ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
 2038: 				(void) fprintf(fp,
 2039: 				    "%-25.25s %5u %9lu %4u %2u %9lx %9lu %9lu\n",
 2040: 				    nntohost(&dstadr),
 2041: 				    ntohs(ml->port),
 2042: 				    (u_long)ntohl(ml->count),
 2043: 				    ml->mode,
 2044: 				    ml->version,
 2045: 				    (u_long)ntohl(ml->restr),
 2046: 				    (u_long)ntohl(ml->lasttime),
 2047: 				    (u_long)ntohl(ml->firsttime));
 2048: 			ml++;
 2049: 			items--;
 2050: 		}
 2051: 	} else if (itemsize == sizeof(struct old_info_monitor)) {
 2052: 		struct old_info_monitor *oml = (struct old_info_monitor *)struct_star;
 2053: 		(void) fprintf(fp,
 2054: 			       "     address          port     count  mode version  lasttime firsttime\n");
 2055: 		(void) fprintf(fp,
 2056: 			       "======================================================================\n");
 2057: 		while (items > 0) {
 2058: 			SET_ADDR(dstadr, oml->v6_flag, oml->addr, oml->addr6);
 2059: 			(void) fprintf(fp, "%-20.20s %5u %9lu %4u   %3u %9lu %9lu\n",
 2060: 				       nntohost(&dstadr),
 2061: 				       ntohs(oml->port),
 2062: 				       (u_long)ntohl(oml->count),
 2063: 				       oml->mode,
 2064: 				       oml->version,
 2065: 				       (u_long)ntohl(oml->lasttime),
 2066: 				       (u_long)ntohl(oml->firsttime));
 2067: 			oml++;
 2068: 			items--;
 2069: 		}
 2070: 	} else {
 2071: 		/* issue warning according to new info_monitor size */
 2072: 		checkitemsize(itemsize, sizeof(struct info_monitor));
 2073: 	}
 2074: }
 2075: 
 2076: 
 2077: /*
 2078:  * Mapping between command line strings and stat reset flags
 2079:  */
 2080: struct statreset {
 2081:   const char *str;
 2082: 	int flag;
 2083: } sreset[] = {
 2084: 	{ "io",		RESET_FLAG_IO },
 2085: 	{ "sys",	RESET_FLAG_SYS },
 2086: 	{ "mem",	RESET_FLAG_MEM },
 2087: 	{ "timer",	RESET_FLAG_TIMER },
 2088: 	{ "auth",	RESET_FLAG_AUTH },
 2089: 	{ "allpeers",	RESET_FLAG_ALLPEERS },
 2090: 	{ "",		0 }
 2091: };
 2092: 
 2093: /*
 2094:  * reset - reset statistic counters
 2095:  */
 2096: static void
 2097: reset(
 2098: 	struct parse *pcmd,
 2099: 	FILE *fp
 2100: 	)
 2101: {
 2102: 	struct reset_flags rflags;
 2103: 	int items;
 2104: 	int itemsize;
 2105: 	char *dummy;
 2106: 	int i;
 2107: 	int res;
 2108: 	int err;
 2109: 
 2110: 	err = 0;
 2111: 	rflags.flags = 0;
 2112: 	for (res = 0; res < pcmd->nargs; res++) {
 2113: 		for (i = 0; sreset[i].flag != 0; i++) {
 2114: 			if (STREQ(pcmd->argval[res].string, sreset[i].str))
 2115: 			    break;
 2116: 		}
 2117: 		if (sreset[i].flag == 0) {
 2118: 			(void) fprintf(fp, "Flag %s unknown\n",
 2119: 				       pcmd->argval[res].string);
 2120: 			err++;
 2121: 		} else {
 2122: 			rflags.flags |= sreset[i].flag;
 2123: 		}
 2124: 	}
 2125: 	rflags.flags = htonl(rflags.flags);
 2126: 
 2127: 	if (err) {
 2128: 		(void) fprintf(fp, "Not done due to errors\n");
 2129: 		return;
 2130: 	}
 2131: 
 2132: again:
 2133: 	res = doquery(impl_ver, REQ_RESET_STATS, 1, 1,
 2134: 		      sizeof(struct reset_flags), (char *)&rflags, &items,
 2135: 		      &itemsize, &dummy, 0, sizeof(struct reset_flags));
 2136: 	
 2137: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2138: 		impl_ver = IMPL_XNTPD_OLD;
 2139: 		goto again;
 2140: 	}
 2141: 
 2142: 	if (res == 0)
 2143: 	    (void) fprintf(fp, "done!\n");
 2144: 	return;
 2145: }
 2146: 
 2147: 
 2148: 
 2149: /*
 2150:  * preset - reset stat counters for particular peers
 2151:  */
 2152: static void
 2153: preset(
 2154: 	struct parse *pcmd,
 2155: 	FILE *fp
 2156: 	)
 2157: {
 2158: 	/* 8 is the maximum number of peers which will fit in a packet */
 2159: 	struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
 2160: 	int qitemlim;
 2161: 	int qitems;
 2162: 	int items;
 2163: 	int itemsize;
 2164: 	char *dummy;
 2165: 	int res;
 2166: 	int sendsize;
 2167: 
 2168: again:
 2169: 	if (impl_ver == IMPL_XNTPD)
 2170: 		sendsize = sizeof(struct conf_unpeer);
 2171: 	else
 2172: 		sendsize = v4sizeof(struct conf_unpeer);
 2173: 
 2174: 	qitemlim = min(pcmd->nargs, COUNTOF(plist));
 2175: 	for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) {
 2176: 		if (IS_IPV4(&pcmd->argval[qitems].netnum)) {
 2177: 			pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum);
 2178: 			if (impl_ver == IMPL_XNTPD)
 2179: 				pl->v6_flag = 0;
 2180: 		} else {
 2181: 			if (impl_ver == IMPL_XNTPD_OLD) {
 2182: 				fprintf(stderr,
 2183: 				    "***Server doesn't understand IPv6 addresses\n");
 2184: 				return;
 2185: 			}
 2186: 			pl->peeraddr6 =
 2187: 			    SOCK_ADDR6(&pcmd->argval[qitems].netnum);
 2188: 			pl->v6_flag = 1;
 2189: 		}
 2190: 		pl = (struct conf_unpeer *)((char *)pl + sendsize);
 2191: 	}
 2192: 
 2193: 	res = doquery(impl_ver, REQ_RESET_PEER, 1, qitems,
 2194: 		      sendsize, (char *)plist, &items,
 2195: 		      &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
 2196: 	
 2197: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2198: 		impl_ver = IMPL_XNTPD_OLD;
 2199: 		goto again;
 2200: 	}
 2201: 
 2202: 	if (res == 0)
 2203: 	    (void) fprintf(fp, "done!\n");
 2204: }
 2205: 
 2206: 
 2207: /*
 2208:  * readkeys - request the server to reread the keys file
 2209:  */
 2210: /*ARGSUSED*/
 2211: static void
 2212: readkeys(
 2213: 	struct parse *pcmd,
 2214: 	FILE *fp
 2215: 	)
 2216: {
 2217: 	int items;
 2218: 	int itemsize;
 2219: 	char *dummy;
 2220: 	int res;
 2221: 
 2222: again:
 2223: 	res = doquery(impl_ver, REQ_REREAD_KEYS, 1, 0, 0, (char *)0,
 2224: 		      &items, &itemsize, &dummy, 0, sizeof(dummy));
 2225: 	
 2226: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2227: 		impl_ver = IMPL_XNTPD_OLD;
 2228: 		goto again;
 2229: 	}
 2230: 
 2231: 	if (res == 0)
 2232: 	    (void) fprintf(fp, "done!\n");
 2233: 	return;
 2234: }
 2235: 
 2236: 
 2237: /*
 2238:  * trustkey - add some keys to the trusted key list
 2239:  */
 2240: static void
 2241: trustkey(
 2242: 	struct parse *pcmd,
 2243: 	FILE *fp
 2244: 	)
 2245: {
 2246: 	do_trustkey(pcmd, fp, REQ_TRUSTKEY);
 2247: }
 2248: 
 2249: 
 2250: /*
 2251:  * untrustkey - remove some keys from the trusted key list
 2252:  */
 2253: static void
 2254: untrustkey(
 2255: 	struct parse *pcmd,
 2256: 	FILE *fp
 2257: 	)
 2258: {
 2259: 	do_trustkey(pcmd, fp, REQ_UNTRUSTKEY);
 2260: }
 2261: 
 2262: 
 2263: /*
 2264:  * do_trustkey - do grunge work of adding/deleting keys
 2265:  */
 2266: static void
 2267: do_trustkey(
 2268: 	struct parse *pcmd,
 2269: 	FILE *fp,
 2270: 	int req
 2271: 	)
 2272: {
 2273: 	u_long keyids[MAXARGS];
 2274: 	int i;
 2275: 	int items;
 2276: 	int itemsize;
 2277: 	char *dummy;
 2278: 	int ritems;
 2279: 	int res;
 2280: 
 2281: 	ritems = 0;
 2282: 	for (i = 0; i < pcmd->nargs; i++) {
 2283: 		keyids[ritems++] = pcmd->argval[i].uval;
 2284: 	}
 2285: 
 2286: again:
 2287: 	res = doquery(impl_ver, req, 1, ritems, sizeof(u_long),
 2288: 		      (char *)keyids, &items, &itemsize, &dummy, 0, 
 2289: 		      sizeof(dummy));
 2290: 	
 2291: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2292: 		impl_ver = IMPL_XNTPD_OLD;
 2293: 		goto again;
 2294: 	}
 2295: 
 2296: 	if (res == 0)
 2297: 	    (void) fprintf(fp, "done!\n");
 2298: 	return;
 2299: }
 2300: 
 2301: 
 2302: 
 2303: /*
 2304:  * authinfo - obtain and print info about authentication
 2305:  */
 2306: /*ARGSUSED*/
 2307: static void
 2308: authinfo(
 2309: 	struct parse *pcmd,
 2310: 	FILE *fp
 2311: 	)
 2312: {
 2313: 	struct info_auth *ia;
 2314: 	int items;
 2315: 	int itemsize;
 2316: 	int res;
 2317: 
 2318: again:
 2319: 	res = doquery(impl_ver, REQ_AUTHINFO, 0, 0, 0, NULL, &items,
 2320: 		      &itemsize, (void *)&ia, 0, sizeof(*ia));
 2321: 	
 2322: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2323: 		impl_ver = IMPL_XNTPD_OLD;
 2324: 		goto again;
 2325: 	}
 2326: 
 2327: 	if (res != 0)
 2328: 		return;
 2329: 
 2330: 	if (!check1item(items, fp))
 2331: 		return;
 2332: 
 2333: 	if (!checkitemsize(itemsize, sizeof(*ia)))
 2334: 		return;
 2335: 
 2336: 	fprintf(fp, "time since reset:     %lu\n",
 2337: 		(u_long)ntohl(ia->timereset));
 2338: 	fprintf(fp, "stored keys:          %lu\n",
 2339: 		(u_long)ntohl(ia->numkeys));
 2340: 	fprintf(fp, "free keys:            %lu\n",
 2341: 		(u_long)ntohl(ia->numfreekeys));
 2342: 	fprintf(fp, "key lookups:          %lu\n",
 2343: 		(u_long)ntohl(ia->keylookups));
 2344: 	fprintf(fp, "keys not found:       %lu\n",
 2345: 		(u_long)ntohl(ia->keynotfound));
 2346: 	fprintf(fp, "uncached keys:        %lu\n",
 2347: 		(u_long)ntohl(ia->keyuncached));
 2348: 	fprintf(fp, "encryptions:          %lu\n",
 2349: 		(u_long)ntohl(ia->encryptions));
 2350: 	fprintf(fp, "decryptions:          %lu\n",
 2351: 		(u_long)ntohl(ia->decryptions));
 2352: 	fprintf(fp, "expired keys:         %lu\n",
 2353: 		(u_long)ntohl(ia->expired));
 2354: }
 2355: 
 2356: 
 2357: 
 2358: /*
 2359:  * traps - obtain and print a list of traps
 2360:  */
 2361: /*ARGSUSED*/
 2362: static void
 2363: traps(
 2364: 	struct parse *pcmd,
 2365: 	FILE *fp
 2366: 	)
 2367: {
 2368: 	int i;
 2369: 	struct info_trap *it;
 2370: 	sockaddr_u trap_addr, local_addr;
 2371: 	int items;
 2372: 	int itemsize;
 2373: 	int res;
 2374: 
 2375: again:
 2376: 	res = doquery(impl_ver, REQ_TRAPS, 0, 0, 0, (char *)NULL,
 2377: 		      &items, &itemsize, (void *)&it, 0, 
 2378: 		      sizeof(struct info_trap));
 2379: 	
 2380: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2381: 		impl_ver = IMPL_XNTPD_OLD;
 2382: 		goto again;
 2383: 	}
 2384: 
 2385: 	if (res != 0)
 2386: 	    return;
 2387: 
 2388: 	if (!checkitems(items, fp))
 2389: 	    return;
 2390: 
 2391: 	if (!checkitemsize(itemsize, sizeof(struct info_trap)) &&
 2392: 	    !checkitemsize(itemsize, v4sizeof(struct info_trap)))
 2393: 	    return;
 2394: 
 2395: 	for (i = 0; i < items; i++ ) {
 2396: 		if (i != 0)
 2397: 		    (void) fprintf(fp, "\n");
 2398: 		SET_ADDRS(trap_addr, local_addr, it, trap_address, local_address);
 2399: 		(void) fprintf(fp, "address %s, port %d\n",
 2400: 				stoa(&trap_addr), 
 2401: 				ntohs(it->trap_port));
 2402: 		(void) fprintf(fp, "interface: %s, ",
 2403: 				(it->local_address == 0)
 2404: 				? "wildcard"
 2405: 				: stoa(&local_addr));
 2406: 		if (ntohl(it->flags) & TRAP_CONFIGURED)
 2407: 		    (void) fprintf(fp, "configured\n");
 2408: 		else if (ntohl(it->flags) & TRAP_NONPRIO)
 2409: 		    (void) fprintf(fp, "low priority\n");
 2410: 		else
 2411: 		    (void) fprintf(fp, "normal priority\n");
 2412: 		
 2413: 		(void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n",
 2414: 			       (long)ntohl(it->origtime),
 2415: 			       (long)ntohl(it->settime));
 2416: 		(void) fprintf(fp, "sequence %d, number of resets %ld\n",
 2417: 			       ntohs(it->sequence),
 2418: 			       (long)ntohl(it->resets));
 2419: 	}
 2420: }
 2421: 
 2422: 
 2423: /*
 2424:  * addtrap - configure a trap
 2425:  */
 2426: static void
 2427: addtrap(
 2428: 	struct parse *pcmd,
 2429: 	FILE *fp
 2430: 	)
 2431: {
 2432: 	do_addclr_trap(pcmd, fp, REQ_ADD_TRAP);
 2433: }
 2434: 
 2435: 
 2436: /*
 2437:  * clrtrap - clear a trap from the server
 2438:  */
 2439: static void
 2440: clrtrap(
 2441: 	struct parse *pcmd,
 2442: 	FILE *fp
 2443: 	)
 2444: {
 2445: 	do_addclr_trap(pcmd, fp, REQ_CLR_TRAP);
 2446: }
 2447: 
 2448: 
 2449: /*
 2450:  * do_addclr_trap - do grunge work of adding/deleting traps
 2451:  */
 2452: static void
 2453: do_addclr_trap(
 2454: 	struct parse *pcmd,
 2455: 	FILE *fp,
 2456: 	int req
 2457: 	)
 2458: {
 2459: 	struct conf_trap ctrap;
 2460: 	int items;
 2461: 	int itemsize;
 2462: 	char *dummy;
 2463: 	int res;
 2464: 	int sendsize;
 2465: 
 2466: again:
 2467: 	if (impl_ver == IMPL_XNTPD)
 2468: 		sendsize = sizeof(struct conf_trap);
 2469: 	else
 2470: 		sendsize = v4sizeof(struct conf_trap);
 2471: 
 2472: 	if (IS_IPV4(&pcmd->argval[0].netnum)) {
 2473: 		ctrap.trap_address = NSRCADR(&pcmd->argval[0].netnum);
 2474: 		if (impl_ver == IMPL_XNTPD)
 2475: 			ctrap.v6_flag = 0;
 2476: 	} else {
 2477: 		if (impl_ver == IMPL_XNTPD_OLD) {
 2478: 			fprintf(stderr,
 2479: 			    "***Server doesn't understand IPv6 addresses\n");
 2480: 			return;
 2481: 		}
 2482: 		ctrap.trap_address6 = SOCK_ADDR6(&pcmd->argval[0].netnum);
 2483: 		ctrap.v6_flag = 1;
 2484: 	}
 2485: 	ctrap.local_address = 0;
 2486: 	ctrap.trap_port = htons(TRAPPORT);
 2487: 	ctrap.unused = 0;
 2488: 
 2489: 	if (pcmd->nargs > 1) {
 2490: 		ctrap.trap_port	= htons((u_short)pcmd->argval[1].uval);
 2491: 		if (pcmd->nargs > 2) {
 2492: 			if (AF(&pcmd->argval[2].netnum) !=
 2493: 			    AF(&pcmd->argval[0].netnum)) {
 2494: 				fprintf(stderr,
 2495: 				    "***Cannot mix IPv4 and IPv6 addresses\n");
 2496: 				return;
 2497: 			}
 2498: 			if (IS_IPV4(&pcmd->argval[2].netnum))
 2499: 				ctrap.local_address = NSRCADR(&pcmd->argval[2].netnum);
 2500: 			else
 2501: 				ctrap.local_address6 = SOCK_ADDR6(&pcmd->argval[2].netnum);
 2502: 		}
 2503: 	}
 2504: 
 2505: 	res = doquery(impl_ver, req, 1, 1, sendsize,
 2506: 		      (char *)&ctrap, &items, &itemsize, &dummy, 0, 
 2507: 		      sizeof(struct conf_trap));
 2508: 	
 2509: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2510: 		impl_ver = IMPL_XNTPD_OLD;
 2511: 		goto again;
 2512: 	}
 2513: 
 2514: 	if (res == 0)
 2515: 	    (void) fprintf(fp, "done!\n");
 2516: 	return;
 2517: }
 2518: 
 2519: 
 2520: 
 2521: /*
 2522:  * requestkey - change the server's request key (a dangerous request)
 2523:  */
 2524: static void
 2525: requestkey(
 2526: 	struct parse *pcmd,
 2527: 	FILE *fp
 2528: 	)
 2529: {
 2530: 	do_changekey(pcmd, fp, REQ_REQUEST_KEY);
 2531: }
 2532: 
 2533: 
 2534: /*
 2535:  * controlkey - change the server's control key
 2536:  */
 2537: static void
 2538: controlkey(
 2539: 	struct parse *pcmd,
 2540: 	FILE *fp
 2541: 	)
 2542: {
 2543: 	do_changekey(pcmd, fp, REQ_CONTROL_KEY);
 2544: }
 2545: 
 2546: 
 2547: 
 2548: /*
 2549:  * do_changekey - do grunge work of changing keys
 2550:  */
 2551: static void
 2552: do_changekey(
 2553: 	struct parse *pcmd,
 2554: 	FILE *fp,
 2555: 	int req
 2556: 	)
 2557: {
 2558: 	u_long key;
 2559: 	int items;
 2560: 	int itemsize;
 2561: 	char *dummy;
 2562: 	int res;
 2563: 
 2564: 
 2565: 	key = htonl((u_int32)pcmd->argval[0].uval);
 2566: 
 2567: again:
 2568: 	res = doquery(impl_ver, req, 1, 1, sizeof(u_int32),
 2569: 		      (char *)&key, &items, &itemsize, &dummy, 0, 
 2570: 		      sizeof(dummy));
 2571: 	
 2572: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2573: 		impl_ver = IMPL_XNTPD_OLD;
 2574: 		goto again;
 2575: 	}
 2576: 
 2577: 	if (res == 0)
 2578: 	    (void) fprintf(fp, "done!\n");
 2579: 	return;
 2580: }
 2581: 
 2582: 
 2583: 
 2584: /*
 2585:  * ctlstats - obtain and print info about authentication
 2586:  */
 2587: /*ARGSUSED*/
 2588: static void
 2589: ctlstats(
 2590: 	struct parse *pcmd,
 2591: 	FILE *fp
 2592: 	)
 2593: {
 2594: 	struct info_control *ic;
 2595: 	int items;
 2596: 	int itemsize;
 2597: 	int res;
 2598: 
 2599: again:
 2600: 	res = doquery(impl_ver, REQ_GET_CTLSTATS, 0, 0, 0, NULL, &items,
 2601: 		      &itemsize, (void *)&ic, 0, sizeof(*ic));
 2602: 	
 2603: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2604: 		impl_ver = IMPL_XNTPD_OLD;
 2605: 		goto again;
 2606: 	}
 2607: 
 2608: 	if (res != 0)
 2609: 		return;
 2610: 
 2611: 	if (!check1item(items, fp))
 2612: 		return;
 2613: 
 2614: 	if (!checkitemsize(itemsize, sizeof(*ic)))
 2615: 		return;
 2616: 
 2617: 	fprintf(fp, "time since reset:       %lu\n",
 2618: 		(u_long)ntohl(ic->ctltimereset));
 2619: 	fprintf(fp, "requests received:      %lu\n",
 2620: 		(u_long)ntohl(ic->numctlreq));
 2621: 	fprintf(fp, "responses sent:         %lu\n",
 2622: 		(u_long)ntohl(ic->numctlresponses));
 2623: 	fprintf(fp, "fragments sent:         %lu\n",
 2624: 		(u_long)ntohl(ic->numctlfrags));
 2625: 	fprintf(fp, "async messages sent:    %lu\n",
 2626: 		(u_long)ntohl(ic->numasyncmsgs));
 2627: 	fprintf(fp, "error msgs sent:        %lu\n",
 2628: 		(u_long)ntohl(ic->numctlerrors));
 2629: 	fprintf(fp, "total bad pkts:         %lu\n",
 2630: 		(u_long)ntohl(ic->numctlbadpkts));
 2631: 	fprintf(fp, "packet too short:       %lu\n",
 2632: 		(u_long)ntohl(ic->numctltooshort));
 2633: 	fprintf(fp, "response on input:      %lu\n",
 2634: 		(u_long)ntohl(ic->numctlinputresp));
 2635: 	fprintf(fp, "fragment on input:      %lu\n",
 2636: 		(u_long)ntohl(ic->numctlinputfrag));
 2637: 	fprintf(fp, "error set on input:     %lu\n",
 2638: 		(u_long)ntohl(ic->numctlinputerr));
 2639: 	fprintf(fp, "bad offset on input:    %lu\n",
 2640: 		(u_long)ntohl(ic->numctlbadoffset));
 2641: 	fprintf(fp, "bad version packets:    %lu\n",
 2642: 		(u_long)ntohl(ic->numctlbadversion));
 2643: 	fprintf(fp, "data in pkt too short:  %lu\n",
 2644: 		(u_long)ntohl(ic->numctldatatooshort));
 2645: 	fprintf(fp, "unknown op codes:       %lu\n",
 2646: 		(u_long)ntohl(ic->numctlbadop));
 2647: }
 2648: 
 2649: 
 2650: /*
 2651:  * clockstat - get and print clock status information
 2652:  */
 2653: static void
 2654: clockstat(
 2655: 	struct parse *pcmd,
 2656: 	FILE *fp
 2657: 	)
 2658: {
 2659: 	struct info_clock *cl;
 2660: 	/* 8 is the maximum number of clocks which will fit in a packet */
 2661: 	u_long clist[min(MAXARGS, 8)];
 2662: 	int qitemlim;
 2663: 	int qitems;
 2664: 	int items;
 2665: 	int itemsize;
 2666: 	int res;
 2667: 	l_fp ts;
 2668: 	struct clktype *clk;
 2669: 
 2670: 	qitemlim = min(pcmd->nargs, COUNTOF(clist));
 2671: 	for (qitems = 0; qitems < qitemlim; qitems++)
 2672: 		clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum);
 2673: 
 2674: again:
 2675: 	res = doquery(impl_ver, REQ_GET_CLOCKINFO, 0, qitems,
 2676: 		      sizeof(u_int32), (char *)clist, &items,
 2677: 		      &itemsize, (void *)&cl, 0, sizeof(struct info_clock));
 2678: 	
 2679: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2680: 		impl_ver = IMPL_XNTPD_OLD;
 2681: 		goto again;
 2682: 	}
 2683: 
 2684: 	if (res != 0)
 2685: 		return;
 2686: 
 2687: 	if (!checkitems(items, fp))
 2688: 		return;
 2689: 
 2690: 	if (!checkitemsize(itemsize, sizeof(struct info_clock)))
 2691: 		return;
 2692: 
 2693: 	while (items-- > 0) {
 2694: 		(void) fprintf(fp, "clock address:        %s\n",
 2695: 			       numtoa(cl->clockadr));
 2696: 		for (clk = clktypes; clk->code >= 0; clk++)
 2697: 		    if (clk->code == cl->type)
 2698: 			break;
 2699: 		if (clk->code >= 0)
 2700: 		    (void) fprintf(fp, "clock type:           %s\n",
 2701: 				   clk->clocktype);
 2702: 		else
 2703: 		    (void) fprintf(fp, "clock type:           unknown type (%d)\n",
 2704: 				   cl->type);
 2705: 		(void) fprintf(fp, "last event:           %d\n",
 2706: 			       cl->lastevent);
 2707: 		(void) fprintf(fp, "current status:       %d\n",
 2708: 			       cl->currentstatus);
 2709: 		(void) fprintf(fp, "number of polls:      %lu\n",
 2710: 			       (u_long)ntohl(cl->polls));
 2711: 		(void) fprintf(fp, "no response to poll:  %lu\n",
 2712: 			       (u_long)ntohl(cl->noresponse));
 2713: 		(void) fprintf(fp, "bad format responses: %lu\n",
 2714: 			       (u_long)ntohl(cl->badformat));
 2715: 		(void) fprintf(fp, "bad data responses:   %lu\n",
 2716: 			       (u_long)ntohl(cl->baddata));
 2717: 		(void) fprintf(fp, "running time:         %lu\n",
 2718: 			       (u_long)ntohl(cl->timestarted));
 2719: 		NTOHL_FP(&cl->fudgetime1, &ts);
 2720: 		(void) fprintf(fp, "fudge time 1:         %s\n",
 2721: 			       lfptoa(&ts, 6));
 2722: 		NTOHL_FP(&cl->fudgetime2, &ts);
 2723: 		(void) fprintf(fp, "fudge time 2:         %s\n",
 2724: 			       lfptoa(&ts, 6));
 2725: 		(void) fprintf(fp, "stratum:              %ld\n",
 2726: 			       (u_long)ntohl(cl->fudgeval1));
 2727: 		(void) fprintf(fp, "reference ID:         %s\n",
 2728: 			       refid_string(ntohl(cl->fudgeval2), 0));
 2729: 		(void) fprintf(fp, "fudge flags:          0x%x\n",
 2730: 			       cl->flags);
 2731: 
 2732: 		if (items > 0)
 2733: 		    (void) fprintf(fp, "\n");
 2734: 		cl++;
 2735: 	}
 2736: }
 2737: 
 2738: 
 2739: /*
 2740:  * fudge - set clock fudge factors
 2741:  */
 2742: static void
 2743: fudge(
 2744: 	struct parse *pcmd,
 2745: 	FILE *fp
 2746: 	)
 2747: {
 2748: 	struct conf_fudge fudgedata;
 2749: 	int items;
 2750: 	int itemsize;
 2751: 	char *dummy;
 2752: 	l_fp ts;
 2753: 	int res;
 2754: 	long val;
 2755: 	u_long u_val;
 2756: 	int err;
 2757: 
 2758: 
 2759: 	err = 0;
 2760: 	memset((char *)&fudgedata, 0, sizeof fudgedata);
 2761: 	fudgedata.clockadr = NSRCADR(&pcmd->argval[0].netnum);
 2762: 
 2763: 	if (STREQ(pcmd->argval[1].string, "time1")) {
 2764: 		fudgedata.which = htonl(FUDGE_TIME1);
 2765: 		if (!atolfp(pcmd->argval[2].string, &ts))
 2766: 		    err = 1;
 2767: 		else
 2768: 		    NTOHL_FP(&ts, &fudgedata.fudgetime);
 2769: 	} else if (STREQ(pcmd->argval[1].string, "time2")) {
 2770: 		fudgedata.which = htonl(FUDGE_TIME2);
 2771: 		if (!atolfp(pcmd->argval[2].string, &ts))
 2772: 		    err = 1;
 2773: 		else
 2774: 		    NTOHL_FP(&ts, &fudgedata.fudgetime);
 2775: 	} else if (STREQ(pcmd->argval[1].string, "val1")) {
 2776: 		fudgedata.which = htonl(FUDGE_VAL1);
 2777: 		if (!atoint(pcmd->argval[2].string, &val))
 2778: 		    err = 1;
 2779: 		else
 2780: 		    fudgedata.fudgeval_flags = htonl(val);
 2781: 	} else if (STREQ(pcmd->argval[1].string, "val2")) {
 2782: 		fudgedata.which = htonl(FUDGE_VAL2);
 2783: 		if (!atoint(pcmd->argval[2].string, &val))
 2784: 		    err = 1;
 2785: 		else
 2786: 		    fudgedata.fudgeval_flags = htonl((u_int32)val);
 2787: 	} else if (STREQ(pcmd->argval[1].string, "flags")) {
 2788: 		fudgedata.which = htonl(FUDGE_FLAGS);
 2789: 		if (!hextoint(pcmd->argval[2].string, &u_val))
 2790: 		    err = 1;
 2791: 		else
 2792: 		    fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf));
 2793: 	} else {
 2794: 		(void) fprintf(stderr, "What fudge is %s?\n",
 2795: 			       pcmd->argval[1].string);
 2796: 		return;
 2797: 	}
 2798: 
 2799: 	if (err) {
 2800: 		(void) fprintf(stderr, "Unknown fudge parameter %s\n",
 2801: 			       pcmd->argval[2].string);
 2802: 		return;
 2803: 	}
 2804: 
 2805: again:
 2806: 	res = doquery(impl_ver, REQ_SET_CLKFUDGE, 1, 1,
 2807: 		      sizeof(struct conf_fudge), (char *)&fudgedata, &items,
 2808: 		      &itemsize, &dummy, 0, sizeof(dummy));
 2809: 
 2810: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2811: 		impl_ver = IMPL_XNTPD_OLD;
 2812: 		goto again;
 2813: 	}
 2814: 
 2815: 	if (res == 0)
 2816: 	    (void) fprintf(fp, "done!\n");
 2817: 	return;
 2818: }
 2819: 
 2820: /*
 2821:  * clkbug - get and print clock debugging information
 2822:  */
 2823: static void
 2824: clkbug(
 2825: 	struct parse *pcmd,
 2826: 	FILE *fp
 2827: 	)
 2828: {
 2829: 	register int i;
 2830: 	register int n;
 2831: 	register u_int32 s;
 2832: 	struct info_clkbug *cl;
 2833: 	/* 8 is the maximum number of clocks which will fit in a packet */
 2834: 	u_long clist[min(MAXARGS, 8)];
 2835: 	u_int32 ltemp;
 2836: 	int qitemlim;
 2837: 	int qitems;
 2838: 	int items;
 2839: 	int itemsize;
 2840: 	int res;
 2841: 	int needsp;
 2842: 	l_fp ts;
 2843: 
 2844: 	qitemlim = min(pcmd->nargs, COUNTOF(clist));
 2845: 	for (qitems = 0; qitems < qitemlim; qitems++)
 2846: 		clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum);
 2847: 
 2848: again:
 2849: 	res = doquery(impl_ver, REQ_GET_CLKBUGINFO, 0, qitems,
 2850: 		      sizeof(u_int32), (char *)clist, &items,
 2851: 		      &itemsize, (void *)&cl, 0, sizeof(struct info_clkbug));
 2852: 	
 2853: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2854: 		impl_ver = IMPL_XNTPD_OLD;
 2855: 		goto again;
 2856: 	}
 2857: 
 2858: 	if (res != 0)
 2859: 		return;
 2860: 
 2861: 	if (!checkitems(items, fp))
 2862: 		return;
 2863: 
 2864: 	if (!checkitemsize(itemsize, sizeof(struct info_clkbug)))
 2865: 		return;
 2866: 
 2867: 	while (items-- > 0) {
 2868: 		(void) fprintf(fp, "clock address:        %s\n",
 2869: 			       numtoa(cl->clockadr));
 2870: 		n = (int)cl->nvalues;
 2871: 		(void) fprintf(fp, "values: %d", n);
 2872: 		s = ntohs(cl->svalues);
 2873: 		if (n > NUMCBUGVALUES)
 2874: 		    n = NUMCBUGVALUES;
 2875: 		for (i = 0; i < n; i++) {
 2876: 			ltemp = ntohl(cl->values[i]);
 2877: 			ltemp &= 0xffffffff;	/* HMS: This does nothing now */
 2878: 			if ((i & 0x3) == 0)
 2879: 			    (void) fprintf(fp, "\n");
 2880: 			if (s & (1 << i))
 2881: 			    (void) fprintf(fp, "%12ld", (u_long)ltemp);
 2882: 			else
 2883: 			    (void) fprintf(fp, "%12lu", (u_long)ltemp);
 2884: 		}
 2885: 		(void) fprintf(fp, "\n");
 2886: 
 2887: 		n = (int)cl->ntimes;
 2888: 		(void) fprintf(fp, "times: %d", n);
 2889: 		s = ntohl(cl->stimes);
 2890: 		if (n > NUMCBUGTIMES)
 2891: 		    n = NUMCBUGTIMES;
 2892: 		needsp = 0;
 2893: 		for (i = 0; i < n; i++) {
 2894: 			if ((i & 0x1) == 0) {
 2895: 			    (void) fprintf(fp, "\n");
 2896: 			} else {
 2897: 				for (;needsp > 0; needsp--)
 2898: 				    putc(' ', fp);
 2899: 			}
 2900: 			NTOHL_FP(&cl->times[i], &ts);
 2901: 			if (s & (1 << i)) {
 2902: 				(void) fprintf(fp, "%17s",
 2903: 					       lfptoa(&ts, 6));
 2904: 				needsp = 22;
 2905: 			} else {
 2906: 				(void) fprintf(fp, "%37s",
 2907: 					       uglydate(&ts));
 2908: 				needsp = 2;
 2909: 			}
 2910: 		}
 2911: 		(void) fprintf(fp, "\n");
 2912: 		if (items > 0) {
 2913: 			cl++;
 2914: 			(void) fprintf(fp, "\n");
 2915: 		}
 2916: 	}
 2917: }
 2918: 
 2919: 
 2920: /*
 2921:  * kerninfo - display the kernel pll/pps variables
 2922:  */
 2923: static void
 2924: kerninfo(
 2925: 	struct parse *pcmd,
 2926: 	FILE *fp
 2927: 	)
 2928: {
 2929: 	struct info_kernel *ik;
 2930: 	int items;
 2931: 	int itemsize;
 2932: 	int res;
 2933: 	unsigned status;
 2934: 	double tscale = 1e-6;
 2935: 
 2936: again:
 2937: 	res = doquery(impl_ver, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
 2938: 		      &items, &itemsize, (void *)&ik, 0, 
 2939: 		      sizeof(struct info_kernel));
 2940: 
 2941: 	if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
 2942: 		impl_ver = IMPL_XNTPD_OLD;
 2943: 		goto again;
 2944: 	}
 2945: 
 2946: 	if (res != 0)
 2947: 	    return;
 2948: 	if (!check1item(items, fp))
 2949: 	    return;
 2950: 	if (!checkitemsize(itemsize, sizeof(struct info_kernel)))
 2951: 	    return;
 2952: 
 2953: 	status = ntohs(ik->status) & 0xffff;
 2954: 	/*
 2955: 	 * pll variables. We know more than we should about the NANO bit.
 2956: 	 */
 2957: #ifdef STA_NANO
 2958: 	if (status & STA_NANO)
 2959: 		tscale = 1e-9;
 2960: #endif
 2961: 	(void)fprintf(fp, "pll offset:           %g s\n",
 2962: 	    (int32)ntohl(ik->offset) * tscale);
 2963: 	(void)fprintf(fp, "pll frequency:        %s ppm\n",
 2964: 	    fptoa((s_fp)ntohl(ik->freq), 3));
 2965: 	(void)fprintf(fp, "maximum error:        %g s\n",
 2966: 	    (u_long)ntohl(ik->maxerror) * 1e-6);
 2967: 	(void)fprintf(fp, "estimated error:      %g s\n",
 2968: 	    (u_long)ntohl(ik->esterror) * 1e-6);
 2969: 	(void)fprintf(fp, "status:               %04x ", status);
 2970: #ifdef STA_PLL
 2971: 	if (status & STA_PLL) (void)fprintf(fp, " pll");
 2972: #endif
 2973: #ifdef STA_PPSFREQ
 2974: 	if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq");
 2975: #endif
 2976: #ifdef STA_PPSTIME
 2977: 	if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime");
 2978: #endif
 2979: #ifdef STA_FLL
 2980: 	if (status & STA_FLL) (void)fprintf(fp, " fll");
 2981: #endif
 2982: #ifdef STA_INS
 2983: 	if (status & STA_INS) (void)fprintf(fp, " ins");
 2984: #endif
 2985: #ifdef STA_DEL
 2986: 	if (status & STA_DEL) (void)fprintf(fp, " del");
 2987: #endif
 2988: #ifdef STA_UNSYNC
 2989: 	if (status & STA_UNSYNC) (void)fprintf(fp, " unsync");
 2990: #endif
 2991: #ifdef STA_FREQHOLD
 2992: 	if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold");
 2993: #endif
 2994: #ifdef STA_PPSSIGNAL
 2995: 	if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal");
 2996: #endif
 2997: #ifdef STA_PPSJITTER
 2998: 	if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter");
 2999: #endif
 3000: #ifdef STA_PPSWANDER
 3001: 	if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander");
 3002: #endif
 3003: #ifdef STA_PPSERROR
 3004: 	if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror");
 3005: #endif
 3006: #ifdef STA_CLOCKERR
 3007: 	if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr");
 3008: #endif
 3009: #ifdef STA_NANO
 3010: 	if (status & STA_NANO) (void)fprintf(fp, " nano");
 3011: #endif
 3012: #ifdef STA_MODE
 3013: 	if (status & STA_MODE) (void)fprintf(fp, " mode=fll");
 3014: #endif
 3015: #ifdef STA_CLK
 3016: 	if (status & STA_CLK) (void)fprintf(fp, " src=B");
 3017: #endif
 3018: 	(void)fprintf(fp, "\n");
 3019: 	(void)fprintf(fp, "pll time constant:    %ld\n",
 3020: 	    (u_long)ntohl(ik->constant));
 3021: 	(void)fprintf(fp, "precision:            %g s\n",
 3022: 	    (u_long)ntohl(ik->precision) * tscale);
 3023: 	(void)fprintf(fp, "frequency tolerance:  %s ppm\n",
 3024: 	    fptoa((s_fp)ntohl(ik->tolerance), 0));
 3025: 
 3026: 	/*
 3027: 	 * For backwards compatibility (ugh), we find the pps variables
 3028: 	 * only if the shift member is nonzero.
 3029: 	 */
 3030: 	if (!ik->shift)
 3031: 	    return;
 3032: 
 3033: 	/*
 3034: 	 * pps variables
 3035: 	 */
 3036: 	(void)fprintf(fp, "pps frequency:        %s ppm\n",
 3037: 	    fptoa((s_fp)ntohl(ik->ppsfreq), 3));
 3038: 	(void)fprintf(fp, "pps stability:        %s ppm\n",
 3039: 	    fptoa((s_fp)ntohl(ik->stabil), 3));
 3040: 	(void)fprintf(fp, "pps jitter:           %g s\n",
 3041: 	    (u_long)ntohl(ik->jitter) * tscale);
 3042: 	(void)fprintf(fp, "calibration interval: %d s\n",
 3043: 		      1 << ntohs(ik->shift));
 3044: 	(void)fprintf(fp, "calibration cycles:   %ld\n",
 3045: 		      (u_long)ntohl(ik->calcnt));
 3046: 	(void)fprintf(fp, "jitter exceeded:      %ld\n",
 3047: 		      (u_long)ntohl(ik->jitcnt));
 3048: 	(void)fprintf(fp, "stability exceeded:   %ld\n",
 3049: 		      (u_long)ntohl(ik->stbcnt));
 3050: 	(void)fprintf(fp, "calibration errors:   %ld\n",
 3051: 		      (u_long)ntohl(ik->errcnt));
 3052: }
 3053: 
 3054: #define IF_LIST_FMT     "%2d %c %48s %c %c %12.12s %03lx %3lu %2lu %5lu %5lu %5lu %2lu %3lu %7lu\n"
 3055: #define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %3s %7s\n"
 3056: #define IF_LIST_AFMT_STR "     %48s %c\n"
 3057: #define IF_LIST_LABELS  "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "PC", "uptime"
 3058: #define IF_LIST_LINE    "==================================================================================================================\n"
 3059: 
 3060: static void
 3061: iflist(
 3062: 	FILE *fp,
 3063: 	struct info_if_stats *ifs,
 3064: 	int items,
 3065: 	int itemsize,
 3066: 	int res
 3067: 	)
 3068: {
 3069: 	static char *actions = "?.+-";
 3070: 	sockaddr_u saddr;
 3071: 
 3072: 	if (res != 0)
 3073: 	    return;
 3074: 
 3075: 	if (!checkitems(items, fp))
 3076: 	    return;
 3077: 
 3078: 	if (!checkitemsize(itemsize, sizeof(struct info_if_stats)))
 3079: 	    return;
 3080: 
 3081: 	fprintf(fp, IF_LIST_FMT_STR, IF_LIST_LABELS);
 3082: 	fprintf(fp, IF_LIST_LINE);
 3083: 	
 3084: 	while (items > 0) {
 3085: 		SET_ADDR(saddr, ntohl(ifs->v6_flag), 
 3086: 			 ifs->unaddr.addr.s_addr, ifs->unaddr.addr6);
 3087: 		fprintf(fp, IF_LIST_FMT,
 3088: 			ntohl(ifs->ifnum),
 3089: 			actions[(ifs->action >= 1 && ifs->action < 4) ? ifs->action : 0],
 3090: 			stoa((&saddr)), 'A',
 3091: 			ifs->ignore_packets ? 'D' : 'E',
 3092: 			ifs->name,
 3093: 			(u_long)ntohl(ifs->flags),
 3094: 			(u_long)ntohl(ifs->last_ttl),
 3095: 			(u_long)ntohl(ifs->num_mcast),
 3096: 			(u_long)ntohl(ifs->received),
 3097: 			(u_long)ntohl(ifs->sent),
 3098: 			(u_long)ntohl(ifs->notsent),
 3099: 			(u_long)ntohl(ifs->scopeid),
 3100: 			(u_long)ntohl(ifs->peercnt),
 3101: 			(u_long)ntohl(ifs->uptime));
 3102: 
 3103: 		SET_ADDR(saddr, ntohl(ifs->v6_flag), 
 3104: 			 ifs->unmask.addr.s_addr, ifs->unmask.addr6);
 3105: 		fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'M');
 3106: 
 3107: 		if (!ntohl(ifs->v6_flag) && ntohl(ifs->flags) & (INT_BCASTOPEN)) {
 3108: 			SET_ADDR(saddr, ntohl(ifs->v6_flag), 
 3109: 				 ifs->unbcast.addr.s_addr, ifs->unbcast.addr6);
 3110: 			fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'B');
 3111: 
 3112: 		}
 3113: 
 3114: 		ifs++;
 3115: 		items--;
 3116: 	}
 3117: }
 3118: 
 3119: /*ARGSUSED*/
 3120: static void
 3121: get_if_stats(
 3122: 	struct parse *pcmd,
 3123: 	FILE *fp
 3124: 	)
 3125: {
 3126: 	struct info_if_stats *ifs;
 3127: 	int items;
 3128: 	int itemsize;
 3129: 	int res;
 3130: 
 3131: 	res = doquery(impl_ver, REQ_IF_STATS, 1, 0, 0, (char *)NULL, &items,
 3132: 		      &itemsize, (void *)&ifs, 0, 
 3133: 		      sizeof(struct info_if_stats));
 3134: 	iflist(fp, ifs, items, itemsize, res);
 3135: }
 3136: 
 3137: /*ARGSUSED*/
 3138: static void
 3139: do_if_reload(
 3140: 	struct parse *pcmd,
 3141: 	FILE *fp
 3142: 	)
 3143: {
 3144: 	struct info_if_stats *ifs;
 3145: 	int items;
 3146: 	int itemsize;
 3147: 	int res;
 3148: 
 3149: 	res = doquery(impl_ver, REQ_IF_RELOAD, 1, 0, 0, (char *)NULL, &items,
 3150: 		      &itemsize, (void *)&ifs, 0, 
 3151: 		      sizeof(struct info_if_stats));
 3152: 	iflist(fp, ifs, items, itemsize, res);
 3153: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>