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