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