PageRenderTime 138ms CodeModel.GetById 29ms app.highlight 95ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/ntp/ntpd/ntp_request.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2913 lines | 2219 code | 305 blank | 389 comment | 397 complexity | 9858527709641a8baeefc751e99f2ed7 MD5 | raw file

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

   1/*
   2 * ntp_request.c - respond to information requests
   3 */
   4
   5#ifdef HAVE_CONFIG_H
   6# include <config.h>
   7#endif
   8
   9#include "ntpd.h"
  10#include "ntp_io.h"
  11#include "ntp_request.h"
  12#include "ntp_control.h"
  13#include "ntp_refclock.h"
  14#include "ntp_if.h"
  15#include "ntp_stdlib.h"
  16
  17#include <stdio.h>
  18#include <stddef.h>
  19#include <signal.h>
  20#include <netinet/in.h>
  21#include <arpa/inet.h>
  22
  23#include "recvbuff.h"
  24
  25#ifdef KERNEL_PLL
  26#include "ntp_syscall.h"
  27#endif /* KERNEL_PLL */
  28
  29/*
  30 * Structure to hold request procedure information
  31 */
  32#define	NOAUTH	0
  33#define	AUTH	1
  34
  35#define	NO_REQUEST	(-1)
  36/*
  37 * Because we now have v6 addresses in the messages, we need to compensate
  38 * for the larger size.  Therefore, we introduce the alternate size to 
  39 * keep us friendly with older implementations.  A little ugly.
  40 */
  41static int client_v6_capable = 0;   /* the client can handle longer messages */
  42
  43#define v6sizeof(type)	(client_v6_capable ? sizeof(type) : v4sizeof(type))
  44
  45struct req_proc {
  46	short request_code;	/* defined request code */
  47	short needs_auth;	/* true when authentication needed */
  48	short sizeofitem;	/* size of request data item (older size)*/
  49	short v6_sizeofitem;	/* size of request data item (new size)*/
  50	void (*handler) P((struct sockaddr_storage *, struct interface *,
  51			   struct req_pkt *));	/* routine to handle request */
  52};
  53
  54/*
  55 * Universal request codes
  56 */
  57static	struct req_proc univ_codes[] = {
  58	{ NO_REQUEST,		NOAUTH,	 0,	0 }
  59};
  60
  61static	void	req_ack	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
  62static	char *	prepare_pkt	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int));
  63static	char *	more_pkt	P((void));
  64static	void	flush_pkt	P((void));
  65static	void	peer_list	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  66static	void	peer_list_sum	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  67static	void	peer_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  68static	void	peer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  69static	void	sys_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  70static	void	sys_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  71static	void	mem_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  72static	void	io_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  73static	void	timer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  74static	void	loop_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  75static	void	do_conf		P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  76static	void	do_unconf	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  77static	void	set_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  78static	void	clr_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  79static	void	setclr_flags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
  80static	void	list_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  81static	void	do_resaddflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  82static	void	do_ressubflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  83static	void	do_unrestrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  84static	void	do_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
  85static	void	mon_getlist_0	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  86static	void	mon_getlist_1	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  87static	void	reset_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  88static	void	reset_peer	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  89static	void	do_key_reread	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  90static	void	trust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  91static	void	untrust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  92static	void	do_trustkey	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
  93static	void	get_auth_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  94static	void	reset_auth_stats P((void));
  95static	void	req_get_traps	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  96static	void	req_set_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  97static	void	req_clr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
  98static	void	do_setclr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
  99static	void	set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 100static	void	set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 101static	void	get_ctl_stats   P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 102static	void	get_if_stats    P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 103static	void	do_if_reload    P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 104#ifdef KERNEL_PLL
 105static	void	get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 106#endif /* KERNEL_PLL */
 107#ifdef REFCLOCK
 108static	void	get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 109static	void	set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 110#endif	/* REFCLOCK */
 111#ifdef REFCLOCK
 112static	void	get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
 113#endif	/* REFCLOCK */
 114
 115/*
 116 * ntpd request codes
 117 */
 118static	struct req_proc ntp_codes[] = {
 119	{ REQ_PEER_LIST,	NOAUTH,	0, 0,	peer_list },
 120	{ REQ_PEER_LIST_SUM,	NOAUTH,	0, 0,	peer_list_sum },
 121	{ REQ_PEER_INFO,    NOAUTH, v4sizeof(struct info_peer_list),
 122				sizeof(struct info_peer_list), peer_info},
 123	{ REQ_PEER_STATS,   NOAUTH, v4sizeof(struct info_peer_list),
 124				sizeof(struct info_peer_list), peer_stats},
 125	{ REQ_SYS_INFO,		NOAUTH,	0, 0,	sys_info },
 126	{ REQ_SYS_STATS,	NOAUTH,	0, 0,	sys_stats },
 127	{ REQ_IO_STATS,		NOAUTH,	0, 0,	io_stats },
 128	{ REQ_MEM_STATS,	NOAUTH,	0, 0,	mem_stats },
 129	{ REQ_LOOP_INFO,	NOAUTH,	0, 0,	loop_info },
 130	{ REQ_TIMER_STATS,	NOAUTH,	0, 0,	timer_stats },
 131	{ REQ_CONFIG,	    AUTH, v4sizeof(struct conf_peer),
 132				sizeof(struct conf_peer), do_conf },
 133	{ REQ_UNCONFIG,	    AUTH, v4sizeof(struct conf_unpeer),
 134				sizeof(struct conf_unpeer), do_unconf },
 135	{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
 136				sizeof(struct conf_sys_flags), set_sys_flag },
 137	{ REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 
 138				sizeof(struct conf_sys_flags),  clr_sys_flag },
 139	{ REQ_GET_RESTRICT,	NOAUTH,	0, 0,	list_restrict },
 140	{ REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),
 141				sizeof(struct conf_restrict), do_resaddflags },
 142	{ REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),
 143				sizeof(struct conf_restrict), do_ressubflags },
 144	{ REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),
 145				sizeof(struct conf_restrict), do_unrestrict },
 146	{ REQ_MON_GETLIST,	NOAUTH,	0, 0,	mon_getlist_0 },
 147	{ REQ_MON_GETLIST_1,	NOAUTH,	0, 0,	mon_getlist_1 },
 148	{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },
 149	{ REQ_RESET_PEER,  AUTH, v4sizeof(struct conf_unpeer),
 150				sizeof(struct conf_unpeer), reset_peer },
 151	{ REQ_REREAD_KEYS,	AUTH,	0, 0,	do_key_reread },
 152	{ REQ_TRUSTKEY,   AUTH, sizeof(u_long), sizeof(u_long), trust_key },
 153	{ REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },
 154	{ REQ_AUTHINFO,		NOAUTH,	0, 0,	get_auth_info },
 155	{ REQ_TRAPS,		NOAUTH, 0, 0,	req_get_traps },
 156	{ REQ_ADD_TRAP,	AUTH, v4sizeof(struct conf_trap),
 157				sizeof(struct conf_trap), req_set_trap },
 158	{ REQ_CLR_TRAP,	AUTH, v4sizeof(struct conf_trap),
 159				sizeof(struct conf_trap), req_clr_trap },
 160	{ REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 
 161				set_request_keyid },
 162	{ REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 
 163				set_control_keyid },
 164	{ REQ_GET_CTLSTATS,	NOAUTH,	0, 0,	get_ctl_stats },
 165#ifdef KERNEL_PLL
 166	{ REQ_GET_KERNEL,	NOAUTH,	0, 0,	get_kernel_info },
 167#endif
 168#ifdef REFCLOCK
 169	{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 
 170				get_clock_info },
 171	{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 
 172				sizeof(struct conf_fudge), set_clock_fudge },
 173	{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
 174				get_clkbug_info },
 175#endif
 176	{ REQ_IF_STATS,		AUTH, 0, 0,	get_if_stats },
 177	{ REQ_IF_RELOAD,        AUTH, 0, 0,	do_if_reload },
 178
 179	{ NO_REQUEST,		NOAUTH,	0, 0,	0 }
 180};
 181
 182
 183/*
 184 * Authentication keyid used to authenticate requests.  Zero means we
 185 * don't allow writing anything.
 186 */
 187keyid_t info_auth_keyid;
 188
 189/*
 190 * Statistic counters to keep track of requests and responses.
 191 */
 192u_long numrequests;		/* number of requests we've received */
 193u_long numresppkts;		/* number of resp packets sent with data */
 194
 195u_long errorcounter[INFO_ERR_AUTH+1];	/* lazy way to count errors, indexed */
 196/* by the error code */
 197
 198/*
 199 * A hack.  To keep the authentication module clear of ntp-ism's, we
 200 * include a time reset variable for its stats here.
 201 */
 202static u_long auth_timereset;
 203
 204/*
 205 * Response packet used by these routines.  Also some state information
 206 * so that we can handle packet formatting within a common set of
 207 * subroutines.  Note we try to enter data in place whenever possible,
 208 * but the need to set the more bit correctly means we occasionally
 209 * use the extra buffer and copy.
 210 */
 211static struct resp_pkt rpkt;
 212static int reqver;
 213static int seqno;
 214static int nitems;
 215static int itemsize;
 216static int databytes;
 217static char exbuf[RESP_DATA_SIZE];
 218static int usingexbuf;
 219static struct sockaddr_storage *toaddr;
 220static struct interface *frominter;
 221
 222/*
 223 * init_request - initialize request data
 224 */
 225void
 226init_request (void)
 227{
 228	int i;
 229
 230	numrequests = 0;
 231	numresppkts = 0;
 232	auth_timereset = 0;
 233	info_auth_keyid = 0;	/* by default, can't do this */
 234
 235	for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
 236	    errorcounter[i] = 0;
 237}
 238
 239
 240/*
 241 * req_ack - acknowledge request with no data
 242 */
 243static void
 244req_ack(
 245	struct sockaddr_storage *srcadr,
 246	struct interface *inter,
 247	struct req_pkt *inpkt,
 248	int errcode
 249	)
 250{
 251	/*
 252	 * fill in the fields
 253	 */
 254	rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
 255	rpkt.auth_seq = AUTH_SEQ(0, 0);
 256	rpkt.implementation = inpkt->implementation;
 257	rpkt.request = inpkt->request;
 258	rpkt.err_nitems = ERR_NITEMS(errcode, 0);
 259	rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
 260
 261	/*
 262	 * send packet and bump counters
 263	 */
 264	sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
 265	errorcounter[errcode]++;
 266}
 267
 268
 269/*
 270 * prepare_pkt - prepare response packet for transmission, return pointer
 271 *		 to storage for data item.
 272 */
 273static char *
 274prepare_pkt(
 275	struct sockaddr_storage *srcadr,
 276	struct interface *inter,
 277	struct req_pkt *pkt,
 278	u_int structsize
 279	)
 280{
 281#ifdef DEBUG
 282	if (debug > 3)
 283	    printf("request: preparing pkt\n");
 284#endif
 285
 286	/*
 287	 * Fill in the implementation, request and itemsize fields
 288	 * since these won't change.
 289	 */
 290	rpkt.implementation = pkt->implementation;
 291	rpkt.request = pkt->request;
 292	rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
 293
 294	/*
 295	 * Compute the static data needed to carry on.
 296	 */
 297	toaddr = srcadr;
 298	frominter = inter;
 299	seqno = 0;
 300	nitems = 0;
 301	itemsize = structsize;
 302	databytes = 0;
 303	usingexbuf = 0;
 304
 305	/*
 306	 * return the beginning of the packet buffer.
 307	 */
 308	return &rpkt.data[0];
 309}
 310
 311
 312/*
 313 * more_pkt - return a data pointer for a new item.
 314 */
 315static char *
 316more_pkt(void)
 317{
 318	/*
 319	 * If we were using the extra buffer, send the packet.
 320	 */
 321	if (usingexbuf) {
 322#ifdef DEBUG
 323		if (debug > 2)
 324		    printf("request: sending pkt\n");
 325#endif
 326		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
 327		rpkt.auth_seq = AUTH_SEQ(0, seqno);
 328		rpkt.err_nitems = htons((u_short)nitems);
 329		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
 330			RESP_HEADER_SIZE+databytes);
 331		numresppkts++;
 332
 333		/*
 334		 * Copy data out of exbuf into the packet.
 335		 */
 336		memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);
 337		seqno++;
 338		databytes = 0;
 339		nitems = 0;
 340		usingexbuf = 0;
 341	}
 342
 343	databytes += itemsize;
 344	nitems++;
 345	if (databytes + itemsize <= RESP_DATA_SIZE) {
 346#ifdef DEBUG
 347		if (debug > 3)
 348		    printf("request: giving him more data\n");
 349#endif
 350		/*
 351		 * More room in packet.  Give him the
 352		 * next address.
 353		 */
 354		return &rpkt.data[databytes];
 355	} else {
 356		/*
 357		 * No room in packet.  Give him the extra
 358		 * buffer unless this was the last in the sequence.
 359		 */
 360#ifdef DEBUG
 361		if (debug > 3)
 362		    printf("request: into extra buffer\n");
 363#endif
 364		if (seqno == MAXSEQ)
 365		    return (char *)0;
 366		else {
 367			usingexbuf = 1;
 368			return exbuf;
 369		}
 370	}
 371}
 372
 373
 374/*
 375 * flush_pkt - we're done, return remaining information.
 376 */
 377static void
 378flush_pkt(void)
 379{
 380#ifdef DEBUG
 381	if (debug > 2)
 382	    printf("request: flushing packet, %d items\n", nitems);
 383#endif
 384	/*
 385	 * Must send the last packet.  If nothing in here and nothing
 386	 * has been sent, send an error saying no data to be found.
 387	 */
 388	if (seqno == 0 && nitems == 0)
 389	    req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
 390		    INFO_ERR_NODATA);
 391	else {
 392		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
 393		rpkt.auth_seq = AUTH_SEQ(0, seqno);
 394		rpkt.err_nitems = htons((u_short)nitems);
 395		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
 396			RESP_HEADER_SIZE+databytes);
 397		numresppkts++;
 398	}
 399}
 400
 401
 402
 403/*
 404 * process_private - process private mode (7) packets
 405 */
 406void
 407process_private(
 408	struct recvbuf *rbufp,
 409	int mod_okay
 410	)
 411{
 412	static u_long quiet_until;
 413	struct req_pkt *inpkt;
 414	struct req_pkt_tail *tailinpkt;
 415	struct sockaddr_storage *srcadr;
 416	struct interface *inter;
 417	struct req_proc *proc;
 418	int ec;
 419	short temp_size;
 420
 421	/*
 422	 * Initialize pointers, for convenience
 423	 */
 424	inpkt = (struct req_pkt *)&rbufp->recv_pkt;
 425	srcadr = &rbufp->recv_srcadr;
 426	inter = rbufp->dstadr;
 427
 428#ifdef DEBUG
 429	if (debug > 2)
 430	    printf("process_private: impl %d req %d\n",
 431		   inpkt->implementation, inpkt->request);
 432#endif
 433
 434	/*
 435	 * Do some sanity checks on the packet.  Return a format
 436	 * error if it fails.
 437	 */
 438	ec = 0;
 439	if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))
 440	    || (++ec, ISMORE(inpkt->rm_vn_mode))
 441	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
 442	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
 443	    || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
 444	    || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
 445	    || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
 446	    || (++ec, rbufp->recv_length < REQ_LEN_HDR)
 447		) {
 448		NLOG(NLOG_SYSEVENT)
 449			if (current_time >= quiet_until) {
 450				msyslog(LOG_ERR,
 451					"process_private: drop test %d"
 452					" failed, pkt from %s",
 453					ec, stoa(srcadr));
 454				quiet_until = current_time + 60;
 455			}
 456		return;
 457	}
 458
 459	reqver = INFO_VERSION(inpkt->rm_vn_mode);
 460
 461	/*
 462	 * Get the appropriate procedure list to search.
 463	 */
 464	if (inpkt->implementation == IMPL_UNIV)
 465	    proc = univ_codes;
 466	else if ((inpkt->implementation == IMPL_XNTPD) ||
 467		 (inpkt->implementation == IMPL_XNTPD_OLD))
 468	    proc = ntp_codes;
 469	else {
 470		req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
 471		return;
 472	}
 473
 474	/*
 475	 * Search the list for the request codes.  If it isn't one
 476	 * we know, return an error.
 477	 */
 478	while (proc->request_code != NO_REQUEST) {
 479		if (proc->request_code == (short) inpkt->request)
 480		    break;
 481		proc++;
 482	}
 483	if (proc->request_code == NO_REQUEST) {
 484		req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
 485		return;
 486	}
 487
 488#ifdef DEBUG
 489	if (debug > 3)
 490	    printf("found request in tables\n");
 491#endif
 492
 493	/*
 494	 * If we need data, check to see if we have some.  If we
 495	 * don't, check to see that there is none (picky, picky).
 496	 */	
 497
 498	/* This part is a bit tricky, we want to be sure that the size
 499	 * returned is either the old or the new size.  We also can find
 500	 * out if the client can accept both types of messages this way. 
 501	 *
 502	 * Handle the exception of REQ_CONFIG. It can have two data sizes.
 503	 */
 504	temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);
 505	if ((temp_size != proc->sizeofitem &&
 506	     temp_size != proc->v6_sizeofitem) &&
 507	    !(inpkt->implementation == IMPL_XNTPD &&
 508	      inpkt->request == REQ_CONFIG &&
 509	      temp_size == sizeof(struct old_conf_peer))) {
 510#ifdef DEBUG
 511		if (debug > 2)
 512			printf("process_private: wrong item size, received %d, should be %d or %d\n",
 513			    temp_size, proc->sizeofitem, proc->v6_sizeofitem);
 514#endif
 515		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 516		return;
 517	}
 518	if ((proc->sizeofitem != 0) &&
 519	    ((temp_size * INFO_NITEMS(inpkt->err_nitems)) >
 520	    (rbufp->recv_length - REQ_LEN_HDR))) {
 521#ifdef DEBUG
 522		if (debug > 2)
 523			printf("process_private: not enough data\n");
 524#endif
 525		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 526		return;
 527	}
 528
 529	switch (inpkt->implementation) {
 530	case IMPL_XNTPD:
 531		client_v6_capable = 1;
 532		break;
 533	case IMPL_XNTPD_OLD:
 534		client_v6_capable = 0;
 535		break;
 536	default:
 537		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 538		return;
 539	}
 540
 541	/*
 542	 * If we need to authenticate, do so.  Note that an
 543	 * authenticatable packet must include a mac field, must
 544	 * have used key info_auth_keyid and must have included
 545	 * a time stamp in the appropriate field.  The time stamp
 546	 * must be within INFO_TS_MAXSKEW of the receive
 547	 * time stamp.
 548	 */
 549	if (proc->needs_auth && sys_authenticate) {
 550		l_fp ftmp;
 551		double dtemp;
 552	
 553		if (rbufp->recv_length < (int)((REQ_LEN_HDR +
 554		    (INFO_ITEMSIZE(inpkt->mbz_itemsize) *
 555		    INFO_NITEMS(inpkt->err_nitems))
 556		    + sizeof(struct req_pkt_tail)))) {
 557			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 558		}
 559		tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt +
 560		    rbufp->recv_length - sizeof(struct req_pkt_tail));
 561
 562		/*
 563		 * If this guy is restricted from doing this, don't let him
 564		 * If wrong key was used, or packet doesn't have mac, return.
 565		 */
 566		if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0
 567		    || ntohl(tailinpkt->keyid) != info_auth_keyid) {
 568#ifdef DEBUG
 569			if (debug > 4)
 570			    printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
 571				   INFO_IS_AUTH(inpkt->auth_seq),
 572				   (u_long)info_auth_keyid,
 573				   (u_long)ntohl(tailinpkt->keyid));
 574			msyslog(LOG_DEBUG,
 575				"process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
 576				INFO_IS_AUTH(inpkt->auth_seq),
 577				(u_long)info_auth_keyid,
 578				(u_long)ntohl(tailinpkt->keyid));
 579#endif
 580			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
 581			return;
 582		}
 583		if (rbufp->recv_length > REQ_LEN_MAC) {
 584#ifdef DEBUG
 585			if (debug > 4)
 586			    printf("bad pkt length %d\n",
 587				   rbufp->recv_length);
 588#endif
 589			msyslog(LOG_ERR, "process_private: bad pkt length %d",
 590				rbufp->recv_length);
 591			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
 592			return;
 593		}
 594		if (!mod_okay || !authhavekey(info_auth_keyid)) {
 595#ifdef DEBUG
 596			if (debug > 4)
 597			    printf("failed auth mod_okay %d\n", mod_okay);
 598			msyslog(LOG_DEBUG,
 599				"process_private: failed auth mod_okay %d\n",
 600				mod_okay);
 601#endif
 602			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
 603			return;
 604		}
 605
 606		/*
 607		 * calculate absolute time difference between xmit time stamp
 608		 * and receive time stamp.  If too large, too bad.
 609		 */
 610		NTOHL_FP(&tailinpkt->tstamp, &ftmp);
 611		L_SUB(&ftmp, &rbufp->recv_time);
 612		LFPTOD(&ftmp, dtemp);
 613		if (fabs(dtemp) >= INFO_TS_MAXSKEW) {
 614			/*
 615			 * He's a loser.  Tell him.
 616			 */
 617#ifdef DEBUG
 618			if (debug > 4)
 619			    printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n");
 620#endif
 621			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
 622			return;
 623		}
 624
 625		/*
 626		 * So far so good.  See if decryption works out okay.
 627		 */
 628		if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
 629		    rbufp->recv_length - sizeof(struct req_pkt_tail) +
 630		    REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) {
 631#ifdef DEBUG
 632			if (debug > 4)
 633			    printf("authdecrypt failed\n");
 634#endif
 635			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
 636			return;
 637		}
 638	}
 639
 640#ifdef DEBUG
 641	if (debug > 3)
 642	    printf("process_private: all okay, into handler\n");
 643#endif
 644
 645	/*
 646	 * Packet is okay.  Call the handler to send him data.
 647	 */
 648	(proc->handler)(srcadr, inter, inpkt);
 649}
 650
 651
 652/*
 653 * peer_list - send a list of the peers
 654 */
 655static void
 656peer_list(
 657	struct sockaddr_storage *srcadr,
 658	struct interface *inter,
 659	struct req_pkt *inpkt
 660	)
 661{
 662	register struct info_peer_list *ip;
 663	register struct peer *pp;
 664	register int i;
 665	register int skip = 0;
 666
 667	ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
 668	    v6sizeof(struct info_peer_list));
 669	for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) {
 670		pp = peer_hash[i];
 671		while (pp != 0 && ip != 0) {
 672			if (pp->srcadr.ss_family == AF_INET6) {
 673				if (client_v6_capable) {
 674					ip->addr6 = GET_INADDR6(pp->srcadr);
 675					ip->v6_flag = 1;
 676					skip = 0;
 677				} else {
 678					skip = 1;
 679					break;
 680				}
 681			} else {
 682				ip->addr = GET_INADDR(pp->srcadr);
 683				if (client_v6_capable)
 684					ip->v6_flag = 0;
 685				skip = 0;
 686			}
 687
 688			if(!skip) {
 689				ip->port = NSRCPORT(&pp->srcadr);
 690				ip->hmode = pp->hmode;
 691				ip->flags = 0;
 692				if (pp->flags & FLAG_CONFIG)
 693				    ip->flags |= INFO_FLAG_CONFIG;
 694				if (pp == sys_peer)
 695				    ip->flags |= INFO_FLAG_SYSPEER;
 696				if (pp->status == CTL_PST_SEL_SYNCCAND)
 697				    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
 698				if (pp->status >= CTL_PST_SEL_SYSPEER)
 699				    ip->flags |= INFO_FLAG_SHORTLIST;
 700				ip = (struct info_peer_list *)more_pkt();
 701			}
 702			pp = pp->next; 
 703		}
 704	}
 705	flush_pkt();
 706}
 707
 708
 709/*
 710 * peer_list_sum - return extended peer list
 711 */
 712static void
 713peer_list_sum(
 714	struct sockaddr_storage *srcadr,
 715	struct interface *inter,
 716	struct req_pkt *inpkt
 717	)
 718{
 719	register struct info_peer_summary *ips;
 720	register struct peer *pp;
 721	register int i;
 722	l_fp ltmp;
 723	register int skip;
 724
 725#ifdef DEBUG
 726	if (debug > 2)
 727	    printf("wants peer list summary\n");
 728#endif
 729	ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
 730	    v6sizeof(struct info_peer_summary));
 731	for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) {
 732		pp = peer_hash[i];
 733		while (pp != 0 && ips != 0) {
 734#ifdef DEBUG
 735			if (debug > 3)
 736			    printf("sum: got one\n");
 737#endif
 738			/*
 739			 * Be careful here not to return v6 peers when we
 740			 * want only v4.
 741			 */
 742			if (pp->srcadr.ss_family == AF_INET6) {
 743				if (client_v6_capable) {
 744					ips->srcadr6 = GET_INADDR6(pp->srcadr);
 745					ips->v6_flag = 1;
 746					if (pp->dstadr)
 747						ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
 748					else
 749						memset(&ips->dstadr6, 0, sizeof(ips->dstadr6));
 750					skip = 0;
 751				} else {
 752					skip = 1;
 753					break;
 754				}
 755			} else {
 756				ips->srcadr = GET_INADDR(pp->srcadr);
 757				if (client_v6_capable)
 758					ips->v6_flag = 0;
 759/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
 760				
 761				if (pp->dstadr)
 762					ips->dstadr = (pp->processed) ?
 763						pp->cast_flags == MDF_BCAST ?
 764						GET_INADDR(pp->dstadr->bcast):
 765						pp->cast_flags ?
 766						GET_INADDR(pp->dstadr->sin) ?
 767						GET_INADDR(pp->dstadr->sin):
 768						GET_INADDR(pp->dstadr->bcast):
 769						1 : GET_INADDR(pp->dstadr->sin);
 770				else
 771						memset(&ips->dstadr, 0, sizeof(ips->dstadr));
 772
 773				skip = 0;
 774			}
 775			
 776			if (!skip){ 
 777				ips->srcport = NSRCPORT(&pp->srcadr);
 778				ips->stratum = pp->stratum;
 779				ips->hpoll = pp->hpoll;
 780				ips->ppoll = pp->ppoll;
 781				ips->reach = pp->reach;
 782				ips->flags = 0;
 783				if (pp == sys_peer)
 784				    ips->flags |= INFO_FLAG_SYSPEER;
 785				if (pp->flags & FLAG_CONFIG)
 786				    ips->flags |= INFO_FLAG_CONFIG;
 787				if (pp->flags & FLAG_REFCLOCK)
 788				    ips->flags |= INFO_FLAG_REFCLOCK;
 789				if (pp->flags & FLAG_AUTHENABLE)
 790				    ips->flags |= INFO_FLAG_AUTHENABLE;
 791				if (pp->flags & FLAG_PREFER)
 792				    ips->flags |= INFO_FLAG_PREFER;
 793				if (pp->flags & FLAG_BURST)
 794				    ips->flags |= INFO_FLAG_BURST;
 795				if (pp->status == CTL_PST_SEL_SYNCCAND)
 796				    ips->flags |= INFO_FLAG_SEL_CANDIDATE;
 797				if (pp->status >= CTL_PST_SEL_SYSPEER)
 798				    ips->flags |= INFO_FLAG_SHORTLIST;
 799				ips->hmode = pp->hmode;
 800				ips->delay = HTONS_FP(DTOFP(pp->delay));
 801				DTOLFP(pp->offset, &ltmp);
 802				HTONL_FP(&ltmp, &ips->offset);
 803				ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
 804			}	
 805			pp = pp->next; 
 806			ips = (struct info_peer_summary *)more_pkt();
 807		}
 808	}
 809	flush_pkt();
 810}
 811
 812
 813/*
 814 * peer_info - send information for one or more peers
 815 */
 816static void
 817peer_info (
 818	struct sockaddr_storage *srcadr,
 819	struct interface *inter,
 820	struct req_pkt *inpkt
 821	)
 822{
 823	register struct info_peer_list *ipl;
 824	register struct peer *pp;
 825	register struct info_peer *ip;
 826	register int items;
 827	register int i, j;
 828	struct sockaddr_storage addr;
 829	extern struct peer *sys_peer;
 830	l_fp ltmp;
 831
 832	memset((char *)&addr, 0, sizeof addr);
 833	items = INFO_NITEMS(inpkt->err_nitems);
 834	ipl = (struct info_peer_list *) inpkt->data;
 835
 836	ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
 837	    v6sizeof(struct info_peer));
 838	while (items-- > 0 && ip != 0) {
 839		memset((char *)&addr, 0, sizeof(addr));
 840		NSRCPORT(&addr) = ipl->port;
 841		if (client_v6_capable && ipl->v6_flag != 0) {
 842			addr.ss_family = AF_INET6;
 843			GET_INADDR6(addr) = ipl->addr6;
 844		} else {
 845			addr.ss_family = AF_INET;
 846			GET_INADDR(addr) = ipl->addr;
 847		}
 848#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 849		addr.ss_len = SOCKLEN(&addr);
 850#endif
 851		ipl++;
 852		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
 853		    continue;
 854		if (pp->srcadr.ss_family == AF_INET6) {
 855			if (pp->dstadr)
 856				ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
 857					GET_INADDR6(pp->dstadr->bcast) :
 858					GET_INADDR6(pp->dstadr->sin);
 859			else
 860				memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
 861
 862			ip->srcadr6 = GET_INADDR6(pp->srcadr);
 863			ip->v6_flag = 1;
 864		} else {
 865/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
 866			if (pp->dstadr)
 867				ip->dstadr = (pp->processed) ?
 868					pp->cast_flags == MDF_BCAST ?
 869					GET_INADDR(pp->dstadr->bcast):
 870					pp->cast_flags ?
 871					GET_INADDR(pp->dstadr->sin) ?
 872					GET_INADDR(pp->dstadr->sin):
 873					GET_INADDR(pp->dstadr->bcast):
 874					2 : GET_INADDR(pp->dstadr->sin);
 875			else
 876				memset(&ip->dstadr, 0, sizeof(ip->dstadr));
 877
 878			ip->srcadr = GET_INADDR(pp->srcadr);
 879			if (client_v6_capable)
 880				ip->v6_flag = 0;
 881		}
 882		ip->srcport = NSRCPORT(&pp->srcadr);
 883		ip->flags = 0;
 884		if (pp == sys_peer)
 885		    ip->flags |= INFO_FLAG_SYSPEER;
 886		if (pp->flags & FLAG_CONFIG)
 887		    ip->flags |= INFO_FLAG_CONFIG;
 888		if (pp->flags & FLAG_REFCLOCK)
 889		    ip->flags |= INFO_FLAG_REFCLOCK;
 890		if (pp->flags & FLAG_AUTHENABLE)
 891		    ip->flags |= INFO_FLAG_AUTHENABLE;
 892		if (pp->flags & FLAG_PREFER)
 893		    ip->flags |= INFO_FLAG_PREFER;
 894		if (pp->flags & FLAG_BURST)
 895		    ip->flags |= INFO_FLAG_BURST;
 896		if (pp->status == CTL_PST_SEL_SYNCCAND)
 897		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
 898		if (pp->status >= CTL_PST_SEL_SYSPEER)
 899		    ip->flags |= INFO_FLAG_SHORTLIST;
 900		ip->leap = pp->leap;
 901		ip->hmode = pp->hmode;
 902		ip->keyid = pp->keyid;
 903		ip->stratum = pp->stratum;
 904		ip->ppoll = pp->ppoll;
 905		ip->hpoll = pp->hpoll;
 906		ip->precision = pp->precision;
 907		ip->version = pp->version;
 908		ip->reach = pp->reach;
 909		ip->unreach = (u_char) pp->unreach;
 910		ip->flash = (u_char)pp->flash;
 911		ip->flash2 = (u_short) pp->flash;
 912		ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
 913		ip->ttl = pp->ttl;
 914		ip->associd = htons(pp->associd);
 915		ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
 916		ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion));
 917		ip->refid = pp->refid;
 918		HTONL_FP(&pp->reftime, &ip->reftime);
 919		HTONL_FP(&pp->org, &ip->org);
 920		HTONL_FP(&pp->rec, &ip->rec);
 921		HTONL_FP(&pp->xmt, &ip->xmt);
 922		j = pp->filter_nextpt - 1;
 923		for (i = 0; i < NTP_SHIFT; i++, j--) {
 924			if (j < 0)
 925			    j = NTP_SHIFT-1;
 926			ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
 927			DTOLFP(pp->filter_offset[j], &ltmp);
 928			HTONL_FP(&ltmp, &ip->filtoffset[i]);
 929			ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1)
 930				- pp->filter_order[i]);
 931			if (ip->order[i] >= NTP_SHIFT)
 932			    ip->order[i] -= NTP_SHIFT;
 933		}
 934		DTOLFP(pp->offset, &ltmp);
 935		HTONL_FP(&ltmp, &ip->offset);
 936		ip->delay = HTONS_FP(DTOFP(pp->delay));
 937		ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
 938		ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
 939		ip = (struct info_peer *)more_pkt();
 940	}
 941	flush_pkt();
 942}
 943
 944
 945/*
 946 * peer_stats - send statistics for one or more peers
 947 */
 948static void
 949peer_stats (
 950	struct sockaddr_storage *srcadr,
 951	struct interface *inter,
 952	struct req_pkt *inpkt
 953	)
 954{
 955	register struct info_peer_list *ipl;
 956	register struct peer *pp;
 957	register struct info_peer_stats *ip;
 958	register int items;
 959	struct sockaddr_storage addr;
 960	extern struct peer *sys_peer;
 961
 962#ifdef DEBUG
 963	if (debug)
 964	     printf("peer_stats: called\n");
 965#endif
 966	items = INFO_NITEMS(inpkt->err_nitems);
 967	ipl = (struct info_peer_list *) inpkt->data;
 968	ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
 969	    v6sizeof(struct info_peer_stats));
 970	while (items-- > 0 && ip != 0) {
 971		memset((char *)&addr, 0, sizeof(addr));
 972		NSRCPORT(&addr) = ipl->port;
 973		if (client_v6_capable && ipl->v6_flag) {
 974			addr.ss_family = AF_INET6;
 975			GET_INADDR6(addr) = ipl->addr6;
 976		} else {
 977			addr.ss_family = AF_INET;
 978			GET_INADDR(addr) = ipl->addr;
 979		}	
 980#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
 981		addr.ss_len = SOCKLEN(&addr);
 982#endif
 983#ifdef DEBUG
 984		if (debug)
 985		    printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
 986		    ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);
 987#endif
 988		ipl = (struct info_peer_list *)((char *)ipl +
 989		    INFO_ITEMSIZE(inpkt->mbz_itemsize));
 990
 991		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
 992		    continue;
 993#ifdef DEBUG
 994		if (debug)
 995		     printf("peer_stats: found %s\n", stoa(&addr));
 996#endif
 997		if (pp->srcadr.ss_family == AF_INET) {
 998			if (pp->dstadr)
 999				ip->dstadr = (pp->processed) ?
1000					pp->cast_flags == MDF_BCAST ?
1001					GET_INADDR(pp->dstadr->bcast):
1002					pp->cast_flags ?
1003					GET_INADDR(pp->dstadr->sin) ?
1004					GET_INADDR(pp->dstadr->sin):
1005					GET_INADDR(pp->dstadr->bcast):
1006					3 : 7;
1007			else
1008				memset(&ip->dstadr, 0, sizeof(ip->dstadr));
1009			
1010			ip->srcadr = GET_INADDR(pp->srcadr);
1011			if (client_v6_capable)
1012				ip->v6_flag = 0;
1013		} else {
1014			if (pp->dstadr)
1015				ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
1016					GET_INADDR6(pp->dstadr->bcast):
1017					GET_INADDR6(pp->dstadr->sin);
1018			else
1019				memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
1020			
1021			ip->srcadr6 = GET_INADDR6(pp->srcadr);
1022			ip->v6_flag = 1;
1023		}	
1024		ip->srcport = NSRCPORT(&pp->srcadr);
1025		ip->flags = 0;
1026		if (pp == sys_peer)
1027		    ip->flags |= INFO_FLAG_SYSPEER;
1028		if (pp->flags & FLAG_CONFIG)
1029		    ip->flags |= INFO_FLAG_CONFIG;
1030		if (pp->flags & FLAG_REFCLOCK)
1031		    ip->flags |= INFO_FLAG_REFCLOCK;
1032		if (pp->flags & FLAG_AUTHENABLE)
1033		    ip->flags |= INFO_FLAG_AUTHENABLE;
1034		if (pp->flags & FLAG_PREFER)
1035		    ip->flags |= INFO_FLAG_PREFER;
1036		if (pp->flags & FLAG_BURST)
1037		    ip->flags |= INFO_FLAG_BURST;
1038		if (pp->flags & FLAG_IBURST)
1039		    ip->flags |= INFO_FLAG_IBURST;
1040		if (pp->status == CTL_PST_SEL_SYNCCAND)
1041		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
1042		if (pp->status >= CTL_PST_SEL_SYSPEER)
1043		    ip->flags |= INFO_FLAG_SHORTLIST;
1044		ip->flags = htons(ip->flags);
1045		ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
1046		ip->timetosend = htonl(pp->nextdate - current_time);
1047		ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
1048		ip->sent = htonl((u_int32)(pp->sent));
1049		ip->processed = htonl((u_int32)(pp->processed));
1050		ip->badauth = htonl((u_int32)(pp->badauth));
1051		ip->bogusorg = htonl((u_int32)(pp->bogusorg));
1052		ip->oldpkt = htonl((u_int32)(pp->oldpkt));
1053		ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
1054		ip->selbroken = htonl((u_int32)(pp->selbroken));
1055		ip->candidate = pp->status;
1056		ip = (struct info_peer_stats *)more_pkt();
1057	}
1058	flush_pkt();
1059}
1060
1061
1062/*
1063 * sys_info - return system info
1064 */
1065static void
1066sys_info(
1067	struct sockaddr_storage *srcadr,
1068	struct interface *inter,
1069	struct req_pkt *inpkt
1070	)
1071{
1072	register struct info_sys *is;
1073
1074	is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
1075	    v6sizeof(struct info_sys));
1076
1077	if (sys_peer != 0) {
1078		if (sys_peer->srcadr.ss_family == AF_INET) {
1079			is->peer = GET_INADDR(sys_peer->srcadr);
1080			if (client_v6_capable)
1081				is->v6_flag = 0;
1082		} else if (client_v6_capable) {
1083			is->peer6 = GET_INADDR6(sys_peer->srcadr);
1084			is->v6_flag = 1;
1085		}
1086		is->peer_mode = sys_peer->hmode;
1087	} else {
1088		is->peer = 0;
1089		if (client_v6_capable) {
1090			is->v6_flag = 0;
1091		}
1092		is->peer_mode = 0;
1093	}
1094
1095	is->leap = sys_leap;
1096	is->stratum = sys_stratum;
1097	is->precision = sys_precision;
1098	is->rootdelay = htonl(DTOFP(sys_rootdelay));
1099	is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
1100	is->frequency = htonl(DTOFP(sys_jitter));
1101	is->stability = htonl(DTOUFP(clock_stability));
1102	is->refid = sys_refid;
1103	HTONL_FP(&sys_reftime, &is->reftime);
1104
1105	is->poll = sys_poll;
1106	
1107	is->flags = 0;
1108	if (sys_authenticate)
1109		is->flags |= INFO_FLAG_AUTHENTICATE;
1110	if (sys_bclient)
1111		is->flags |= INFO_FLAG_BCLIENT;
1112#ifdef REFCLOCK
1113	if (cal_enable)
1114		is->flags |= INFO_FLAG_CAL;
1115#endif /* REFCLOCK */
1116	if (kern_enable)
1117		is->flags |= INFO_FLAG_KERNEL;
1118	if (mon_enabled != MON_OFF)
1119		is->flags |= INFO_FLAG_MONITOR;
1120	if (ntp_enable)
1121		is->flags |= INFO_FLAG_NTP;
1122	if (pps_enable)
1123		is->flags |= INFO_FLAG_PPS_SYNC;
1124	if (stats_control)
1125		is->flags |= INFO_FLAG_FILEGEN;
1126	is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
1127	HTONL_UF(sys_authdelay.l_f, &is->authdelay);
1128
1129	(void) more_pkt();
1130	flush_pkt();
1131}
1132
1133
1134/*
1135 * sys_stats - return system statistics
1136 */
1137static void
1138sys_stats(
1139	struct sockaddr_storage *srcadr,
1140	struct interface *inter,
1141	struct req_pkt *inpkt
1142	)
1143{
1144	register struct info_sys_stats *ss;
1145
1146	/*
1147	 * Importations from the protocol module
1148	 */
1149	ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
1150		sizeof(struct info_sys_stats));
1151	ss->timeup = htonl((u_int32)current_time);
1152	ss->timereset = htonl((u_int32)(current_time - sys_stattime));
1153	ss->denied = htonl((u_int32)sys_restricted);
1154	ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt);
1155	ss->newversionpkt = htonl((u_int32)sys_newversionpkt);
1156	ss->unknownversion = htonl((u_int32)sys_unknownversion);
1157	ss->badlength = htonl((u_int32)sys_badlength);
1158	ss->processed = htonl((u_int32)sys_processed);
1159	ss->badauth = htonl((u_int32)sys_badauth);
1160	ss->limitrejected = htonl((u_int32)sys_limitrejected);
1161	ss->received = htonl((u_int32)sys_received);
1162	(void) more_pkt();
1163	flush_pkt();
1164}
1165
1166
1167/*
1168 * mem_stats - return memory statistics
1169 */
1170static void
1171mem_stats(
1172	struct sockaddr_storage *srcadr,
1173	struct interface *inter,
1174	struct req_pkt *inpkt
1175	)
1176{
1177	register struct info_mem_stats *ms;
1178	register int i;
1179
1180	/*
1181	 * Importations from the peer module
1182	 */
1183	extern int peer_hash_count[NTP_HASH_SIZE];
1184	extern int peer_free_count;
1185	extern u_long peer_timereset;
1186	extern u_long findpeer_calls;
1187	extern u_long peer_allocations;
1188	extern u_long peer_demobilizations;
1189	extern int total_peer_structs;
1190
1191	ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
1192						  sizeof(struct info_mem_stats));
1193
1194	ms->timereset = htonl((u_int32)(current_time - peer_timereset));
1195	ms->totalpeermem = htons((u_short)total_peer_structs);
1196	ms->freepeermem = htons((u_short)peer_free_count);
1197	ms->findpeer_calls = htonl((u_int32)findpeer_calls);
1198	ms->allocations = htonl((u_int32)peer_allocations);
1199	ms->demobilizations = htonl((u_int32)peer_demobilizations);
1200
1201	for (i = 0; i < NTP_HASH_SIZE; i++) {
1202		if (peer_hash_count[i] > 255)
1203		    ms->hashcount[i] = 255;
1204		else
1205		    ms->hashcount[i] = (u_char)peer_hash_count[i];
1206	}
1207
1208	(void) more_pkt();
1209	flush_pkt();
1210}
1211
1212
1213/*
1214 * io_stats - return io statistics
1215 */
1216static void
1217io_stats(
1218	struct sockaddr_storage *srcadr,
1219	struct interface *inter,
1220	struct req_pkt *inpkt
1221	)
1222{
1223	register struct info_io_stats *io;
1224
1225	/*
1226	 * Importations from the io module
1227	 */
1228	extern u_long io_timereset;
1229	
1230	io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
1231						 sizeof(struct info_io_stats));
1232
1233	io->timereset = htonl((u_int32)(current_time - io_timereset));
1234	io->totalrecvbufs = htons((u_short) total_recvbuffs());
1235	io->freerecvbufs = htons((u_short) free_recvbuffs());
1236	io->fullrecvbufs = htons((u_short) full_recvbuffs());
1237	io->lowwater = htons((u_short) lowater_additions());
1238	io->dropped = htonl((u_int32)packets_dropped);
1239	io->ignored = htonl((u_int32)packets_ignored);
1240	io->received = htonl((u_int32)packets_received);
1241	io->sent = htonl((u_int32)packets_sent);
1242	io->notsent = htonl((u_int32)packets_notsent);
1243	io->interrupts = htonl((u_int32)handler_calls);
1244	io->int_received = htonl((u_int32)handler_pkts);
1245
1246	(void) more_pkt();
1247	flush_pkt();
1248}
1249
1250
1251/*
1252 * timer_stats - return timer statistics
1253 */
1254static void
1255timer_stats(
1256	struct sockaddr_storage *srcadr,
1257	struct interface *inter,
1258	struct req_pkt *inpkt
1259	)
1260{
1261	register struct info_timer_stats *ts;
1262
1263	/*
1264	 * Importations from the timer module
1265	 */
1266	extern u_long timer_timereset;
1267	extern u_long timer_overflows;
1268	extern u_long timer_xmtcalls;
1269
1270	ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt,
1271						    sizeof(struct info_timer_stats));
1272
1273	ts->timereset = htonl((u_int32)(current_time - timer_timereset));
1274	ts->alarms = htonl((u_int32)alarm_overflow);
1275	ts->overflows = htonl((u_int32)timer_overflows);
1276	ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
1277
1278	(void) more_pkt();
1279	flush_pkt();
1280}
1281
1282
1283/*
1284 * loop_info - return the current state of the loop filter
1285 */
1286static void
1287loop_info(
1288	struct sockaddr_storage *srcadr,
1289	struct interface *inter,
1290	struct req_pkt *inpkt
1291	)
1292{
1293	register struct info_loop *li;
1294	l_fp ltmp;
1295
1296	/*
1297	 * Importations from the loop filter module
1298	 */
1299	extern double last_offset;
1300	extern double drift_comp;
1301	extern int tc_counter;
1302	extern u_long sys_clocktime;
1303
1304	li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
1305	    sizeof(struct info_loop));
1306
1307	DTOLFP(last_offset, &ltmp);
1308	HTONL_FP(&ltmp, &li->last_offset);
1309	DTOLFP(drift_comp * 1e6, &ltmp);
1310	HTONL_FP(&ltmp, &li->drift_comp);
1311	li->compliance = htonl((u_int32)(tc_counter));
1312	li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime));
1313
1314	(void) more_pkt();
1315	flush_pkt();
1316}
1317
1318
1319/*
1320 * do_conf - add a peer to the configuration list
1321 */
1322static void
1323do_conf(
1324	struct sockaddr_storage *srcadr,
1325	struct interface *inter,
1326	struct req_pkt *inpkt
1327	)
1328{
1329	static u_long soonest_ifrescan_time = 0;
1330	int items;
1331	u_int fl;
1332	struct conf_peer *cp; 
1333	struct conf_peer temp_cp;
1334	struct sockaddr_storage peeraddr;
1335	struct sockaddr_in tmp_clock;
1336
1337	/*
1338	 * Do a check of everything to see that it looks
1339	 * okay.  If not, complain about it.  Note we are
1340	 * very picky here.
1341	 */
1342	items = INFO_NITEMS(inpkt->err_nitems);
1343	cp = (struct conf_peer *)inpkt->data;
1344	memset(&temp_cp, 0, sizeof(struct conf_peer));
1345	memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1346	fl = 0;
1347	while (items-- > 0 && !fl) {
1348		if (((temp_cp.version) > NTP_VERSION)
1349		    || ((temp_cp.version) < NTP_OLDVERSION))
1350		    fl = 1;
1351		if (temp_cp.hmode != MODE_ACTIVE
1352		    && temp_cp.hmode != MODE_CLIENT
1353		    && temp_cp.hmode != MODE_BROADCAST)
1354		    fl = 1;
1355		if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
1356				  | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY))
1357		    fl = 1;
1358		cp = (struct conf_peer *)
1359		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1360	}
1361
1362	if (fl) {
1363		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1364		return;
1365	}
1366
1367	/*
1368	 * Looks okay, try it out
1369	 */
1370	items = INFO_NITEMS(inpkt->err_nitems);
1371	cp = (struct conf_peer *)inpkt->data;  
1372
1373	while (items-- > 0) {
1374		memset(&temp_cp, 0, sizeof(struct conf_peer));
1375		memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1376		memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage));
1377
1378		fl = 0;
1379		if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
1380			fl |= FLAG_AUTHENABLE;
1381		if (temp_cp.flags & CONF_FLAG_PREFER)
1382			fl |= FLAG_PREFER;
1383		if (temp_cp.flags & CONF_FLAG_BURST)
1384		    fl |= FLAG_BURST;
1385		if (temp_cp.flags & CONF_FLAG_IBURST)
1386		    fl |= FLAG_IBURST;
1387		if (temp_cp.flags & CONF_FLAG_SKEY)
1388			fl |= FLAG_SKEY;
1389		
1390		if (client_v6_capable && temp_cp.v6_flag != 0) {
1391			peeraddr.ss_family = AF_INET6;
1392			GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 
1393		} else {
1394			peeraddr.ss_family = AF_INET;
1395			GET_INADDR(peeraddr) = temp_cp.peeraddr;
1396			/*
1397			 * Make sure the address is valid
1398			 */
1399			tmp_clock = *CAST_V4(peeraddr);
1400			if (
1401#ifdef REFCLOCK
1402				!ISREFCLOCKADR(&tmp_clock) &&
1403#endif
1404				ISBADADR(&tmp_clock)) {
1405				req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1406				return;
1407			}
1408
1409		}
1410		NSRCPORT(&peeraddr) = htons(NTP_PORT);
1411#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1412		peeraddr.ss_len = SOCKLEN(&peeraddr);
1413#endif
1414
1415		/* XXX W2DO? minpoll/maxpoll arguments ??? */
1416		if (peer_config(&peeraddr, (struct interface *)0,
1417		    temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 
1418		    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
1419		    NULL) == 0) {
1420			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1421			return;
1422		}
1423
1424		/*
1425		 * ntp_intres.c uses REQ_CONFIG/doconf() to add each
1426		 * server after its name is resolved.  If we have been
1427		 * disconnected from the network, it may notice the
1428		 * network has returned and add the first server while
1429		 * the relevant interface is still disabled, awaiting
1430		 * the next interface rescan.  To get things moving
1431		 * more quickly, trigger an interface scan now, except
1432		 * if we have done so in the last half minute.
1433		 */
1434		if (soonest_ifrescan_time < current_time) {
1435			soonest_ifrescan_time = current_time + 30;
1436			timer_interfacetimeout(current_time);
1437			DPRINTF(1, ("do_conf triggering interface rescan\n"));
1438		}
1439
1440		cp = (struct conf_peer *)
1441		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1442	}
1443
1444	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1445}
1446
1447#if 0
1448/* XXX */
1449/*
1450 * dns_a - Snarf DNS info for an association ID
1451 */
1452static void
1453dns_a(
1454	struct sockaddr_storage *srcadr,
1455	struct interface *inter,
1456	struct req_pkt *inpkt
1457	)
1458{
1459	register struct info_dns_assoc *dp;
1460	register int items;
1461	struct sockaddr_in peeraddr;
1462
1463	/*
1464	 * Do a check of everything to see that it looks
1465	 * okay.  If not, complain about it.  Note we are
1466	 * very picky here.
1467	 */
1468	items = INFO_NITEMS(inpkt->err_nitems);
1469	dp = (struct info_dns_assoc *)inpkt->data;
1470
1471	/*
1472	 * Looks okay, try it out
1473	 */
1474	items = INFO_NITEMS(inpkt->err_nitems);
1475	dp = (struct info_dns_assoc *)inpkt->data;
1476	memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
1477	peeraddr.sin_family = AF_INET;
1478	peeraddr.sin_port = htons(NTP_PORT);
1479
1480	/*
1481	 * Make sure the address is valid
1482	 */
1483	if (
1484#ifdef REFCLOCK
1485		!ISREFCLOCKADR(&peeraddr) &&
1486#endif
1487		ISBADADR(&peeraddr)) {
1488#ifdef REFCLOCK
1489		msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
1490#else
1491		msyslog(LOG_ERR, "dns_a: ISBADADR");
1492#endif
1493		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1494		return;
1495	}
1496
1497	while (items-- > 0) {
1498		associd_t associd;
1499		size_t hnl;
1500		struct peer *peer;
1501		int bogon = 0;
1502
1503		associd = dp->associd;
1504		peer = findpeerbyassoc(associd);
1505		if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
1506			msyslog(LOG_ERR, "dns_a: %s",
1507				(peer == 0)
1508				? "peer == 0"
1509				: "peer->flags & FLAG_REFCLOCK");
1510			++bogon;
1511		}
1512		peeraddr.sin_addr.s_addr = dp->peeraddr;
1513		for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
1514		if (hnl >= sizeof dp->hostname) {
1515			msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
1516				(long)hnl, (long)sizeof dp->hostname);
1517			++bogon;
1518		}
1519
1520		msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
1521			dp->hostname,
1522			stoa((struct sockaddr_storage *)&peeraddr), associd,
1523			bogon);
1524
1525		if (bogon) {
1526			/* If it didn't work */
1527			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1528			return;
1529		} else {
1530#if 0
1531#ifdef PUBKEY
1532			crypto_public(peer, dp->hostname);
1533#endif /* PUBKEY */
1534#endif
1535		}
1536
1537		dp++;
1538	}
1539
1540	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1541}
1542#endif /* 0 */
1543
1544/*
1545 * do_unconf - remove a peer from the configuration list
1546 */
1547static void
1548do_unconf(
1549	struct sockaddr_storage *srcadr,
1550	struct interface *inter,
1551	struct req_pkt *inpkt
1552	)
1553{
1554	register struct conf_unpeer *cp;
1555	struct conf_unpeer temp_cp;
1556	register int items;
1557	register struct peer *peer;
1558	struct sockaddr_storage peeraddr;
1559	int bad, found;
1560
1561	/*
1562	 * This is a bit unstructured, but I like to be careful.
1563	 * We check to see that every peer exists and is actually
1564	 * configured.  If so, we remove them.  If not, we return
1565	 * an error.
1566	 */
1567	items = INFO_NITEMS(inpkt->err_nitems);
1568	cp = (struct conf_unpeer *)inpkt->data;
1569
1570	bad = 0;
1571	while (items-- > 0 && !bad) {
1572		memset(&temp_cp, 0, sizeof(temp_cp));
1573		memset(&peeraddr, 0, sizeof(peeraddr));
1574		memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1575		if (client_v6_capable && temp_cp.v6_flag != 0) {
1576			peeraddr.ss_family = AF_INET6;
1577			GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
1578		} else {
1579			peeraddr.ss_family = AF_INET;
1580			GET_INADDR(peeraddr) = temp_cp.peeraddr;
1581		}
1582		NSRCPORT(&peeraddr) = htons(NTP_PORT);
1583#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1584		peeraddr.ss_len = SOCKLEN(&peeraddr);
1585#endif
1586		found = 0;
1587		peer = (struct peer *)0;
1588#ifdef DEBUG
1589		if (debug)
1590		     printf("searching for %s\n", stoa(&peeraddr));
1591#endif
1592		while (!found) {
1593			peer = findexistingpeer(&peeraddr, peer, -1);
1594			if (peer == (struct peer *)0)
1595			    break;
1596			if (peer->flags & FLAG_CONFIG)
1597			    found = 1;
1598		}
1599		if (!found)
1600		    bad = 1;
1601		cp = (struct conf_unpeer *)
1602		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1603	}
1604
1605	if (bad) {
1606		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1607		return;
1608	}
1609
1610	/*
1611	 * Now do it in earnest.
1612	 */
1613
1614	items = INFO_NITEMS(inpkt->err_nitems);
1615	cp = (struct conf_unpeer *)inpkt->data;
1616	while (items-- > 0) {
1617		memset(&temp_cp, 0, sizeof(temp_cp));
1618		memset(&peeraddr, 0, sizeof(peeraddr));
1619		memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1620		if (client_v6_capable && temp_cp.v6_flag != 0) {
1621			peeraddr.ss_family = AF_INET6;
1622			GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
1623		} else {
1624			peeraddr.ss_family = AF_INET;
1625			GET_INADDR(peeraddr) = temp_cp.peeraddr;
1626		}
1627		NSRCPORT(&peeraddr) = htons(NTP_PORT);
1628#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1629		peeraddr.ss_len = SOCKLEN(&peeraddr);
1630#endif
1631		peer_unconfig(&peeraddr, (struct interface *)0, -1);
1632		cp = (struct conf_unpeer *)
1633		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1634	}
1635
1636	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1637}
1638
1639
1640/*
1641 * set_sys_flag - set system flags
1642 */
1643static void
1644set_sys_flag(
1645	struct sockaddr_storage *srcadr,
1646	struct interface *inter,
1647	struct req_pkt *inpkt
1648	)
1649{
1650	setclr_flags(srcadr, inter, inpkt, 1);
1651}
1652
1653
1654/*
1655 * clr_sys_flag - clear system flags
1656 */
1657static void
1658clr_sys_flag(
1659	struct sockaddr_storage *srcadr,
1660	struct interface *inter,
1661	struct req_pkt *inpkt
1662	)
1663{
1664	setclr_flags(srcadr, inter, inpkt, 0);
1665}
1666
1667
1668/*
1669 * setclr_flags - do the grunge work of flag setting/clearing
1670 */
1671static void
1672setclr_flags(
1673	struct sockaddr_storage *srcadr,
1674	struct interface *inter,
1675	struct req_pkt *inpkt,
1676	u_long set
1677	)
1678{
1679	register u_int flags;
1680	int prev_kern_enable;
1681
1682	prev_kern_enable = kern_enable;
1683	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1684		msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
1685		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1686		return;
1687	}
1688
1689	flags = ((struct conf_sys_flags *)inpkt->data)->flags;
1690	flags = ntohl(flags);
1691	
1692	if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1693		      SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
1694		      SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
1695		msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
1696			flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1697				  SYS_FLAG_NTP | SYS_FLAG_KERNEL |
1698				  SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
1699				  SYS_FLAG_AUTH | SYS_FLAG_CAL));
1700		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1701		return;
1702	}
1703
1704	if (flags & SYS_FLAG_BCLIENT)
1705		proto_config(PROTO_BROADCLIENT, set, 0., NULL);
1706	if (flags & SYS_FLAG_PPS)
1707		proto_config(PROTO_PPS, set, 0., NULL);
1708	if (flags & SYS_FLAG_NTP)
1709		proto_config(PROTO_NTP, set, 0., NULL);
1710	if (flags & SYS_FLAG_KERNEL)
1711		proto_config(PROTO_KERNEL, set, 0., NULL);
1712	if (flags & SYS_FLAG_MONITOR)
1713		proto_config(PROTO_MONITOR, set, 0., NULL);
1714	if (flags & SYS_FLAG_FILEGEN)
1715		proto_config(PROTO_FILEGEN, set, 0., NULL);
1716	if (flags & SYS_FLAG_AUTH)
1717		proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
1718	if (flags & SYS_FLAG_CAL)
1719		proto_config(PROTO_CAL, set, 0., NULL);
1720	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1721
1722	/* Reset the kernel ntp parameters if the kernel flag changed. */
1723	if (prev_kern_enable && !kern_enable)
1724	     	loop_config(LOOP_KERN_CLEAR, 0.0);
1725	if (!prev_kern_enable && kern_enable)
1726	     	loop_config(LOOP_DRIFTCOMP, drift_comp);
1727}
1728
1729
1730/*
1731 * list_restrict - return the restrict list
1732 */
1733static void
1734list_restrict(
1735	struct sockaddr_storage *srcadr,
1736	struct interface *inter,
1737	struct req_pkt *inpkt
1738	)
1739{
1740	register struct info_restrict *ir;
1741	register struct restrictlist *rl;
1742	register struct restrictlist6 *rl6;
1743
1744#ifdef DEBUG
1745	if (debug > 2)
1746	    printf("wants restrict list summary\n");
1747#endif
1748
1749	ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
1750	    v6sizeof(struct info_restrict));
1751	
1752	for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
1753		ir->addr = htonl(rl->addr);
1754		if (client_v6_capable) 
1755			ir->v6_flag = 0;
1756		ir->mask = htonl(rl->mask);
1757		ir->count = htonl((u_int32)rl->count);
1758		ir->flags = htons(rl->flags);
1759		ir->mflags = htons(rl->mflags);
1760		ir = (struct info_restrict *)more_pkt();
1761	}
1762	if (client_v6_capable)
1763		for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
1764			ir->addr6 = rl6->addr6;
1765			ir->mask6 = rl6->mask6;
1766			ir->v6_flag = 1;
1767			ir->count = htonl((u_int32)rl6->count);
1768			ir->flags = htons(rl6->flags);
1769			ir->mflags = htons(rl6->mflags);
1770			ir = (struct info_restrict *)more_pkt();
1771		}
1772	flush_pkt();
1773}
1774
1775
1776
1777/*
1778 * do_resaddflags - add flags to a restrict entry (or create one)
1779 */
1780static void
1781do_resaddflags(
1782	struct sockaddr_storage *srcadr,
1783	struct interface *inter,
1784	struct req_pkt *inpkt
1785	)
1786{
1787	do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
1788}
1789
1790
1791
1792/*
1793 * do_ressubflags - remove flags from a restrict entry
1794 */
1795static void
1796do_ressubflags(
1797	struct sockaddr_storage *srcadr,
1798	struct interface *inter,
1799	struct req_pkt *inpkt
1800	)
1801{
1802	do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
1803}
1804
1805
1806/*
1807 * do_unres…

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