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