xref: /freebsd/contrib/ntp/ntpd/ntp_request.c (revision ae83180158c4c937f170e31eff311b18c0286a93)
1 /*
2  * ntp_request.c - respond to information requests
3  */
4 #ifdef HAVE_CONFIG_H
5 # include <config.h>
6 #endif
7 
8 #include "ntpd.h"
9 #include "ntp_io.h"
10 #include "ntp_request.h"
11 #include "ntp_control.h"
12 #include "ntp_refclock.h"
13 #include "ntp_if.h"
14 #include "ntp_stdlib.h"
15 
16 #include <stdio.h>
17 #include <signal.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 
21 #include "recvbuff.h"
22 
23 #ifdef KERNEL_PLL
24 #include "ntp_syscall.h"
25 #endif /* KERNEL_PLL */
26 
27 /*
28  * Structure to hold request procedure information
29  */
30 #define	NOAUTH	0
31 #define	AUTH	1
32 
33 #define	NO_REQUEST	(-1)
34 
35 struct req_proc {
36 	short request_code;	/* defined request code */
37 	short needs_auth;	/* true when authentication needed */
38 	short sizeofitem;	/* size of request data item */
39 	void (*handler) P((struct sockaddr_in *, struct interface *,
40 			   struct req_pkt *));	/* routine to handle request */
41 };
42 
43 /*
44  * Universal request codes
45  */
46 static	struct req_proc univ_codes[] = {
47 	{ NO_REQUEST,		NOAUTH,	 0,	0 }
48 };
49 
50 static	void	req_ack	P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
51 static	char *	prepare_pkt	P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_int));
52 static	char *	more_pkt	P((void));
53 static	void	flush_pkt	P((void));
54 static	void	peer_list	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
55 static	void	peer_list_sum	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
56 static	void	peer_info	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
57 static	void	peer_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
58 static	void	sys_info	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
59 static	void	sys_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
60 static	void	mem_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
61 static	void	io_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
62 static	void	timer_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
63 static	void	loop_info	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
64 static	void	dns_a		P((struct sockaddr_in *, struct interface *, struct req_pkt *));
65 static	void	do_conf		P((struct sockaddr_in *, struct interface *, struct req_pkt *));
66 static	void	do_unconf	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
67 static	void	set_sys_flag	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
68 static	void	clr_sys_flag	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
69 static	void	setclr_flags	P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long));
70 static	void	list_restrict	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
71 static	void	do_resaddflags	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
72 static	void	do_ressubflags	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
73 static	void	do_unrestrict	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
74 static	void	do_restrict	P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
75 static	void	mon_getlist_0	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
76 static	void	mon_getlist_1	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
77 static	void	reset_stats	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
78 static	void	reset_peer	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
79 static	void	do_key_reread	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
80 static	void	trust_key	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
81 static	void	untrust_key	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
82 static	void	do_trustkey	P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long));
83 static	void	get_auth_info	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
84 static	void	reset_auth_stats P((void));
85 static	void	req_get_traps	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
86 static	void	req_set_trap	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
87 static	void	req_clr_trap	P((struct sockaddr_in *, struct interface *, struct req_pkt *));
88 static	void	do_setclr_trap	P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
89 static	void	set_request_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *));
90 static	void	set_control_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *));
91 static	void	get_ctl_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
92 #ifdef KERNEL_PLL
93 static	void	get_kernel_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
94 #endif /* KERNEL_PLL */
95 #ifdef REFCLOCK
96 static	void	get_clock_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
97 static	void	set_clock_fudge P((struct sockaddr_in *, struct interface *, struct req_pkt *));
98 #endif	/* REFCLOCK */
99 #ifdef REFCLOCK
100 static	void	get_clkbug_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
101 #endif	/* REFCLOCK */
102 
103 /*
104  * ntpd request codes
105  */
106 static	struct req_proc ntp_codes[] = {
107 	{ REQ_PEER_LIST,	NOAUTH,	0,	peer_list },
108 	{ REQ_PEER_LIST_SUM,	NOAUTH,	0,	peer_list_sum },
109 	{ REQ_PEER_INFO,    NOAUTH, sizeof(struct info_peer_list), peer_info },
110 	{ REQ_PEER_STATS,   NOAUTH, sizeof(struct info_peer_list), peer_stats },
111 	{ REQ_SYS_INFO,		NOAUTH,	0,	sys_info },
112 	{ REQ_SYS_STATS,	NOAUTH,	0,	sys_stats },
113 	{ REQ_IO_STATS,		NOAUTH,	0,	io_stats },
114 	{ REQ_MEM_STATS,	NOAUTH,	0,	mem_stats },
115 	{ REQ_LOOP_INFO,	NOAUTH,	0,	loop_info },
116 	{ REQ_TIMER_STATS,	NOAUTH,	0,	timer_stats },
117 	{ REQ_HOSTNAME_ASSOCID,	AUTH, sizeof(struct info_dns_assoc), dns_a },
118 	{ REQ_CONFIG,	    AUTH, sizeof(struct conf_peer), do_conf },
119 	{ REQ_UNCONFIG,	    AUTH, sizeof(struct conf_unpeer), do_unconf },
120 	{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), set_sys_flag },
121 	{ REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), clr_sys_flag },
122 	{ REQ_GET_RESTRICT,	NOAUTH,	0,	list_restrict },
123 	{ REQ_RESADDFLAGS, AUTH, sizeof(struct conf_restrict), do_resaddflags },
124 	{ REQ_RESSUBFLAGS, AUTH, sizeof(struct conf_restrict), do_ressubflags },
125 	{ REQ_UNRESTRICT,  AUTH, sizeof(struct conf_restrict), do_unrestrict },
126 	{ REQ_MON_GETLIST,	NOAUTH,	0,	mon_getlist_0 },
127 	{ REQ_MON_GETLIST_1,	NOAUTH,	0,	mon_getlist_1 },
128 	{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), reset_stats },
129 	{ REQ_RESET_PEER,  AUTH, sizeof(struct conf_unpeer), reset_peer },
130 	{ REQ_REREAD_KEYS,	AUTH,	0,	do_key_reread },
131 	{ REQ_TRUSTKEY,    AUTH, sizeof(u_long),	trust_key },
132 	{ REQ_UNTRUSTKEY,  AUTH, sizeof(u_long),	untrust_key },
133 	{ REQ_AUTHINFO,		NOAUTH,	0,	get_auth_info },
134 	{ REQ_TRAPS,		NOAUTH, 0,	req_get_traps },
135 	{ REQ_ADD_TRAP,	   AUTH, sizeof(struct conf_trap), req_set_trap },
136 	{ REQ_CLR_TRAP,	   AUTH, sizeof(struct conf_trap), req_clr_trap },
137 	{ REQ_REQUEST_KEY, AUTH, sizeof(u_long),	set_request_keyid },
138 	{ REQ_CONTROL_KEY, AUTH, sizeof(u_long),	set_control_keyid },
139 	{ REQ_GET_CTLSTATS,	NOAUTH,	0,	get_ctl_stats },
140 #ifdef KERNEL_PLL
141 	{ REQ_GET_KERNEL,	NOAUTH,	0,	get_kernel_info },
142 #endif
143 #ifdef REFCLOCK
144 	{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32),	get_clock_info },
145 	{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), set_clock_fudge },
146 	{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32),	get_clkbug_info },
147 #endif
148 	{ NO_REQUEST,		NOAUTH,	0,	0 }
149 };
150 
151 
152 /*
153  * Authentication keyid used to authenticate requests.  Zero means we
154  * don't allow writing anything.
155  */
156 keyid_t info_auth_keyid;
157 
158 /*
159  * Statistic counters to keep track of requests and responses.
160  */
161 u_long numrequests;		/* number of requests we've received */
162 u_long numresppkts;		/* number of resp packets sent with data */
163 
164 u_long errorcounter[INFO_ERR_AUTH+1];	/* lazy way to count errors, indexed */
165 /* by the error code */
166 
167 /*
168  * A hack.  To keep the authentication module clear of ntp-ism's, we
169  * include a time reset variable for its stats here.
170  */
171 static u_long auth_timereset;
172 
173 /*
174  * Response packet used by these routines.  Also some state information
175  * so that we can handle packet formatting within a common set of
176  * subroutines.  Note we try to enter data in place whenever possible,
177  * but the need to set the more bit correctly means we occasionally
178  * use the extra buffer and copy.
179  */
180 static struct resp_pkt rpkt;
181 static int reqver;
182 static int seqno;
183 static int nitems;
184 static int itemsize;
185 static int databytes;
186 static char exbuf[RESP_DATA_SIZE];
187 static int usingexbuf;
188 static struct sockaddr_in *toaddr;
189 static struct interface *frominter;
190 
191 /*
192  * init_request - initialize request data
193  */
194 void
195 init_request (void)
196 {
197 	int i;
198 
199 	numrequests = 0;
200 	numresppkts = 0;
201 	auth_timereset = 0;
202 	info_auth_keyid = 0;	/* by default, can't do this */
203 
204 	for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
205 	    errorcounter[i] = 0;
206 }
207 
208 
209 /*
210  * req_ack - acknowledge request with no data
211  */
212 static void
213 req_ack(
214 	struct sockaddr_in *srcadr,
215 	struct interface *inter,
216 	struct req_pkt *inpkt,
217 	int errcode
218 	)
219 {
220 	/*
221 	 * fill in the fields
222 	 */
223 	rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
224 	rpkt.auth_seq = AUTH_SEQ(0, 0);
225 	rpkt.implementation = inpkt->implementation;
226 	rpkt.request = inpkt->request;
227 	rpkt.err_nitems = ERR_NITEMS(errcode, 0);
228 	rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
229 
230 	/*
231 	 * send packet and bump counters
232 	 */
233 	sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
234 	errorcounter[errcode]++;
235 }
236 
237 
238 /*
239  * prepare_pkt - prepare response packet for transmission, return pointer
240  *		 to storage for data item.
241  */
242 static char *
243 prepare_pkt(
244 	struct sockaddr_in *srcadr,
245 	struct interface *inter,
246 	struct req_pkt *pkt,
247 	u_int structsize
248 	)
249 {
250 #ifdef DEBUG
251 	if (debug > 3)
252 	    printf("request: preparing pkt\n");
253 #endif
254 
255 	/*
256 	 * Fill in the implementation, reqest and itemsize fields
257 	 * since these won't change.
258 	 */
259 	rpkt.implementation = pkt->implementation;
260 	rpkt.request = pkt->request;
261 	rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
262 
263 	/*
264 	 * Compute the static data needed to carry on.
265 	 */
266 	toaddr = srcadr;
267 	frominter = inter;
268 	seqno = 0;
269 	nitems = 0;
270 	itemsize = structsize;
271 	databytes = 0;
272 	usingexbuf = 0;
273 
274 	/*
275 	 * return the beginning of the packet buffer.
276 	 */
277 	return &rpkt.data[0];
278 }
279 
280 
281 /*
282  * more_pkt - return a data pointer for a new item.
283  */
284 static char *
285 more_pkt(void)
286 {
287 	/*
288 	 * If we were using the extra buffer, send the packet.
289 	 */
290 	if (usingexbuf) {
291 #ifdef DEBUG
292 		if (debug > 2)
293 		    printf("request: sending pkt\n");
294 #endif
295 		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
296 		rpkt.auth_seq = AUTH_SEQ(0, seqno);
297 		rpkt.err_nitems = htons((u_short)nitems);
298 		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
299 			RESP_HEADER_SIZE+databytes);
300 		numresppkts++;
301 
302 		/*
303 		 * Copy data out of exbuf into the packet.
304 		 */
305 		memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);
306 		seqno++;
307 		databytes = 0;
308 		nitems = 0;
309 		usingexbuf = 0;
310 	}
311 
312 	databytes += itemsize;
313 	nitems++;
314 	if (databytes + itemsize <= RESP_DATA_SIZE) {
315 #ifdef DEBUG
316 		if (debug > 3)
317 		    printf("request: giving him more data\n");
318 #endif
319 		/*
320 		 * More room in packet.  Give him the
321 		 * next address.
322 		 */
323 		return &rpkt.data[databytes];
324 	} else {
325 		/*
326 		 * No room in packet.  Give him the extra
327 		 * buffer unless this was the last in the sequence.
328 		 */
329 #ifdef DEBUG
330 		if (debug > 3)
331 		    printf("request: into extra buffer\n");
332 #endif
333 		if (seqno == MAXSEQ)
334 		    return (char *)0;
335 		else {
336 			usingexbuf = 1;
337 			return exbuf;
338 		}
339 	}
340 }
341 
342 
343 /*
344  * flush_pkt - we're done, return remaining information.
345  */
346 static void
347 flush_pkt(void)
348 {
349 #ifdef DEBUG
350 	if (debug > 2)
351 	    printf("request: flushing packet, %d items\n", nitems);
352 #endif
353 	/*
354 	 * Must send the last packet.  If nothing in here and nothing
355 	 * has been sent, send an error saying no data to be found.
356 	 */
357 	if (seqno == 0 && nitems == 0)
358 	    req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
359 		    INFO_ERR_NODATA);
360 	else {
361 		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
362 		rpkt.auth_seq = AUTH_SEQ(0, seqno);
363 		rpkt.err_nitems = htons((u_short)nitems);
364 		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
365 			RESP_HEADER_SIZE+databytes);
366 		numresppkts++;
367 	}
368 }
369 
370 
371 
372 /*
373  * process_private - process private mode (7) packets
374  */
375 void
376 process_private(
377 	struct recvbuf *rbufp,
378 	int mod_okay
379 	)
380 {
381 	struct req_pkt *inpkt;
382 	struct sockaddr_in *srcadr;
383 	struct interface *inter;
384 	struct req_proc *proc;
385 	int ec;
386 
387 	/*
388 	 * Initialize pointers, for convenience
389 	 */
390 	inpkt = (struct req_pkt *)&rbufp->recv_pkt;
391 	srcadr = &rbufp->recv_srcadr;
392 	inter = rbufp->dstadr;
393 
394 #ifdef DEBUG
395 	if (debug > 2)
396 	    printf("process_private: impl %d req %d\n",
397 		   inpkt->implementation, inpkt->request);
398 #endif
399 
400 	/*
401 	 * Do some sanity checks on the packet.  Return a format
402 	 * error if it fails.
403 	 */
404 	ec = 0;
405 	if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))
406 	    || (++ec, ISMORE(inpkt->rm_vn_mode))
407 	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
408 	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
409 	    || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
410 	    || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
411 	    || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
412 	    || (++ec, rbufp->recv_length > REQ_LEN_MAC)
413 	    || (++ec, rbufp->recv_length < REQ_LEN_NOMAC)
414 		) {
415 		msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed", ec);
416 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
417 		return;
418 	}
419 
420 	reqver = INFO_VERSION(inpkt->rm_vn_mode);
421 
422 	/*
423 	 * Get the appropriate procedure list to search.
424 	 */
425 	if (inpkt->implementation == IMPL_UNIV)
426 	    proc = univ_codes;
427 	else if (inpkt->implementation == IMPL_XNTPD)
428 	    proc = ntp_codes;
429 	else {
430 		req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
431 		return;
432 	}
433 
434 	/*
435 	 * Search the list for the request codes.  If it isn't one
436 	 * we know, return an error.
437 	 */
438 	while (proc->request_code != NO_REQUEST) {
439 		if (proc->request_code == (short) inpkt->request)
440 		    break;
441 		proc++;
442 	}
443 	if (proc->request_code == NO_REQUEST) {
444 		req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
445 		return;
446 	}
447 
448 #ifdef DEBUG
449 	if (debug > 3)
450 	    printf("found request in tables\n");
451 #endif
452 
453 	/*
454 	 * If we need to authenticate, do so.  Note that an
455 	 * authenticatable packet must include a mac field, must
456 	 * have used key info_auth_keyid and must have included
457 	 * a time stamp in the appropriate field.  The time stamp
458 	 * must be within INFO_TS_MAXSKEW of the receive
459 	 * time stamp.
460 	 */
461 	if (proc->needs_auth && sys_authenticate) {
462 		l_fp ftmp;
463 		double dtemp;
464 
465 		/*
466 		 * If this guy is restricted from doing this, don't let him
467 		 * If wrong key was used, or packet doesn't have mac, return.
468 		 */
469 		if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0
470 		    || ntohl(inpkt->keyid) != info_auth_keyid) {
471 #ifdef DEBUG
472 			if (debug > 4)
473 			    printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
474 				    INFO_IS_AUTH(inpkt->auth_seq),
475 				    (u_long)info_auth_keyid,
476 				    (u_long)ntohl(inpkt->keyid));
477 #endif
478 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
479 			return;
480 		}
481 		if (rbufp->recv_length > REQ_LEN_MAC) {
482 #ifdef DEBUG
483 			if (debug > 4)
484 			    printf("bad pkt length %d\n",
485 				   rbufp->recv_length);
486 #endif
487 			msyslog(LOG_ERR, "process_private: bad pkt length %d",
488 				rbufp->recv_length);
489 			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
490 			return;
491 		}
492 		if (!mod_okay || !authhavekey(info_auth_keyid)) {
493 #ifdef DEBUG
494 			if (debug > 4)
495 			    printf("failed auth mod_okay %d\n", mod_okay);
496 #endif
497 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
498 			return;
499 		}
500 
501 		/*
502 		 * calculate absolute time difference between xmit time stamp
503 		 * and receive time stamp.  If too large, too bad.
504 		 */
505 		NTOHL_FP(&inpkt->tstamp, &ftmp);
506 		L_SUB(&ftmp, &rbufp->recv_time);
507 		LFPTOD(&ftmp, dtemp);
508 		if (fabs(dtemp) >= INFO_TS_MAXSKEW) {
509 			/*
510 			 * He's a loser.  Tell him.
511 			 */
512 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
513 			return;
514 		}
515 
516 		/*
517 		 * So far so good.  See if decryption works out okay.
518 		 */
519 		if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
520 		    REQ_LEN_NOMAC, (int)(rbufp->recv_length - REQ_LEN_NOMAC))) {
521 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
522 			return;
523 		}
524 	}
525 
526 	/*
527 	 * If we need data, check to see if we have some.  If we
528 	 * don't, check to see that there is none (picky, picky).
529 	 */
530 	if (INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem) {
531                 msyslog(LOG_ERR, "INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem: %d != %d",
532 			INFO_ITEMSIZE(inpkt->mbz_itemsize), proc->sizeofitem);
533 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
534 		return;
535 	}
536 	if (proc->sizeofitem != 0)
537 	    if (proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems)
538 		> sizeof(inpkt->data)) {
539 		    msyslog(LOG_ERR, "sizeofitem(%d)*NITEMS(%d) > data: %d > %ld",
540 	    		    proc->sizeofitem, INFO_NITEMS(inpkt->err_nitems),
541 			    proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems),
542 			    (long)sizeof(inpkt->data));
543 		    req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
544 		    return;
545 	    }
546 #ifdef DEBUG
547 	if (debug > 3)
548 	    printf("process_private: all okay, into handler\n");
549 #endif
550 
551 	/*
552 	 * Packet is okay.  Call the handler to send him data.
553 	 */
554 	(proc->handler)(srcadr, inter, inpkt);
555 }
556 
557 
558 /*
559  * peer_list - send a list of the peers
560  */
561 static void
562 peer_list(
563 	struct sockaddr_in *srcadr,
564 	struct interface *inter,
565 	struct req_pkt *inpkt
566 	)
567 {
568 	register struct info_peer_list *ip;
569 	register struct peer *pp;
570 	register int i;
571 
572 	ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
573 						  sizeof(struct info_peer_list));
574 	for (i = 0; i < HASH_SIZE && ip != 0; i++) {
575 		pp = peer_hash[i];
576 		while (pp != 0 && ip != 0) {
577 			ip->address = pp->srcadr.sin_addr.s_addr;
578 			ip->port = pp->srcadr.sin_port;
579 			ip->hmode = pp->hmode;
580 			ip->flags = 0;
581 			if (pp->flags & FLAG_CONFIG)
582 			    ip->flags |= INFO_FLAG_CONFIG;
583 			if (pp == sys_peer)
584 			    ip->flags |= INFO_FLAG_SYSPEER;
585 			if (pp->status == CTL_PST_SEL_SYNCCAND)
586 			    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
587 			if (pp->status >= CTL_PST_SEL_SYSPEER)
588 			    ip->flags |= INFO_FLAG_SHORTLIST;
589 			ip = (struct info_peer_list *)more_pkt();
590 			pp = pp->next;
591 		}
592 	}
593 	flush_pkt();
594 }
595 
596 
597 /*
598  * peer_list_sum - return extended peer list
599  */
600 static void
601 peer_list_sum(
602 	struct sockaddr_in *srcadr,
603 	struct interface *inter,
604 	struct req_pkt *inpkt
605 	)
606 {
607 	register struct info_peer_summary *ips;
608 	register struct peer *pp;
609 	register int i;
610 	l_fp ltmp;
611 
612 #ifdef DEBUG
613 	if (debug > 2)
614 	    printf("wants peer list summary\n");
615 #endif
616 
617 	ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
618 						      sizeof(struct info_peer_summary));
619 	for (i = 0; i < HASH_SIZE && ips != 0; i++) {
620 		pp = peer_hash[i];
621 		while (pp != 0 && ips != 0) {
622 #ifdef DEBUG
623 			if (debug > 3)
624 			    printf("sum: got one\n");
625 #endif
626 			ips->dstadr =
627 			    (pp->processed)
628 			    ? pp->cast_flags == MDF_BCAST
629 			      ? pp->dstadr->bcast.sin_addr.s_addr
630 			      : pp->cast_flags
631 			        ? pp->dstadr->sin.sin_addr.s_addr
632 			          ? pp->dstadr->sin.sin_addr.s_addr
633 			          : pp->dstadr->bcast.sin_addr.s_addr
634 			        : 1
635 			    : 5;
636 			ips->srcadr = pp->srcadr.sin_addr.s_addr;
637 			ips->srcport = pp->srcadr.sin_port;
638 			ips->stratum = pp->stratum;
639 			ips->hpoll = pp->hpoll;
640 			ips->ppoll = pp->ppoll;
641 			ips->reach = pp->reach;
642 			ips->flags = 0;
643 			if (pp == sys_peer)
644 			    ips->flags |= INFO_FLAG_SYSPEER;
645 			if (pp->flags & FLAG_CONFIG)
646 			    ips->flags |= INFO_FLAG_CONFIG;
647 			if (pp->flags & FLAG_REFCLOCK)
648 			    ips->flags |= INFO_FLAG_REFCLOCK;
649 			if (pp->flags & FLAG_AUTHENABLE)
650 			    ips->flags |= INFO_FLAG_AUTHENABLE;
651 			if (pp->flags & FLAG_PREFER)
652 			    ips->flags |= INFO_FLAG_PREFER;
653 			if (pp->flags & FLAG_BURST)
654 			    ips->flags |= INFO_FLAG_BURST;
655 			if (pp->status == CTL_PST_SEL_SYNCCAND)
656 			    ips->flags |= INFO_FLAG_SEL_CANDIDATE;
657 			if (pp->status >= CTL_PST_SEL_SYSPEER)
658 			    ips->flags |= INFO_FLAG_SHORTLIST;
659 			ips->hmode = pp->hmode;
660 			ips->delay = HTONS_FP(DTOFP(pp->delay));
661 			DTOLFP(pp->offset, &ltmp);
662 			HTONL_FP(&ltmp, &ips->offset);
663 			ips->dispersion = HTONS_FP(DTOUFP(pp->disp));
664 
665 			pp = pp->next;
666 			ips = (struct info_peer_summary *)more_pkt();
667 		}
668 	}
669 	flush_pkt();
670 }
671 
672 
673 /*
674  * peer_info - send information for one or more peers
675  */
676 static void
677 peer_info (
678 	struct sockaddr_in *srcadr,
679 	struct interface *inter,
680 	struct req_pkt *inpkt
681 	)
682 {
683 	register struct info_peer_list *ipl;
684 	register struct peer *pp;
685 	register struct info_peer *ip;
686 	register int items;
687 	register int i, j;
688 	struct sockaddr_in addr;
689 	extern struct peer *sys_peer;
690 	l_fp ltmp;
691 
692 	memset((char *)&addr, 0, sizeof addr);
693 	addr.sin_family = AF_INET;
694 	items = INFO_NITEMS(inpkt->err_nitems);
695 	ipl = (struct info_peer_list *) inpkt->data;
696 	ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
697 					     sizeof(struct info_peer));
698 	while (items-- > 0 && ip != 0) {
699 		addr.sin_port = ipl->port;
700 		addr.sin_addr.s_addr = ipl->address;
701 		ipl++;
702 		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
703 		    continue;
704 		ip->dstadr =
705 		    (pp->processed)
706 		    ? pp->cast_flags == MDF_BCAST
707 		      ? pp->dstadr->bcast.sin_addr.s_addr
708 		      : pp->cast_flags
709 		        ? pp->dstadr->sin.sin_addr.s_addr
710 		          ? pp->dstadr->sin.sin_addr.s_addr
711 		          : pp->dstadr->bcast.sin_addr.s_addr
712 		        : 2
713 		    : 6;
714 		ip->srcadr = NSRCADR(&pp->srcadr);
715 		ip->srcport = NSRCPORT(&pp->srcadr);
716 		ip->flags = 0;
717 		if (pp == sys_peer)
718 		    ip->flags |= INFO_FLAG_SYSPEER;
719 		if (pp->flags & FLAG_CONFIG)
720 		    ip->flags |= INFO_FLAG_CONFIG;
721 		if (pp->flags & FLAG_REFCLOCK)
722 		    ip->flags |= INFO_FLAG_REFCLOCK;
723 		if (pp->flags & FLAG_AUTHENABLE)
724 		    ip->flags |= INFO_FLAG_AUTHENABLE;
725 		if (pp->flags & FLAG_PREFER)
726 		    ip->flags |= INFO_FLAG_PREFER;
727 		if (pp->flags & FLAG_BURST)
728 		    ip->flags |= INFO_FLAG_BURST;
729 		if (pp->status == CTL_PST_SEL_SYNCCAND)
730 		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
731 		if (pp->status >= CTL_PST_SEL_SYSPEER)
732 		    ip->flags |= INFO_FLAG_SHORTLIST;
733 		ip->leap = pp->leap;
734 		ip->hmode = pp->hmode;
735 		ip->keyid = pp->keyid;
736 		ip->stratum = pp->stratum;
737 		ip->ppoll = pp->ppoll;
738 		ip->hpoll = pp->hpoll;
739 		ip->precision = pp->precision;
740 		ip->version = pp->version;
741 		ip->reach = pp->reach;
742 		ip->unreach = pp->unreach;
743 		ip->flash = (u_char)pp->flash;
744 		ip->flash2 = pp->flash;
745 		ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
746 		ip->ttl = pp->ttl;
747 		ip->associd = htons(pp->associd);
748 		ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
749 		ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion));
750 		ip->refid = pp->refid;
751 		HTONL_FP(&pp->reftime, &ip->reftime);
752 		HTONL_FP(&pp->org, &ip->org);
753 		HTONL_FP(&pp->rec, &ip->rec);
754 		HTONL_FP(&pp->xmt, &ip->xmt);
755 		j = pp->filter_nextpt - 1;
756 		for (i = 0; i < NTP_SHIFT; i++, j--) {
757 			if (j < 0)
758 			    j = NTP_SHIFT-1;
759 			ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
760 			DTOLFP(pp->filter_offset[j], &ltmp);
761 			HTONL_FP(&ltmp, &ip->filtoffset[i]);
762 			ip->order[i] = (pp->filter_nextpt+NTP_SHIFT-1)
763 				- pp->filter_order[i];
764 			if (ip->order[i] >= NTP_SHIFT)
765 			    ip->order[i] -= NTP_SHIFT;
766 		}
767 		DTOLFP(pp->offset, &ltmp);
768 		HTONL_FP(&ltmp, &ip->offset);
769 		ip->delay = HTONS_FP(DTOFP(pp->delay));
770 		ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
771 		ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
772 		ip = (struct info_peer *)more_pkt();
773 	}
774 	flush_pkt();
775 }
776 
777 
778 /*
779  * peer_stats - send statistics for one or more peers
780  */
781 static void
782 peer_stats (
783 	struct sockaddr_in *srcadr,
784 	struct interface *inter,
785 	struct req_pkt *inpkt
786 	)
787 {
788 	register struct info_peer_list *ipl;
789 	register struct peer *pp;
790 	register struct info_peer_stats *ip;
791 	register int items;
792 	struct sockaddr_in addr;
793 	extern struct peer *sys_peer;
794 
795 	memset((char *)&addr, 0, sizeof addr);
796 	addr.sin_family = AF_INET;
797 	items = INFO_NITEMS(inpkt->err_nitems);
798 	ipl = (struct info_peer_list *) inpkt->data;
799 	ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
800 						   sizeof(struct info_peer_stats));
801 	while (items-- > 0 && ip != 0) {
802 		addr.sin_port = ipl->port;
803 		addr.sin_addr.s_addr = ipl->address;
804 		ipl++;
805 		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
806 		    continue;
807 		ip->dstadr =
808 		    (pp->processed)
809 		    ? pp->cast_flags == MDF_BCAST
810 		      ? pp->dstadr->bcast.sin_addr.s_addr
811 		      : pp->cast_flags
812 		        ? pp->dstadr->sin.sin_addr.s_addr
813 		          ? pp->dstadr->sin.sin_addr.s_addr
814 		          : pp->dstadr->bcast.sin_addr.s_addr
815 		        : 3
816 		    : 7;
817 		ip->srcadr = NSRCADR(&pp->srcadr);
818 		ip->srcport = NSRCPORT(&pp->srcadr);
819 		ip->flags = 0;
820 		if (pp == sys_peer)
821 		    ip->flags |= INFO_FLAG_SYSPEER;
822 		if (pp->flags & FLAG_CONFIG)
823 		    ip->flags |= INFO_FLAG_CONFIG;
824 		if (pp->flags & FLAG_REFCLOCK)
825 		    ip->flags |= INFO_FLAG_REFCLOCK;
826 		if (pp->flags & FLAG_AUTHENABLE)
827 		    ip->flags |= INFO_FLAG_AUTHENABLE;
828 		if (pp->flags & FLAG_PREFER)
829 		    ip->flags |= INFO_FLAG_PREFER;
830 		if (pp->flags & FLAG_BURST)
831 		    ip->flags |= INFO_FLAG_BURST;
832 		if (pp->status == CTL_PST_SEL_SYNCCAND)
833 		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
834 		if (pp->status >= CTL_PST_SEL_SYSPEER)
835 		    ip->flags |= INFO_FLAG_SHORTLIST;
836 		ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
837 		ip->timetosend = htonl(pp->nextdate - current_time);
838 		ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
839 		ip->sent = htonl((u_int32)(pp->sent));
840 		ip->processed = htonl((u_int32)(pp->processed));
841 		ip->badauth = htonl((u_int32)(pp->badauth));
842 		ip->bogusorg = htonl((u_int32)(pp->bogusorg));
843 		ip->oldpkt = htonl((u_int32)(pp->oldpkt));
844 		ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
845 		ip->selbroken = htonl((u_int32)(pp->selbroken));
846 		ip->candidate = pp->status;
847 		ip = (struct info_peer_stats *)more_pkt();
848 	}
849 	flush_pkt();
850 }
851 
852 
853 /*
854  * sys_info - return system info
855  */
856 static void
857 sys_info(
858 	struct sockaddr_in *srcadr,
859 	struct interface *inter,
860 	struct req_pkt *inpkt
861 	)
862 {
863 	register struct info_sys *is;
864 
865 	/*
866 	 * Importations from the protocol module
867 	 */
868 	extern u_char sys_leap;
869 	extern u_char sys_stratum;
870 	extern s_char sys_precision;
871 	extern double sys_rootdelay;
872 	extern double sys_rootdispersion;
873 	extern u_int32 sys_refid;
874 	extern l_fp sys_reftime;
875 	extern u_char sys_poll;
876 	extern struct peer *sys_peer;
877 	extern int sys_bclient;
878 	extern double sys_bdelay;
879 	extern l_fp sys_authdelay;
880 	extern double clock_stability;
881 	extern double sys_jitter;
882 
883 	is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
884 	    sizeof(struct info_sys));
885 
886 	if (sys_peer != 0) {
887 		is->peer = NSRCADR(&sys_peer->srcadr);
888 		is->peer_mode = sys_peer->hmode;
889 	} else {
890 		is->peer = 0;
891 		is->peer_mode = 0;
892 	}
893 	is->leap = sys_leap;
894 	is->stratum = sys_stratum;
895 	is->precision = sys_precision;
896 	is->rootdelay = htonl(DTOFP(sys_rootdelay));
897 	is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
898 	is->frequency = htonl(DTOFP(sys_jitter));
899 	is->stability = htonl(DTOUFP(clock_stability * 1e6));
900 	is->refid = sys_refid;
901 	HTONL_FP(&sys_reftime, &is->reftime);
902 
903 	is->poll = sys_poll;
904 
905 	is->flags = 0;
906 	if (sys_bclient)
907 	    is->flags |= INFO_FLAG_BCLIENT;
908 	if (sys_authenticate)
909 	    is->flags |= INFO_FLAG_AUTHENTICATE;
910 	if (kern_enable)
911 	    is->flags |= INFO_FLAG_KERNEL;
912 	if (ntp_enable)
913 	    is->flags |= INFO_FLAG_NTP;
914 	if (pll_control)
915 	    is->flags |= INFO_FLAG_PLL_SYNC;
916 	if (pps_control)
917 	    is->flags |= INFO_FLAG_PPS_SYNC;
918 	if (mon_enabled != MON_OFF)
919 	    is->flags |= INFO_FLAG_MONITOR;
920 	if (stats_control)
921 	    is->flags |= INFO_FLAG_FILEGEN;
922 	is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
923 	HTONL_UF(sys_authdelay.l_f, &is->authdelay);
924 
925 	(void) more_pkt();
926 	flush_pkt();
927 }
928 
929 
930 /*
931  * sys_stats - return system statistics
932  */
933 static void
934 sys_stats(
935 	struct sockaddr_in *srcadr,
936 	struct interface *inter,
937 	struct req_pkt *inpkt
938 	)
939 {
940 	register struct info_sys_stats *ss;
941 
942 	/*
943 	 * Importations from the protocol module
944 	 */
945 	extern u_long sys_stattime;
946 	extern u_long sys_badstratum;
947 	extern u_long sys_oldversionpkt;
948 	extern u_long sys_newversionpkt;
949 	extern u_long sys_unknownversion;
950 	extern u_long sys_badlength;
951 	extern u_long sys_processed;
952 	extern u_long sys_badauth;
953 	extern u_long sys_limitrejected;
954 
955 	ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
956 						  sizeof(struct info_sys_stats));
957 
958 	ss->timeup = htonl((u_int32)current_time);
959 	ss->timereset = htonl((u_int32)(current_time - sys_stattime));
960 	ss->badstratum = htonl((u_int32)sys_badstratum);
961 	ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt);
962 	ss->newversionpkt = htonl((u_int32)sys_newversionpkt);
963 	ss->unknownversion = htonl((u_int32)sys_unknownversion);
964 	ss->badlength = htonl((u_int32)sys_badlength);
965 	ss->processed = htonl((u_int32)sys_processed);
966 	ss->badauth = htonl((u_int32)sys_badauth);
967 	ss->limitrejected = htonl((u_int32)sys_limitrejected);
968 	(void) more_pkt();
969 	flush_pkt();
970 }
971 
972 
973 /*
974  * mem_stats - return memory statistics
975  */
976 static void
977 mem_stats(
978 	struct sockaddr_in *srcadr,
979 	struct interface *inter,
980 	struct req_pkt *inpkt
981 	)
982 {
983 	register struct info_mem_stats *ms;
984 	register int i;
985 
986 	/*
987 	 * Importations from the peer module
988 	 */
989 	extern int peer_hash_count[HASH_SIZE];
990 	extern int peer_free_count;
991 	extern u_long peer_timereset;
992 	extern u_long findpeer_calls;
993 	extern u_long peer_allocations;
994 	extern u_long peer_demobilizations;
995 	extern int total_peer_structs;
996 
997 	ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
998 						  sizeof(struct info_mem_stats));
999 
1000 	ms->timereset = htonl((u_int32)(current_time - peer_timereset));
1001 	ms->totalpeermem = htons((u_short)total_peer_structs);
1002 	ms->freepeermem = htons((u_short)peer_free_count);
1003 	ms->findpeer_calls = htonl((u_int32)findpeer_calls);
1004 	ms->allocations = htonl((u_int32)peer_allocations);
1005 	ms->demobilizations = htonl((u_int32)peer_demobilizations);
1006 
1007 	for (i = 0; i < HASH_SIZE; i++) {
1008 		if (peer_hash_count[i] > 255)
1009 		    ms->hashcount[i] = 255;
1010 		else
1011 		    ms->hashcount[i] = (u_char)peer_hash_count[i];
1012 	}
1013 
1014 	(void) more_pkt();
1015 	flush_pkt();
1016 }
1017 
1018 
1019 /*
1020  * io_stats - return io statistics
1021  */
1022 static void
1023 io_stats(
1024 	struct sockaddr_in *srcadr,
1025 	struct interface *inter,
1026 	struct req_pkt *inpkt
1027 	)
1028 {
1029 	register struct info_io_stats *io;
1030 
1031 	/*
1032 	 * Importations from the io module
1033 	 */
1034 	extern u_long io_timereset;
1035 
1036 	io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
1037 						 sizeof(struct info_io_stats));
1038 
1039 	io->timereset = htonl((u_int32)(current_time - io_timereset));
1040 	io->totalrecvbufs = htons((u_short) total_recvbuffs());
1041 	io->freerecvbufs = htons((u_short) free_recvbuffs());
1042 	io->fullrecvbufs = htons((u_short) full_recvbuffs());
1043 	io->lowwater = htons((u_short) lowater_additions());
1044 	io->dropped = htonl((u_int32)packets_dropped);
1045 	io->ignored = htonl((u_int32)packets_ignored);
1046 	io->received = htonl((u_int32)packets_received);
1047 	io->sent = htonl((u_int32)packets_sent);
1048 	io->notsent = htonl((u_int32)packets_notsent);
1049 	io->interrupts = htonl((u_int32)handler_calls);
1050 	io->int_received = htonl((u_int32)handler_pkts);
1051 
1052 	(void) more_pkt();
1053 	flush_pkt();
1054 }
1055 
1056 
1057 /*
1058  * timer_stats - return timer statistics
1059  */
1060 static void
1061 timer_stats(
1062 	struct sockaddr_in *srcadr,
1063 	struct interface *inter,
1064 	struct req_pkt *inpkt
1065 	)
1066 {
1067 	register struct info_timer_stats *ts;
1068 
1069 	/*
1070 	 * Importations from the timer module
1071 	 */
1072 	extern u_long timer_timereset;
1073 	extern u_long timer_overflows;
1074 	extern u_long timer_xmtcalls;
1075 
1076 	ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt,
1077 						    sizeof(struct info_timer_stats));
1078 
1079 	ts->timereset = htonl((u_int32)(current_time - timer_timereset));
1080 	ts->alarms = htonl((u_int32)alarm_overflow);
1081 	ts->overflows = htonl((u_int32)timer_overflows);
1082 	ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
1083 
1084 	(void) more_pkt();
1085 	flush_pkt();
1086 }
1087 
1088 
1089 /*
1090  * loop_info - return the current state of the loop filter
1091  */
1092 static void
1093 loop_info(
1094 	struct sockaddr_in *srcadr,
1095 	struct interface *inter,
1096 	struct req_pkt *inpkt
1097 	)
1098 {
1099 	register struct info_loop *li;
1100 	l_fp ltmp;
1101 
1102 	/*
1103 	 * Importations from the loop filter module
1104 	 */
1105 	extern double last_offset;
1106 	extern double drift_comp;
1107 	extern int tc_counter;
1108 	extern u_long last_time;
1109 
1110 	li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
1111 	    sizeof(struct info_loop));
1112 
1113 	DTOLFP(last_offset, &ltmp);
1114 	HTONL_FP(&ltmp, &li->last_offset);
1115 	DTOLFP(drift_comp * 1e6, &ltmp);
1116 	HTONL_FP(&ltmp, &li->drift_comp);
1117 	li->compliance = htonl((u_int32)(tc_counter));
1118 	li->watchdog_timer = htonl((u_int32)(current_time - last_time));
1119 
1120 	(void) more_pkt();
1121 	flush_pkt();
1122 }
1123 
1124 
1125 /*
1126  * do_conf - add a peer to the configuration list
1127  */
1128 static void
1129 do_conf(
1130 	struct sockaddr_in *srcadr,
1131 	struct interface *inter,
1132 	struct req_pkt *inpkt
1133 	)
1134 {
1135 	u_int fl;
1136 	register struct conf_peer *cp;
1137 	register int items;
1138 	struct sockaddr_in peeraddr;
1139 
1140 	/*
1141 	 * Do a check of everything to see that it looks
1142 	 * okay.  If not, complain about it.  Note we are
1143 	 * very picky here.
1144 	 */
1145 	items = INFO_NITEMS(inpkt->err_nitems);
1146 	cp = (struct conf_peer *)inpkt->data;
1147 
1148 	fl = 0;
1149 	while (items-- > 0 && !fl) {
1150 		if (((cp->version) > NTP_VERSION)
1151 		    || ((cp->version) < NTP_OLDVERSION))
1152 		    fl = 1;
1153 		if (cp->hmode != MODE_ACTIVE
1154 		    && cp->hmode != MODE_CLIENT
1155 		    && cp->hmode != MODE_BROADCAST)
1156 		    fl = 1;
1157 		if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER |
1158 		    CONF_FLAG_NOSELECT | CONF_FLAG_BURST | CONF_FLAG_IBURST |
1159 		    CONF_FLAG_SKEY))
1160 		    fl = 1;
1161 		cp++;
1162 	}
1163 
1164 	if (fl) {
1165 		msyslog(LOG_ERR, "do_conf: fl is nonzero!");
1166 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1167 		return;
1168 	}
1169 
1170 	/*
1171 	 * Looks okay, try it out
1172 	 */
1173 	items = INFO_NITEMS(inpkt->err_nitems);
1174 	cp = (struct conf_peer *)inpkt->data;
1175 	memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
1176 	peeraddr.sin_family = AF_INET;
1177 	peeraddr.sin_port = htons(NTP_PORT);
1178 
1179 	/*
1180 	 * Make sure the address is valid
1181 	 */
1182 	if (
1183 #ifdef REFCLOCK
1184 		!ISREFCLOCKADR(&peeraddr) &&
1185 #endif
1186 		ISBADADR(&peeraddr)) {
1187 #ifdef REFCLOCK
1188 		msyslog(LOG_ERR, "do_conf: !ISREFCLOCK && ISBADADR");
1189 #else
1190 		msyslog(LOG_ERR, "do_conf: ISBADADR");
1191 #endif
1192 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1193 		return;
1194 	}
1195 
1196 	while (items-- > 0) {
1197 		fl = 0;
1198 		if (cp->flags & CONF_FLAG_AUTHENABLE)
1199 			fl |= FLAG_AUTHENABLE;
1200 		if (cp->flags & CONF_FLAG_PREFER)
1201 			fl |= FLAG_PREFER;
1202 		if (cp->flags & CONF_FLAG_NOSELECT)
1203 			fl |= FLAG_NOSELECT;
1204 		if (cp->flags & CONF_FLAG_BURST)
1205 			fl |= FLAG_BURST;
1206 		if (cp->flags & CONF_FLAG_IBURST)
1207 			fl |= FLAG_IBURST;
1208 		if (cp->flags & CONF_FLAG_SKEY)
1209 			fl |= FLAG_SKEY;
1210 		peeraddr.sin_addr.s_addr = cp->peeraddr;
1211 		/* XXX W2DO? minpoll/maxpoll arguments ??? */
1212 		if (peer_config(&peeraddr, any_interface, cp->hmode,
1213 		    cp->version, cp->minpoll, cp->maxpoll, fl, cp->ttl,
1214 		    cp->keyid, cp->keystr) == 0) {
1215 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1216 			return;
1217 		}
1218 		cp++;
1219 	}
1220 
1221 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1222 }
1223 
1224 
1225 /*
1226  * dns_a - Snarf DNS info for an association ID
1227  */
1228 static void
1229 dns_a(
1230 	struct sockaddr_in *srcadr,
1231 	struct interface *inter,
1232 	struct req_pkt *inpkt
1233 	)
1234 {
1235 	register struct info_dns_assoc *dp;
1236 	register int items;
1237 	struct sockaddr_in peeraddr;
1238 
1239 	/*
1240 	 * Do a check of everything to see that it looks
1241 	 * okay.  If not, complain about it.  Note we are
1242 	 * very picky here.
1243 	 */
1244 	items = INFO_NITEMS(inpkt->err_nitems);
1245 	dp = (struct info_dns_assoc *)inpkt->data;
1246 
1247 	/*
1248 	 * Looks okay, try it out
1249 	 */
1250 	items = INFO_NITEMS(inpkt->err_nitems);
1251 	dp = (struct info_dns_assoc *)inpkt->data;
1252 	memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
1253 	peeraddr.sin_family = AF_INET;
1254 	peeraddr.sin_port = htons(NTP_PORT);
1255 
1256 	/*
1257 	 * Make sure the address is valid
1258 	 */
1259 	if (
1260 #ifdef REFCLOCK
1261 		!ISREFCLOCKADR(&peeraddr) &&
1262 #endif
1263 		ISBADADR(&peeraddr)) {
1264 #ifdef REFCLOCK
1265 		msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
1266 #else
1267 		msyslog(LOG_ERR, "dns_a: ISBADADR");
1268 #endif
1269 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1270 		return;
1271 	}
1272 
1273 	while (items-- > 0) {
1274 		associd_t associd;
1275 		size_t hnl;
1276 		struct peer *peer;
1277 		int bogon = 0;
1278 
1279 		associd = dp->associd;
1280 		peer = findpeerbyassoc(associd);
1281 		if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
1282 			msyslog(LOG_ERR, "dns_a: %s",
1283 				(peer == 0)
1284 				? "peer == 0"
1285 				: "peer->flags & FLAG_REFCLOCK");
1286 			++bogon;
1287 		}
1288 		peeraddr.sin_addr.s_addr = dp->peeraddr;
1289 		for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
1290 		if (hnl >= sizeof dp->hostname) {
1291 			msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
1292 				(long)hnl, (long)sizeof dp->hostname);
1293 			++bogon;
1294 		}
1295 
1296 		msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
1297 			dp->hostname, inet_ntoa(peeraddr.sin_addr), associd,
1298 			bogon);
1299 
1300 		if (bogon) {
1301 			/* If it didn't work */
1302 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1303 			return;
1304 		} else {
1305 #if 0
1306 #ifdef PUBKEY
1307 			crypto_public(peer, dp->hostname);
1308 #endif /* PUBKEY */
1309 #endif
1310 		}
1311 
1312 		dp++;
1313 	}
1314 
1315 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1316 }
1317 
1318 
1319 /*
1320  * do_unconf - remove a peer from the configuration list
1321  */
1322 static void
1323 do_unconf(
1324 	struct sockaddr_in *srcadr,
1325 	struct interface *inter,
1326 	struct req_pkt *inpkt
1327 	)
1328 {
1329 	register struct conf_unpeer *cp;
1330 	register int items;
1331 	register struct peer *peer;
1332 	struct sockaddr_in peeraddr;
1333 	int bad, found;
1334 
1335 	/*
1336 	 * This is a bit unstructured, but I like to be careful.
1337 	 * We check to see that every peer exists and is actually
1338 	 * configured.  If so, we remove them.  If not, we return
1339 	 * an error.
1340 	 */
1341 	peeraddr.sin_family = AF_INET;
1342 	peeraddr.sin_port = htons(NTP_PORT);
1343 
1344 	items = INFO_NITEMS(inpkt->err_nitems);
1345 	cp = (struct conf_unpeer *)inpkt->data;
1346 
1347 	bad = 0;
1348 	while (items-- > 0 && !bad) {
1349 		peeraddr.sin_addr.s_addr = cp->peeraddr;
1350 		found = 0;
1351 		peer = (struct peer *)0;
1352 		while (!found) {
1353 			peer = findexistingpeer(&peeraddr, peer, -1);
1354 			if (peer == (struct peer *)0)
1355 			    break;
1356 			if (peer->flags & FLAG_CONFIG)
1357 			    found = 1;
1358 		}
1359 		if (!found)
1360 		    bad = 1;
1361 		cp++;
1362 	}
1363 
1364 	if (bad) {
1365 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1366 		return;
1367 	}
1368 
1369 	/*
1370 	 * Now do it in earnest.
1371 	 */
1372 
1373 	items = INFO_NITEMS(inpkt->err_nitems);
1374 	cp = (struct conf_unpeer *)inpkt->data;
1375 	while (items-- > 0) {
1376 		peeraddr.sin_addr.s_addr = cp->peeraddr;
1377 		peer_unconfig(&peeraddr, (struct interface *)0, -1);
1378 		cp++;
1379 	}
1380 
1381 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1382 }
1383 
1384 
1385 /*
1386  * set_sys_flag - set system flags
1387  */
1388 static void
1389 set_sys_flag(
1390 	struct sockaddr_in *srcadr,
1391 	struct interface *inter,
1392 	struct req_pkt *inpkt
1393 	)
1394 {
1395 	setclr_flags(srcadr, inter, inpkt, 1);
1396 }
1397 
1398 
1399 /*
1400  * clr_sys_flag - clear system flags
1401  */
1402 static void
1403 clr_sys_flag(
1404 	struct sockaddr_in *srcadr,
1405 	struct interface *inter,
1406 	struct req_pkt *inpkt
1407 	)
1408 {
1409 	setclr_flags(srcadr, inter, inpkt, 0);
1410 }
1411 
1412 
1413 /*
1414  * setclr_flags - do the grunge work of flag setting/clearing
1415  */
1416 static void
1417 setclr_flags(
1418 	struct sockaddr_in *srcadr,
1419 	struct interface *inter,
1420 	struct req_pkt *inpkt,
1421 	u_long set
1422 	)
1423 {
1424 	register u_int flags;
1425 
1426 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1427 		msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
1428 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1429 		return;
1430 	}
1431 
1432 	flags = ((struct conf_sys_flags *)inpkt->data)->flags;
1433 
1434 	if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1435 		      SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
1436 		      SYS_FLAG_FILEGEN)) {
1437 		msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
1438 			flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1439 				  SYS_FLAG_NTP | SYS_FLAG_KERNEL |
1440 				  SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN));
1441 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1442 		return;
1443 	}
1444 
1445 	if (flags & SYS_FLAG_BCLIENT)
1446 	    proto_config(PROTO_BROADCLIENT, set, 0.);
1447 	if (flags & SYS_FLAG_PPS)
1448 	    proto_config(PROTO_PPS, set, 0.);
1449 	if (flags & SYS_FLAG_NTP)
1450 	    proto_config(PROTO_NTP, set, 0.);
1451 	if (flags & SYS_FLAG_KERNEL)
1452 	    proto_config(PROTO_KERNEL, set, 0.);
1453 	if (flags & SYS_FLAG_MONITOR)
1454 	    proto_config(PROTO_MONITOR, set, 0.);
1455 	if (flags & SYS_FLAG_FILEGEN)
1456 	    proto_config(PROTO_FILEGEN, set, 0.);
1457 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1458 }
1459 
1460 
1461 /*
1462  * list_restrict - return the restrict list
1463  */
1464 static void
1465 list_restrict(
1466 	struct sockaddr_in *srcadr,
1467 	struct interface *inter,
1468 	struct req_pkt *inpkt
1469 	)
1470 {
1471 	register struct info_restrict *ir;
1472 	register struct restrictlist *rl;
1473 	extern struct restrictlist *restrictlist;
1474 
1475 #ifdef DEBUG
1476 	if (debug > 2)
1477 	    printf("wants peer list summary\n");
1478 #endif
1479 
1480 	ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
1481 						 sizeof(struct info_restrict));
1482 	for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
1483 		ir->addr = htonl(rl->addr);
1484 		ir->mask = htonl(rl->mask);
1485 		ir->count = htonl((u_int32)rl->count);
1486 		ir->flags = htons(rl->flags);
1487 		ir->mflags = htons(rl->mflags);
1488 		ir = (struct info_restrict *)more_pkt();
1489 	}
1490 	flush_pkt();
1491 }
1492 
1493 
1494 
1495 /*
1496  * do_resaddflags - add flags to a restrict entry (or create one)
1497  */
1498 static void
1499 do_resaddflags(
1500 	struct sockaddr_in *srcadr,
1501 	struct interface *inter,
1502 	struct req_pkt *inpkt
1503 	)
1504 {
1505 	do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
1506 }
1507 
1508 
1509 
1510 /*
1511  * do_ressubflags - remove flags from a restrict entry
1512  */
1513 static void
1514 do_ressubflags(
1515 	struct sockaddr_in *srcadr,
1516 	struct interface *inter,
1517 	struct req_pkt *inpkt
1518 	)
1519 {
1520 	do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
1521 }
1522 
1523 
1524 /*
1525  * do_unrestrict - remove a restrict entry from the list
1526  */
1527 static void
1528 do_unrestrict(
1529 	struct sockaddr_in *srcadr,
1530 	struct interface *inter,
1531 	struct req_pkt *inpkt
1532 	)
1533 {
1534 	do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
1535 }
1536 
1537 
1538 
1539 
1540 
1541 /*
1542  * do_restrict - do the dirty stuff of dealing with restrictions
1543  */
1544 static void
1545 do_restrict(
1546 	struct sockaddr_in *srcadr,
1547 	struct interface *inter,
1548 	struct req_pkt *inpkt,
1549 	int op
1550 	)
1551 {
1552 	register struct conf_restrict *cr;
1553 	register int items;
1554 	struct sockaddr_in matchaddr;
1555 	struct sockaddr_in matchmask;
1556 	int bad;
1557 
1558 	/*
1559 	 * Do a check of the flags to make sure that only
1560 	 * the NTPPORT flag is set, if any.  If not, complain
1561 	 * about it.  Note we are very picky here.
1562 	 */
1563 	items = INFO_NITEMS(inpkt->err_nitems);
1564 	cr = (struct conf_restrict *)inpkt->data;
1565 
1566 	bad = 0;
1567 	while (items-- > 0 && !bad) {
1568 		if (cr->mflags & ~(RESM_NTPONLY))
1569 		    bad |= 1;
1570 		if (cr->flags & ~(RES_ALLFLAGS))
1571 		    bad |= 2;
1572 		if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY))
1573 		    bad |= 4;
1574 		cr++;
1575 	}
1576 
1577 	if (bad) {
1578 		msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
1579 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1580 		return;
1581 	}
1582 
1583 	/*
1584 	 * Looks okay, try it out
1585 	 */
1586 	items = INFO_NITEMS(inpkt->err_nitems);
1587 	cr = (struct conf_restrict *)inpkt->data;
1588 	memset((char *)&matchaddr, 0, sizeof(struct sockaddr_in));
1589 	memset((char *)&matchmask, 0, sizeof(struct sockaddr_in));
1590 	matchaddr.sin_family = AF_INET;
1591 	matchmask.sin_family = AF_INET;
1592 
1593 	while (items-- > 0) {
1594 		matchaddr.sin_addr.s_addr = cr->addr;
1595 		matchmask.sin_addr.s_addr = cr->mask;
1596 		hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
1597 			 cr->flags);
1598 		cr++;
1599 	}
1600 
1601 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1602 }
1603 
1604 
1605 /*
1606  * mon_getlist - return monitor data
1607  */
1608 static void
1609 mon_getlist_0(
1610 	struct sockaddr_in *srcadr,
1611 	struct interface *inter,
1612 	struct req_pkt *inpkt
1613 	)
1614 {
1615 	register struct info_monitor *im;
1616 	register struct mon_data *md;
1617 	extern struct mon_data mon_mru_list;
1618 	extern int mon_enabled;
1619 
1620 #ifdef DEBUG
1621 	if (debug > 2)
1622 	    printf("wants monitor 0 list\n");
1623 #endif
1624 	if (!mon_enabled) {
1625 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1626 		return;
1627 	}
1628 
1629 	im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
1630 						sizeof(struct info_monitor));
1631 	for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1632 	     md = md->mru_next) {
1633 		im->lasttime = htonl((u_int32)(current_time - md->lasttime));
1634 		im->firsttime = htonl((u_int32)(current_time - md->firsttime));
1635 		if (md->lastdrop)
1636 		    im->lastdrop = htonl((u_int32)(current_time - md->lastdrop));
1637 		else
1638 		    im->lastdrop = 0;
1639 		im->count = htonl((u_int32)(md->count));
1640 		im->addr = md->rmtadr;
1641 		im->port = md->rmtport;
1642 		im->mode = md->mode;
1643 		im->version = md->version;
1644 		im = (struct info_monitor *)more_pkt();
1645 	}
1646 	flush_pkt();
1647 }
1648 
1649 /*
1650  * mon_getlist - return monitor data
1651  */
1652 static void
1653 mon_getlist_1(
1654 	struct sockaddr_in *srcadr,
1655 	struct interface *inter,
1656 	struct req_pkt *inpkt
1657 	)
1658 {
1659 	register struct info_monitor_1 *im;
1660 	register struct mon_data *md;
1661 	extern struct mon_data mon_mru_list;
1662 	extern int mon_enabled;
1663 
1664 #ifdef DEBUG
1665 	if (debug > 2)
1666 	    printf("wants monitor 1 list\n");
1667 #endif
1668 	if (!mon_enabled) {
1669 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1670 		return;
1671 	}
1672 
1673 	im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
1674 						  sizeof(struct info_monitor_1));
1675 	for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1676 	     md = md->mru_next) {
1677 		im->lasttime = htonl((u_int32)(current_time - md->lasttime));
1678 		im->firsttime = htonl((u_int32)(current_time - md->firsttime));
1679 		if (md->lastdrop)
1680 		    im->lastdrop = htonl((u_int32)(current_time - md->lastdrop));
1681 		else
1682 		    im->lastdrop = 0;
1683 		im->count = htonl((u_int32)md->count);
1684 		im->addr = md->rmtadr;
1685 		im->daddr =
1686 		    (md->cast_flags == MDF_BCAST)
1687 		    ? md->interface->bcast.sin_addr.s_addr
1688 		    : (md->cast_flags
1689 		       ? (md->interface->sin.sin_addr.s_addr
1690 		          ? md->interface->sin.sin_addr.s_addr
1691 			  : md->interface->bcast.sin_addr.s_addr
1692 			  )
1693 		       : 4);
1694 		im->flags = md->cast_flags;
1695 		im->port = md->rmtport;
1696 		im->mode = md->mode;
1697 		im->version = md->version;
1698 		im = (struct info_monitor_1 *)more_pkt();
1699 	}
1700 	flush_pkt();
1701 }
1702 
1703 /*
1704  * Module entry points and the flags they correspond with
1705  */
1706 struct reset_entry {
1707 	int flag;		/* flag this corresponds to */
1708 	void (*handler) P((void)); /* routine to handle request */
1709 };
1710 
1711 struct reset_entry reset_entries[] = {
1712 	{ RESET_FLAG_ALLPEERS,	peer_all_reset },
1713 	{ RESET_FLAG_IO,	io_clr_stats },
1714 	{ RESET_FLAG_SYS,	proto_clr_stats },
1715 	{ RESET_FLAG_MEM,	peer_clr_stats },
1716 	{ RESET_FLAG_TIMER,	timer_clr_stats },
1717 	{ RESET_FLAG_AUTH,	reset_auth_stats },
1718 	{ RESET_FLAG_CTL,	ctl_clr_stats },
1719 	{ 0,			0 }
1720 };
1721 
1722 /*
1723  * reset_stats - reset statistic counters here and there
1724  */
1725 static void
1726 reset_stats(
1727 	struct sockaddr_in *srcadr,
1728 	struct interface *inter,
1729 	struct req_pkt *inpkt
1730 	)
1731 {
1732 	u_long flags;
1733 	struct reset_entry *rent;
1734 
1735 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1736 		msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
1737 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1738 		return;
1739 	}
1740 
1741 	flags = ((struct reset_flags *)inpkt->data)->flags;
1742 
1743 	if (flags & ~RESET_ALLFLAGS) {
1744 		msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
1745 			flags & ~RESET_ALLFLAGS);
1746 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1747 		return;
1748 	}
1749 
1750 	for (rent = reset_entries; rent->flag != 0; rent++) {
1751 		if (flags & rent->flag)
1752 		    (rent->handler)();
1753 	}
1754 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1755 }
1756 
1757 
1758 /*
1759  * reset_peer - clear a peer's statistics
1760  */
1761 static void
1762 reset_peer(
1763 	struct sockaddr_in *srcadr,
1764 	struct interface *inter,
1765 	struct req_pkt *inpkt
1766 	)
1767 {
1768 	register struct conf_unpeer *cp;
1769 	register int items;
1770 	register struct peer *peer;
1771 	struct sockaddr_in peeraddr;
1772 	int bad;
1773 
1774 	/*
1775 	 * We check first to see that every peer exists.  If not,
1776 	 * we return an error.
1777 	 */
1778 	peeraddr.sin_family = AF_INET;
1779 	peeraddr.sin_port = htons(NTP_PORT);
1780 
1781 	items = INFO_NITEMS(inpkt->err_nitems);
1782 	cp = (struct conf_unpeer *)inpkt->data;
1783 
1784 	bad = 0;
1785 	while (items-- > 0 && !bad) {
1786 		peeraddr.sin_addr.s_addr = cp->peeraddr;
1787 		peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
1788 		if (peer == (struct peer *)0)
1789 		    bad++;
1790 		cp++;
1791 	}
1792 
1793 	if (bad) {
1794 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1795 		return;
1796 	}
1797 
1798 	/*
1799 	 * Now do it in earnest.
1800 	 */
1801 
1802 	items = INFO_NITEMS(inpkt->err_nitems);
1803 	cp = (struct conf_unpeer *)inpkt->data;
1804 	while (items-- > 0) {
1805 		peeraddr.sin_addr.s_addr = cp->peeraddr;
1806 		peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
1807 		while (peer != 0) {
1808 			peer_reset(peer);
1809 			peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1);
1810 		}
1811 		cp++;
1812 	}
1813 
1814 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1815 }
1816 
1817 
1818 /*
1819  * do_key_reread - reread the encryption key file
1820  */
1821 static void
1822 do_key_reread(
1823 	struct sockaddr_in *srcadr,
1824 	struct interface *inter,
1825 	struct req_pkt *inpkt
1826 	)
1827 {
1828 	rereadkeys();
1829 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1830 }
1831 
1832 
1833 /*
1834  * trust_key - make one or more keys trusted
1835  */
1836 static void
1837 trust_key(
1838 	struct sockaddr_in *srcadr,
1839 	struct interface *inter,
1840 	struct req_pkt *inpkt
1841 	)
1842 {
1843 	do_trustkey(srcadr, inter, inpkt, 1);
1844 }
1845 
1846 
1847 /*
1848  * untrust_key - make one or more keys untrusted
1849  */
1850 static void
1851 untrust_key(
1852 	struct sockaddr_in *srcadr,
1853 	struct interface *inter,
1854 	struct req_pkt *inpkt
1855 	)
1856 {
1857 	do_trustkey(srcadr, inter, inpkt, 0);
1858 }
1859 
1860 
1861 /*
1862  * do_trustkey - make keys either trustable or untrustable
1863  */
1864 static void
1865 do_trustkey(
1866 	struct sockaddr_in *srcadr,
1867 	struct interface *inter,
1868 	struct req_pkt *inpkt,
1869 	u_long trust
1870 	)
1871 {
1872 	register u_long *kp;
1873 	register int items;
1874 
1875 	items = INFO_NITEMS(inpkt->err_nitems);
1876 	kp = (u_long *)inpkt->data;
1877 	while (items-- > 0) {
1878 		authtrust(*kp, trust);
1879 		kp++;
1880 	}
1881 
1882 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1883 }
1884 
1885 
1886 /*
1887  * get_auth_info - return some stats concerning the authentication module
1888  */
1889 static void
1890 get_auth_info(
1891 	struct sockaddr_in *srcadr,
1892 	struct interface *inter,
1893 	struct req_pkt *inpkt
1894 	)
1895 {
1896 	register struct info_auth *ia;
1897 
1898 	/*
1899 	 * Importations from the authentication module
1900 	 */
1901 	extern u_long authnumkeys;
1902 	extern int authnumfreekeys;
1903 	extern u_long authkeylookups;
1904 	extern u_long authkeynotfound;
1905 	extern u_long authencryptions;
1906 	extern u_long authdecryptions;
1907 	extern u_long authkeyuncached;
1908 	extern u_long authkeyexpired;
1909 
1910 	ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
1911 					     sizeof(struct info_auth));
1912 
1913 	ia->numkeys = htonl((u_int32)authnumkeys);
1914 	ia->numfreekeys = htonl((u_int32)authnumfreekeys);
1915 	ia->keylookups = htonl((u_int32)authkeylookups);
1916 	ia->keynotfound = htonl((u_int32)authkeynotfound);
1917 	ia->encryptions = htonl((u_int32)authencryptions);
1918 	ia->decryptions = htonl((u_int32)authdecryptions);
1919 	ia->keyuncached = htonl((u_int32)authkeyuncached);
1920 	ia->expired = htonl((u_int32)authkeyexpired);
1921 	ia->timereset = htonl((u_int32)(current_time - auth_timereset));
1922 
1923 	(void) more_pkt();
1924 	flush_pkt();
1925 }
1926 
1927 
1928 
1929 /*
1930  * reset_auth_stats - reset the authentication stat counters.  Done here
1931  *		      to keep ntp-isms out of the authentication module
1932  */
1933 static void
1934 reset_auth_stats(void)
1935 {
1936 	/*
1937 	 * Importations from the authentication module
1938 	 */
1939 	extern u_long authkeylookups;
1940 	extern u_long authkeynotfound;
1941 	extern u_long authencryptions;
1942 	extern u_long authdecryptions;
1943 	extern u_long authkeyuncached;
1944 
1945 	authkeylookups = 0;
1946 	authkeynotfound = 0;
1947 	authencryptions = 0;
1948 	authdecryptions = 0;
1949 	authkeyuncached = 0;
1950 	auth_timereset = current_time;
1951 }
1952 
1953 
1954 /*
1955  * req_get_traps - return information about current trap holders
1956  */
1957 static void
1958 req_get_traps(
1959 	struct sockaddr_in *srcadr,
1960 	struct interface *inter,
1961 	struct req_pkt *inpkt
1962 	)
1963 {
1964 	register struct info_trap *it;
1965 	register struct ctl_trap *tr;
1966 	register int i;
1967 
1968 	/*
1969 	 * Imported from the control module
1970 	 */
1971 	extern struct ctl_trap ctl_trap[];
1972 	extern int num_ctl_traps;
1973 
1974 	if (num_ctl_traps == 0) {
1975 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1976 		return;
1977 	}
1978 
1979 	it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
1980 					     sizeof(struct info_trap));
1981 
1982 	for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
1983 		if (tr->tr_flags & TRAP_INUSE) {
1984 			if (tr->tr_localaddr == any_interface)
1985 			    it->local_address = 0;
1986 			else
1987 			    it->local_address
1988 				    = NSRCADR(&tr->tr_localaddr->sin);
1989 			it->trap_address = NSRCADR(&tr->tr_addr);
1990 			it->trap_port = NSRCPORT(&tr->tr_addr);
1991 			it->sequence = htons(tr->tr_sequence);
1992 			it->settime = htonl((u_int32)(current_time - tr->tr_settime));
1993 			it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
1994 			it->resets = htonl((u_int32)tr->tr_resets);
1995 			it->flags = htonl((u_int32)tr->tr_flags);
1996 			it = (struct info_trap *)more_pkt();
1997 		}
1998 	}
1999 	flush_pkt();
2000 }
2001 
2002 
2003 /*
2004  * req_set_trap - configure a trap
2005  */
2006 static void
2007 req_set_trap(
2008 	struct sockaddr_in *srcadr,
2009 	struct interface *inter,
2010 	struct req_pkt *inpkt
2011 	)
2012 {
2013 	do_setclr_trap(srcadr, inter, inpkt, 1);
2014 }
2015 
2016 
2017 
2018 /*
2019  * req_clr_trap - unconfigure a trap
2020  */
2021 static void
2022 req_clr_trap(
2023 	struct sockaddr_in *srcadr,
2024 	struct interface *inter,
2025 	struct req_pkt *inpkt
2026 	)
2027 {
2028 	do_setclr_trap(srcadr, inter, inpkt, 0);
2029 }
2030 
2031 
2032 
2033 /*
2034  * do_setclr_trap - do the grunge work of (un)configuring a trap
2035  */
2036 static void
2037 do_setclr_trap(
2038 	struct sockaddr_in *srcadr,
2039 	struct interface *inter,
2040 	struct req_pkt *inpkt,
2041 	int set
2042 	)
2043 {
2044 	register struct conf_trap *ct;
2045 	register struct interface *linter;
2046 	int res;
2047 	struct sockaddr_in laddr;
2048 
2049 	/*
2050 	 * Prepare sockaddr_in structure
2051 	 */
2052 	memset((char *)&laddr, 0, sizeof laddr);
2053 	laddr.sin_family = AF_INET;
2054 	laddr.sin_port = ntohs(NTP_PORT);
2055 
2056 	/*
2057 	 * Restrict ourselves to one item only.  This eliminates
2058 	 * the error reporting problem.
2059 	 */
2060 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2061 		msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
2062 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2063 		return;
2064 	}
2065 	ct = (struct conf_trap *)inpkt->data;
2066 
2067 	/*
2068 	 * Look for the local interface.  If none, use the default.
2069 	 */
2070 	if (ct->local_address == 0) {
2071 		linter = any_interface;
2072 	} else {
2073 		laddr.sin_addr.s_addr = ct->local_address;
2074 		linter = findinterface(&laddr);
2075 		if (linter == NULL) {
2076 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2077 			return;
2078 		}
2079 	}
2080 
2081 	laddr.sin_addr.s_addr = ct->trap_address;
2082 	if (ct->trap_port != 0)
2083 	    laddr.sin_port = ct->trap_port;
2084 	else
2085 	    laddr.sin_port = htons(TRAPPORT);
2086 
2087 	if (set) {
2088 		res = ctlsettrap(&laddr, linter, 0,
2089 				 INFO_VERSION(inpkt->rm_vn_mode));
2090 	} else {
2091 		res = ctlclrtrap(&laddr, linter, 0);
2092 	}
2093 
2094 	if (!res) {
2095 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2096 	} else {
2097 		req_ack(srcadr, inter, inpkt, INFO_OKAY);
2098 	}
2099 	return;
2100 }
2101 
2102 
2103 
2104 /*
2105  * set_request_keyid - set the keyid used to authenticate requests
2106  */
2107 static void
2108 set_request_keyid(
2109 	struct sockaddr_in *srcadr,
2110 	struct interface *inter,
2111 	struct req_pkt *inpkt
2112 	)
2113 {
2114 	keyid_t keyid;
2115 
2116 	/*
2117 	 * Restrict ourselves to one item only.
2118 	 */
2119 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2120 		msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
2121 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2122 		return;
2123 	}
2124 
2125 	keyid = ntohl(*((u_int32 *)(inpkt->data)));
2126 	info_auth_keyid = keyid;
2127 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2128 }
2129 
2130 
2131 
2132 /*
2133  * set_control_keyid - set the keyid used to authenticate requests
2134  */
2135 static void
2136 set_control_keyid(
2137 	struct sockaddr_in *srcadr,
2138 	struct interface *inter,
2139 	struct req_pkt *inpkt
2140 	)
2141 {
2142 	keyid_t keyid;
2143 	extern keyid_t ctl_auth_keyid;
2144 
2145 	/*
2146 	 * Restrict ourselves to one item only.
2147 	 */
2148 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2149 		msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
2150 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2151 		return;
2152 	}
2153 
2154 	keyid = ntohl(*((u_int32 *)(inpkt->data)));
2155 	ctl_auth_keyid = keyid;
2156 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2157 }
2158 
2159 
2160 
2161 /*
2162  * get_ctl_stats - return some stats concerning the control message module
2163  */
2164 static void
2165 get_ctl_stats(
2166 	struct sockaddr_in *srcadr,
2167 	struct interface *inter,
2168 	struct req_pkt *inpkt
2169 	)
2170 {
2171 	register struct info_control *ic;
2172 
2173 	/*
2174 	 * Importations from the control module
2175 	 */
2176 	extern u_long ctltimereset;
2177 	extern u_long numctlreq;
2178 	extern u_long numctlbadpkts;
2179 	extern u_long numctlresponses;
2180 	extern u_long numctlfrags;
2181 	extern u_long numctlerrors;
2182 	extern u_long numctltooshort;
2183 	extern u_long numctlinputresp;
2184 	extern u_long numctlinputfrag;
2185 	extern u_long numctlinputerr;
2186 	extern u_long numctlbadoffset;
2187 	extern u_long numctlbadversion;
2188 	extern u_long numctldatatooshort;
2189 	extern u_long numctlbadop;
2190 	extern u_long numasyncmsgs;
2191 
2192 	ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
2193 						sizeof(struct info_control));
2194 
2195 	ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
2196 	ic->numctlreq = htonl((u_int32)numctlreq);
2197 	ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
2198 	ic->numctlresponses = htonl((u_int32)numctlresponses);
2199 	ic->numctlfrags = htonl((u_int32)numctlfrags);
2200 	ic->numctlerrors = htonl((u_int32)numctlerrors);
2201 	ic->numctltooshort = htonl((u_int32)numctltooshort);
2202 	ic->numctlinputresp = htonl((u_int32)numctlinputresp);
2203 	ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
2204 	ic->numctlinputerr = htonl((u_int32)numctlinputerr);
2205 	ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
2206 	ic->numctlbadversion = htonl((u_int32)numctlbadversion);
2207 	ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
2208 	ic->numctlbadop = htonl((u_int32)numctlbadop);
2209 	ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
2210 
2211 	(void) more_pkt();
2212 	flush_pkt();
2213 }
2214 
2215 
2216 #ifdef KERNEL_PLL
2217 /*
2218  * get_kernel_info - get kernel pll/pps information
2219  */
2220 static void
2221 get_kernel_info(
2222 	struct sockaddr_in *srcadr,
2223 	struct interface *inter,
2224 	struct req_pkt *inpkt
2225 	)
2226 {
2227 	register struct info_kernel *ik;
2228 	struct timex ntx;
2229 
2230 	if (!pll_control) {
2231 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2232 		return;
2233 	}
2234 
2235 	memset((char *)&ntx, 0, sizeof(ntx));
2236 	if (ntp_adjtime(&ntx) < 0)
2237 		msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
2238 	ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
2239 	    sizeof(struct info_kernel));
2240 
2241 	/*
2242 	 * pll variables
2243 	 */
2244 	ik->offset = htonl((u_int32)ntx.offset);
2245 	ik->freq = htonl((u_int32)ntx.freq);
2246 	ik->maxerror = htonl((u_int32)ntx.maxerror);
2247 	ik->esterror = htonl((u_int32)ntx.esterror);
2248 	ik->status = htons(ntx.status);
2249 	ik->constant = htonl((u_int32)ntx.constant);
2250 	ik->precision = htonl((u_int32)ntx.precision);
2251 	ik->tolerance = htonl((u_int32)ntx.tolerance);
2252 
2253 	/*
2254 	 * pps variables
2255 	 */
2256 	ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
2257 	ik->jitter = htonl((u_int32)ntx.jitter);
2258 	ik->shift = htons(ntx.shift);
2259 	ik->stabil = htonl((u_int32)ntx.stabil);
2260 	ik->jitcnt = htonl((u_int32)ntx.jitcnt);
2261 	ik->calcnt = htonl((u_int32)ntx.calcnt);
2262 	ik->errcnt = htonl((u_int32)ntx.errcnt);
2263 	ik->stbcnt = htonl((u_int32)ntx.stbcnt);
2264 
2265 	(void) more_pkt();
2266 	flush_pkt();
2267 }
2268 #endif /* KERNEL_PLL */
2269 
2270 
2271 #ifdef REFCLOCK
2272 /*
2273  * get_clock_info - get info about a clock
2274  */
2275 static void
2276 get_clock_info(
2277 	struct sockaddr_in *srcadr,
2278 	struct interface *inter,
2279 	struct req_pkt *inpkt
2280 	)
2281 {
2282 	register struct info_clock *ic;
2283 	register u_int32 *clkaddr;
2284 	register int items;
2285 	struct refclockstat clock_stat;
2286 	struct sockaddr_in addr;
2287 	l_fp ltmp;
2288 
2289 	memset((char *)&addr, 0, sizeof addr);
2290 	addr.sin_family = AF_INET;
2291 	addr.sin_port = htons(NTP_PORT);
2292 	items = INFO_NITEMS(inpkt->err_nitems);
2293 	clkaddr = (u_int32 *) inpkt->data;
2294 
2295 	ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
2296 					      sizeof(struct info_clock));
2297 
2298 	while (items-- > 0) {
2299 		addr.sin_addr.s_addr = *clkaddr++;
2300 		if (!ISREFCLOCKADR(&addr) ||
2301 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2302 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2303 			return;
2304 		}
2305 
2306 		clock_stat.kv_list = (struct ctl_var *)0;
2307 
2308 		refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
2309 
2310 		ic->clockadr = addr.sin_addr.s_addr;
2311 		ic->type = clock_stat.type;
2312 		ic->flags = clock_stat.flags;
2313 		ic->lastevent = clock_stat.lastevent;
2314 		ic->currentstatus = clock_stat.currentstatus;
2315 		ic->polls = htonl((u_int32)clock_stat.polls);
2316 		ic->noresponse = htonl((u_int32)clock_stat.noresponse);
2317 		ic->badformat = htonl((u_int32)clock_stat.badformat);
2318 		ic->baddata = htonl((u_int32)clock_stat.baddata);
2319 		ic->timestarted = htonl((u_int32)clock_stat.timereset);
2320 		DTOLFP(clock_stat.fudgetime1, &ltmp);
2321 		HTONL_FP(&ltmp, &ic->fudgetime1);
2322 		DTOLFP(clock_stat.fudgetime1, &ltmp);
2323 		HTONL_FP(&ltmp, &ic->fudgetime2);
2324 		ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
2325 		ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2);
2326 
2327 		free_varlist(clock_stat.kv_list);
2328 
2329 		ic = (struct info_clock *)more_pkt();
2330 	}
2331 	flush_pkt();
2332 }
2333 
2334 
2335 
2336 /*
2337  * set_clock_fudge - get a clock's fudge factors
2338  */
2339 static void
2340 set_clock_fudge(
2341 	struct sockaddr_in *srcadr,
2342 	struct interface *inter,
2343 	struct req_pkt *inpkt
2344 	)
2345 {
2346 	register struct conf_fudge *cf;
2347 	register int items;
2348 	struct refclockstat clock_stat;
2349 	struct sockaddr_in addr;
2350 	l_fp ltmp;
2351 
2352 	memset((char *)&addr, 0, sizeof addr);
2353 	memset((char *)&clock_stat, 0, sizeof clock_stat);
2354 	addr.sin_family = AF_INET;
2355 	addr.sin_port = htons(NTP_PORT);
2356 	items = INFO_NITEMS(inpkt->err_nitems);
2357 	cf = (struct conf_fudge *) inpkt->data;
2358 
2359 	while (items-- > 0) {
2360 		addr.sin_addr.s_addr = cf->clockadr;
2361 		if (!ISREFCLOCKADR(&addr) ||
2362 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2363 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2364 			return;
2365 		}
2366 
2367 		switch(ntohl(cf->which)) {
2368 		    case FUDGE_TIME1:
2369 			NTOHL_FP(&cf->fudgetime, &ltmp);
2370 			LFPTOD(&ltmp, clock_stat.fudgetime1);
2371 			clock_stat.haveflags = CLK_HAVETIME1;
2372 			break;
2373 		    case FUDGE_TIME2:
2374 			NTOHL_FP(&cf->fudgetime, &ltmp);
2375 			LFPTOD(&ltmp, clock_stat.fudgetime2);
2376 			clock_stat.haveflags = CLK_HAVETIME2;
2377 			break;
2378 		    case FUDGE_VAL1:
2379 			clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
2380 			clock_stat.haveflags = CLK_HAVEVAL1;
2381 			break;
2382 		    case FUDGE_VAL2:
2383 			clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
2384 			clock_stat.haveflags = CLK_HAVEVAL2;
2385 			break;
2386 		    case FUDGE_FLAGS:
2387 			clock_stat.flags = (u_char) ntohl(cf->fudgeval_flags) & 0xf;
2388 			clock_stat.haveflags =
2389 				(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
2390 			break;
2391 		    default:
2392 			msyslog(LOG_ERR, "set_clock_fudge: default!");
2393 			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2394 			return;
2395 		}
2396 
2397 		refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
2398 	}
2399 
2400 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2401 }
2402 #endif
2403 
2404 #ifdef REFCLOCK
2405 /*
2406  * get_clkbug_info - get debugging info about a clock
2407  */
2408 static void
2409 get_clkbug_info(
2410 	struct sockaddr_in *srcadr,
2411 	struct interface *inter,
2412 	struct req_pkt *inpkt
2413 	)
2414 {
2415 	register int i;
2416 	register struct info_clkbug *ic;
2417 	register u_int32 *clkaddr;
2418 	register int items;
2419 	struct refclockbug bug;
2420 	struct sockaddr_in addr;
2421 
2422 	memset((char *)&addr, 0, sizeof addr);
2423 	addr.sin_family = AF_INET;
2424 	addr.sin_port = htons(NTP_PORT);
2425 	items = INFO_NITEMS(inpkt->err_nitems);
2426 	clkaddr = (u_int32 *) inpkt->data;
2427 
2428 	ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
2429 					       sizeof(struct info_clkbug));
2430 
2431 	while (items-- > 0) {
2432 		addr.sin_addr.s_addr = *clkaddr++;
2433 		if (!ISREFCLOCKADR(&addr) ||
2434 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2435 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2436 			return;
2437 		}
2438 
2439 		memset((char *)&bug, 0, sizeof bug);
2440 		refclock_buginfo(&addr, &bug);
2441 		if (bug.nvalues == 0 && bug.ntimes == 0) {
2442 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2443 			return;
2444 		}
2445 
2446 		ic->clockadr = addr.sin_addr.s_addr;
2447 		i = bug.nvalues;
2448 		if (i > NUMCBUGVALUES)
2449 		    i = NUMCBUGVALUES;
2450 		ic->nvalues = (u_char)i;
2451 		ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
2452 		while (--i >= 0)
2453 		    ic->values[i] = htonl(bug.values[i]);
2454 
2455 		i = bug.ntimes;
2456 		if (i > NUMCBUGTIMES)
2457 		    i = NUMCBUGTIMES;
2458 		ic->ntimes = (u_char)i;
2459 		ic->stimes = htonl(bug.stimes);
2460 		while (--i >= 0) {
2461 			HTONL_FP(&bug.times[i], &ic->times[i]);
2462 		}
2463 
2464 		ic = (struct info_clkbug *)more_pkt();
2465 	}
2466 	flush_pkt();
2467 }
2468 #endif
2469