xref: /freebsd/contrib/ntp/ntpd/ntp_request.c (revision eb6d21b4ca6d668cf89afd99eef7baeafa712197)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * ntp_request.c - respond to information requests
3c0b746e5SOllivier Robert  */
49c2daa00SOllivier Robert 
5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
6c0b746e5SOllivier Robert # include <config.h>
7c0b746e5SOllivier Robert #endif
8c0b746e5SOllivier Robert 
9c0b746e5SOllivier Robert #include "ntpd.h"
10c0b746e5SOllivier Robert #include "ntp_io.h"
11c0b746e5SOllivier Robert #include "ntp_request.h"
12c0b746e5SOllivier Robert #include "ntp_control.h"
13c0b746e5SOllivier Robert #include "ntp_refclock.h"
14c0b746e5SOllivier Robert #include "ntp_if.h"
15c0b746e5SOllivier Robert #include "ntp_stdlib.h"
16224ba2bdSOllivier Robert 
17224ba2bdSOllivier Robert #include <stdio.h>
189c2daa00SOllivier Robert #include <stddef.h>
19224ba2bdSOllivier Robert #include <signal.h>
20224ba2bdSOllivier Robert #include <netinet/in.h>
21224ba2bdSOllivier Robert #include <arpa/inet.h>
22224ba2bdSOllivier Robert 
23c0b746e5SOllivier Robert #include "recvbuff.h"
24c0b746e5SOllivier Robert 
25c0b746e5SOllivier Robert #ifdef KERNEL_PLL
26c0b746e5SOllivier Robert #include "ntp_syscall.h"
27c0b746e5SOllivier Robert #endif /* KERNEL_PLL */
28c0b746e5SOllivier Robert 
29c0b746e5SOllivier Robert /*
30c0b746e5SOllivier Robert  * Structure to hold request procedure information
31c0b746e5SOllivier Robert  */
32c0b746e5SOllivier Robert #define	NOAUTH	0
33c0b746e5SOllivier Robert #define	AUTH	1
34c0b746e5SOllivier Robert 
35c0b746e5SOllivier Robert #define	NO_REQUEST	(-1)
369c2daa00SOllivier Robert /*
379c2daa00SOllivier Robert  * Because we now have v6 addresses in the messages, we need to compensate
389c2daa00SOllivier Robert  * for the larger size.  Therefore, we introduce the alternate size to
399c2daa00SOllivier Robert  * keep us friendly with older implementations.  A little ugly.
409c2daa00SOllivier Robert  */
419c2daa00SOllivier Robert static int client_v6_capable = 0;   /* the client can handle longer messages */
429c2daa00SOllivier Robert 
439c2daa00SOllivier Robert #define v6sizeof(type)	(client_v6_capable ? sizeof(type) : v4sizeof(type))
44c0b746e5SOllivier Robert 
45c0b746e5SOllivier Robert struct req_proc {
46c0b746e5SOllivier Robert 	short request_code;	/* defined request code */
47c0b746e5SOllivier Robert 	short needs_auth;	/* true when authentication needed */
489c2daa00SOllivier Robert 	short sizeofitem;	/* size of request data item (older size)*/
499c2daa00SOllivier Robert 	short v6_sizeofitem;	/* size of request data item (new size)*/
509c2daa00SOllivier Robert 	void (*handler) P((struct sockaddr_storage *, struct interface *,
51c0b746e5SOllivier Robert 			   struct req_pkt *));	/* routine to handle request */
52c0b746e5SOllivier Robert };
53c0b746e5SOllivier Robert 
54c0b746e5SOllivier Robert /*
55c0b746e5SOllivier Robert  * Universal request codes
56c0b746e5SOllivier Robert  */
57c0b746e5SOllivier Robert static	struct req_proc univ_codes[] = {
58c0b746e5SOllivier Robert 	{ NO_REQUEST,		NOAUTH,	 0,	0 }
59c0b746e5SOllivier Robert };
60c0b746e5SOllivier Robert 
619c2daa00SOllivier Robert static	void	req_ack	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
629c2daa00SOllivier Robert static	char *	prepare_pkt	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int));
63c0b746e5SOllivier Robert static	char *	more_pkt	P((void));
64c0b746e5SOllivier Robert static	void	flush_pkt	P((void));
659c2daa00SOllivier Robert static	void	peer_list	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
669c2daa00SOllivier Robert static	void	peer_list_sum	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
679c2daa00SOllivier Robert static	void	peer_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
689c2daa00SOllivier Robert static	void	peer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
699c2daa00SOllivier Robert static	void	sys_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
709c2daa00SOllivier Robert static	void	sys_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
719c2daa00SOllivier Robert static	void	mem_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
729c2daa00SOllivier Robert static	void	io_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
739c2daa00SOllivier Robert static	void	timer_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
749c2daa00SOllivier Robert static	void	loop_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
759c2daa00SOllivier Robert static	void	do_conf		P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
769c2daa00SOllivier Robert static	void	do_unconf	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
779c2daa00SOllivier Robert static	void	set_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
789c2daa00SOllivier Robert static	void	clr_sys_flag	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
799c2daa00SOllivier Robert static	void	setclr_flags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
809c2daa00SOllivier Robert static	void	list_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
819c2daa00SOllivier Robert static	void	do_resaddflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
829c2daa00SOllivier Robert static	void	do_ressubflags	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
839c2daa00SOllivier Robert static	void	do_unrestrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
849c2daa00SOllivier Robert static	void	do_restrict	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
859c2daa00SOllivier Robert static	void	mon_getlist_0	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
869c2daa00SOllivier Robert static	void	mon_getlist_1	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
879c2daa00SOllivier Robert static	void	reset_stats	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
889c2daa00SOllivier Robert static	void	reset_peer	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
899c2daa00SOllivier Robert static	void	do_key_reread	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
909c2daa00SOllivier Robert static	void	trust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
919c2daa00SOllivier Robert static	void	untrust_key	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
929c2daa00SOllivier Robert static	void	do_trustkey	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
939c2daa00SOllivier Robert static	void	get_auth_info	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
94c0b746e5SOllivier Robert static	void	reset_auth_stats P((void));
959c2daa00SOllivier Robert static	void	req_get_traps	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
969c2daa00SOllivier Robert static	void	req_set_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
979c2daa00SOllivier Robert static	void	req_clr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
989c2daa00SOllivier Robert static	void	do_setclr_trap	P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
999c2daa00SOllivier Robert static	void	set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
1009c2daa00SOllivier Robert static	void	set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
1019c2daa00SOllivier Robert static	void	get_ctl_stats   P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
102ea906c41SOllivier Robert static	void	get_if_stats    P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
103ea906c41SOllivier Robert static	void	do_if_reload    P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
104c0b746e5SOllivier Robert #ifdef KERNEL_PLL
1059c2daa00SOllivier Robert static	void	get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
106c0b746e5SOllivier Robert #endif /* KERNEL_PLL */
107c0b746e5SOllivier Robert #ifdef REFCLOCK
1089c2daa00SOllivier Robert static	void	get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
1099c2daa00SOllivier Robert static	void	set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
110c0b746e5SOllivier Robert #endif	/* REFCLOCK */
111c0b746e5SOllivier Robert #ifdef REFCLOCK
1129c2daa00SOllivier Robert static	void	get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
113c0b746e5SOllivier Robert #endif	/* REFCLOCK */
114c0b746e5SOllivier Robert 
115c0b746e5SOllivier Robert /*
116c0b746e5SOllivier Robert  * ntpd request codes
117c0b746e5SOllivier Robert  */
118c0b746e5SOllivier Robert static	struct req_proc ntp_codes[] = {
1199c2daa00SOllivier Robert 	{ REQ_PEER_LIST,	NOAUTH,	0, 0,	peer_list },
1209c2daa00SOllivier Robert 	{ REQ_PEER_LIST_SUM,	NOAUTH,	0, 0,	peer_list_sum },
1219c2daa00SOllivier Robert 	{ REQ_PEER_INFO,    NOAUTH, v4sizeof(struct info_peer_list),
1229c2daa00SOllivier Robert 				sizeof(struct info_peer_list), peer_info},
1239c2daa00SOllivier Robert 	{ REQ_PEER_STATS,   NOAUTH, v4sizeof(struct info_peer_list),
1249c2daa00SOllivier Robert 				sizeof(struct info_peer_list), peer_stats},
1259c2daa00SOllivier Robert 	{ REQ_SYS_INFO,		NOAUTH,	0, 0,	sys_info },
1269c2daa00SOllivier Robert 	{ REQ_SYS_STATS,	NOAUTH,	0, 0,	sys_stats },
1279c2daa00SOllivier Robert 	{ REQ_IO_STATS,		NOAUTH,	0, 0,	io_stats },
1289c2daa00SOllivier Robert 	{ REQ_MEM_STATS,	NOAUTH,	0, 0,	mem_stats },
1299c2daa00SOllivier Robert 	{ REQ_LOOP_INFO,	NOAUTH,	0, 0,	loop_info },
1309c2daa00SOllivier Robert 	{ REQ_TIMER_STATS,	NOAUTH,	0, 0,	timer_stats },
1319c2daa00SOllivier Robert 	{ REQ_CONFIG,	    AUTH, v4sizeof(struct conf_peer),
1329c2daa00SOllivier Robert 				sizeof(struct conf_peer), do_conf },
1339c2daa00SOllivier Robert 	{ REQ_UNCONFIG,	    AUTH, v4sizeof(struct conf_unpeer),
1349c2daa00SOllivier Robert 				sizeof(struct conf_unpeer), do_unconf },
1359c2daa00SOllivier Robert 	{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
1369c2daa00SOllivier Robert 				sizeof(struct conf_sys_flags), set_sys_flag },
1379c2daa00SOllivier Robert 	{ REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
1389c2daa00SOllivier Robert 				sizeof(struct conf_sys_flags),  clr_sys_flag },
1399c2daa00SOllivier Robert 	{ REQ_GET_RESTRICT,	NOAUTH,	0, 0,	list_restrict },
1409c2daa00SOllivier Robert 	{ REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),
1419c2daa00SOllivier Robert 				sizeof(struct conf_restrict), do_resaddflags },
1429c2daa00SOllivier Robert 	{ REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),
1439c2daa00SOllivier Robert 				sizeof(struct conf_restrict), do_ressubflags },
1449c2daa00SOllivier Robert 	{ REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),
1459c2daa00SOllivier Robert 				sizeof(struct conf_restrict), do_unrestrict },
1469c2daa00SOllivier Robert 	{ REQ_MON_GETLIST,	NOAUTH,	0, 0,	mon_getlist_0 },
1479c2daa00SOllivier Robert 	{ REQ_MON_GETLIST_1,	NOAUTH,	0, 0,	mon_getlist_1 },
1489c2daa00SOllivier Robert 	{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },
1499c2daa00SOllivier Robert 	{ REQ_RESET_PEER,  AUTH, v4sizeof(struct conf_unpeer),
1509c2daa00SOllivier Robert 				sizeof(struct conf_unpeer), reset_peer },
1519c2daa00SOllivier Robert 	{ REQ_REREAD_KEYS,	AUTH,	0, 0,	do_key_reread },
1529c2daa00SOllivier Robert 	{ REQ_TRUSTKEY,   AUTH, sizeof(u_long), sizeof(u_long), trust_key },
1539c2daa00SOllivier Robert 	{ REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },
1549c2daa00SOllivier Robert 	{ REQ_AUTHINFO,		NOAUTH,	0, 0,	get_auth_info },
1559c2daa00SOllivier Robert 	{ REQ_TRAPS,		NOAUTH, 0, 0,	req_get_traps },
1569c2daa00SOllivier Robert 	{ REQ_ADD_TRAP,	AUTH, v4sizeof(struct conf_trap),
1579c2daa00SOllivier Robert 				sizeof(struct conf_trap), req_set_trap },
1589c2daa00SOllivier Robert 	{ REQ_CLR_TRAP,	AUTH, v4sizeof(struct conf_trap),
1599c2daa00SOllivier Robert 				sizeof(struct conf_trap), req_clr_trap },
1609c2daa00SOllivier Robert 	{ REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long),
1619c2daa00SOllivier Robert 				set_request_keyid },
1629c2daa00SOllivier Robert 	{ REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long),
1639c2daa00SOllivier Robert 				set_control_keyid },
1649c2daa00SOllivier Robert 	{ REQ_GET_CTLSTATS,	NOAUTH,	0, 0,	get_ctl_stats },
165c0b746e5SOllivier Robert #ifdef KERNEL_PLL
1669c2daa00SOllivier Robert 	{ REQ_GET_KERNEL,	NOAUTH,	0, 0,	get_kernel_info },
167c0b746e5SOllivier Robert #endif
168c0b746e5SOllivier Robert #ifdef REFCLOCK
1699c2daa00SOllivier Robert 	{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
1709c2daa00SOllivier Robert 				get_clock_info },
1719c2daa00SOllivier Robert 	{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge),
1729c2daa00SOllivier Robert 				sizeof(struct conf_fudge), set_clock_fudge },
1739c2daa00SOllivier Robert 	{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
1749c2daa00SOllivier Robert 				get_clkbug_info },
175c0b746e5SOllivier Robert #endif
176ea906c41SOllivier Robert 	{ REQ_IF_STATS,		AUTH, 0, 0,	get_if_stats },
177ea906c41SOllivier Robert 	{ REQ_IF_RELOAD,        AUTH, 0, 0,	do_if_reload },
178ea906c41SOllivier Robert 
1799c2daa00SOllivier Robert 	{ NO_REQUEST,		NOAUTH,	0, 0,	0 }
180c0b746e5SOllivier Robert };
181c0b746e5SOllivier Robert 
182c0b746e5SOllivier Robert 
183c0b746e5SOllivier Robert /*
184c0b746e5SOllivier Robert  * Authentication keyid used to authenticate requests.  Zero means we
185c0b746e5SOllivier Robert  * don't allow writing anything.
186c0b746e5SOllivier Robert  */
187224ba2bdSOllivier Robert keyid_t info_auth_keyid;
188c0b746e5SOllivier Robert 
189c0b746e5SOllivier Robert /*
190c0b746e5SOllivier Robert  * Statistic counters to keep track of requests and responses.
191c0b746e5SOllivier Robert  */
192c0b746e5SOllivier Robert u_long numrequests;		/* number of requests we've received */
193c0b746e5SOllivier Robert u_long numresppkts;		/* number of resp packets sent with data */
194c0b746e5SOllivier Robert 
195c0b746e5SOllivier Robert u_long errorcounter[INFO_ERR_AUTH+1];	/* lazy way to count errors, indexed */
196c0b746e5SOllivier Robert /* by the error code */
197c0b746e5SOllivier Robert 
198c0b746e5SOllivier Robert /*
199c0b746e5SOllivier Robert  * A hack.  To keep the authentication module clear of ntp-ism's, we
200c0b746e5SOllivier Robert  * include a time reset variable for its stats here.
201c0b746e5SOllivier Robert  */
202c0b746e5SOllivier Robert static u_long auth_timereset;
203c0b746e5SOllivier Robert 
204c0b746e5SOllivier Robert /*
205c0b746e5SOllivier Robert  * Response packet used by these routines.  Also some state information
206c0b746e5SOllivier Robert  * so that we can handle packet formatting within a common set of
207c0b746e5SOllivier Robert  * subroutines.  Note we try to enter data in place whenever possible,
208c0b746e5SOllivier Robert  * but the need to set the more bit correctly means we occasionally
209c0b746e5SOllivier Robert  * use the extra buffer and copy.
210c0b746e5SOllivier Robert  */
211c0b746e5SOllivier Robert static struct resp_pkt rpkt;
212c0b746e5SOllivier Robert static int reqver;
213c0b746e5SOllivier Robert static int seqno;
214c0b746e5SOllivier Robert static int nitems;
215c0b746e5SOllivier Robert static int itemsize;
216c0b746e5SOllivier Robert static int databytes;
217c0b746e5SOllivier Robert static char exbuf[RESP_DATA_SIZE];
218c0b746e5SOllivier Robert static int usingexbuf;
2199c2daa00SOllivier Robert static struct sockaddr_storage *toaddr;
220c0b746e5SOllivier Robert static struct interface *frominter;
221c0b746e5SOllivier Robert 
222c0b746e5SOllivier Robert /*
223c0b746e5SOllivier Robert  * init_request - initialize request data
224c0b746e5SOllivier Robert  */
225c0b746e5SOllivier Robert void
226c0b746e5SOllivier Robert init_request (void)
227c0b746e5SOllivier Robert {
228c0b746e5SOllivier Robert 	int i;
229c0b746e5SOllivier Robert 
230c0b746e5SOllivier Robert 	numrequests = 0;
231c0b746e5SOllivier Robert 	numresppkts = 0;
232c0b746e5SOllivier Robert 	auth_timereset = 0;
233c0b746e5SOllivier Robert 	info_auth_keyid = 0;	/* by default, can't do this */
234c0b746e5SOllivier Robert 
235c0b746e5SOllivier Robert 	for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
236c0b746e5SOllivier Robert 	    errorcounter[i] = 0;
237c0b746e5SOllivier Robert }
238c0b746e5SOllivier Robert 
239c0b746e5SOllivier Robert 
240c0b746e5SOllivier Robert /*
241c0b746e5SOllivier Robert  * req_ack - acknowledge request with no data
242c0b746e5SOllivier Robert  */
243c0b746e5SOllivier Robert static void
244c0b746e5SOllivier Robert req_ack(
2459c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
246c0b746e5SOllivier Robert 	struct interface *inter,
247c0b746e5SOllivier Robert 	struct req_pkt *inpkt,
248c0b746e5SOllivier Robert 	int errcode
249c0b746e5SOllivier Robert 	)
250c0b746e5SOllivier Robert {
251c0b746e5SOllivier Robert 	/*
252c0b746e5SOllivier Robert 	 * fill in the fields
253c0b746e5SOllivier Robert 	 */
254c0b746e5SOllivier Robert 	rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
255c0b746e5SOllivier Robert 	rpkt.auth_seq = AUTH_SEQ(0, 0);
256c0b746e5SOllivier Robert 	rpkt.implementation = inpkt->implementation;
257c0b746e5SOllivier Robert 	rpkt.request = inpkt->request;
258c0b746e5SOllivier Robert 	rpkt.err_nitems = ERR_NITEMS(errcode, 0);
259c0b746e5SOllivier Robert 	rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
260c0b746e5SOllivier Robert 
261c0b746e5SOllivier Robert 	/*
262c0b746e5SOllivier Robert 	 * send packet and bump counters
263c0b746e5SOllivier Robert 	 */
264c0b746e5SOllivier Robert 	sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
265c0b746e5SOllivier Robert 	errorcounter[errcode]++;
266c0b746e5SOllivier Robert }
267c0b746e5SOllivier Robert 
268c0b746e5SOllivier Robert 
269c0b746e5SOllivier Robert /*
270c0b746e5SOllivier Robert  * prepare_pkt - prepare response packet for transmission, return pointer
271c0b746e5SOllivier Robert  *		 to storage for data item.
272c0b746e5SOllivier Robert  */
273c0b746e5SOllivier Robert static char *
274c0b746e5SOllivier Robert prepare_pkt(
2759c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
276c0b746e5SOllivier Robert 	struct interface *inter,
277c0b746e5SOllivier Robert 	struct req_pkt *pkt,
278c0b746e5SOllivier Robert 	u_int structsize
279c0b746e5SOllivier Robert 	)
280c0b746e5SOllivier Robert {
281c0b746e5SOllivier Robert #ifdef DEBUG
282c0b746e5SOllivier Robert 	if (debug > 3)
283c0b746e5SOllivier Robert 	    printf("request: preparing pkt\n");
284c0b746e5SOllivier Robert #endif
285c0b746e5SOllivier Robert 
286c0b746e5SOllivier Robert 	/*
2879c2daa00SOllivier Robert 	 * Fill in the implementation, request and itemsize fields
288c0b746e5SOllivier Robert 	 * since these won't change.
289c0b746e5SOllivier Robert 	 */
290c0b746e5SOllivier Robert 	rpkt.implementation = pkt->implementation;
291c0b746e5SOllivier Robert 	rpkt.request = pkt->request;
292c0b746e5SOllivier Robert 	rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
293c0b746e5SOllivier Robert 
294c0b746e5SOllivier Robert 	/*
295c0b746e5SOllivier Robert 	 * Compute the static data needed to carry on.
296c0b746e5SOllivier Robert 	 */
297c0b746e5SOllivier Robert 	toaddr = srcadr;
298c0b746e5SOllivier Robert 	frominter = inter;
299c0b746e5SOllivier Robert 	seqno = 0;
300c0b746e5SOllivier Robert 	nitems = 0;
301c0b746e5SOllivier Robert 	itemsize = structsize;
302c0b746e5SOllivier Robert 	databytes = 0;
303c0b746e5SOllivier Robert 	usingexbuf = 0;
304c0b746e5SOllivier Robert 
305c0b746e5SOllivier Robert 	/*
306c0b746e5SOllivier Robert 	 * return the beginning of the packet buffer.
307c0b746e5SOllivier Robert 	 */
308c0b746e5SOllivier Robert 	return &rpkt.data[0];
309c0b746e5SOllivier Robert }
310c0b746e5SOllivier Robert 
311c0b746e5SOllivier Robert 
312c0b746e5SOllivier Robert /*
313c0b746e5SOllivier Robert  * more_pkt - return a data pointer for a new item.
314c0b746e5SOllivier Robert  */
315c0b746e5SOllivier Robert static char *
316c0b746e5SOllivier Robert more_pkt(void)
317c0b746e5SOllivier Robert {
318c0b746e5SOllivier Robert 	/*
319c0b746e5SOllivier Robert 	 * If we were using the extra buffer, send the packet.
320c0b746e5SOllivier Robert 	 */
321c0b746e5SOllivier Robert 	if (usingexbuf) {
322c0b746e5SOllivier Robert #ifdef DEBUG
323c0b746e5SOllivier Robert 		if (debug > 2)
324c0b746e5SOllivier Robert 		    printf("request: sending pkt\n");
325c0b746e5SOllivier Robert #endif
326c0b746e5SOllivier Robert 		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
327c0b746e5SOllivier Robert 		rpkt.auth_seq = AUTH_SEQ(0, seqno);
328c0b746e5SOllivier Robert 		rpkt.err_nitems = htons((u_short)nitems);
329c0b746e5SOllivier Robert 		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
330c0b746e5SOllivier Robert 			RESP_HEADER_SIZE+databytes);
331c0b746e5SOllivier Robert 		numresppkts++;
332c0b746e5SOllivier Robert 
333c0b746e5SOllivier Robert 		/*
334c0b746e5SOllivier Robert 		 * Copy data out of exbuf into the packet.
335c0b746e5SOllivier Robert 		 */
336c0b746e5SOllivier Robert 		memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);
337c0b746e5SOllivier Robert 		seqno++;
338c0b746e5SOllivier Robert 		databytes = 0;
339c0b746e5SOllivier Robert 		nitems = 0;
340c0b746e5SOllivier Robert 		usingexbuf = 0;
341c0b746e5SOllivier Robert 	}
342c0b746e5SOllivier Robert 
343c0b746e5SOllivier Robert 	databytes += itemsize;
344c0b746e5SOllivier Robert 	nitems++;
345c0b746e5SOllivier Robert 	if (databytes + itemsize <= RESP_DATA_SIZE) {
346c0b746e5SOllivier Robert #ifdef DEBUG
347c0b746e5SOllivier Robert 		if (debug > 3)
348c0b746e5SOllivier Robert 		    printf("request: giving him more data\n");
349c0b746e5SOllivier Robert #endif
350c0b746e5SOllivier Robert 		/*
351c0b746e5SOllivier Robert 		 * More room in packet.  Give him the
352c0b746e5SOllivier Robert 		 * next address.
353c0b746e5SOllivier Robert 		 */
354c0b746e5SOllivier Robert 		return &rpkt.data[databytes];
355c0b746e5SOllivier Robert 	} else {
356c0b746e5SOllivier Robert 		/*
357c0b746e5SOllivier Robert 		 * No room in packet.  Give him the extra
358c0b746e5SOllivier Robert 		 * buffer unless this was the last in the sequence.
359c0b746e5SOllivier Robert 		 */
360c0b746e5SOllivier Robert #ifdef DEBUG
361c0b746e5SOllivier Robert 		if (debug > 3)
362c0b746e5SOllivier Robert 		    printf("request: into extra buffer\n");
363c0b746e5SOllivier Robert #endif
364c0b746e5SOllivier Robert 		if (seqno == MAXSEQ)
365c0b746e5SOllivier Robert 		    return (char *)0;
366c0b746e5SOllivier Robert 		else {
367c0b746e5SOllivier Robert 			usingexbuf = 1;
368c0b746e5SOllivier Robert 			return exbuf;
369c0b746e5SOllivier Robert 		}
370c0b746e5SOllivier Robert 	}
371c0b746e5SOllivier Robert }
372c0b746e5SOllivier Robert 
373c0b746e5SOllivier Robert 
374c0b746e5SOllivier Robert /*
375c0b746e5SOllivier Robert  * flush_pkt - we're done, return remaining information.
376c0b746e5SOllivier Robert  */
377c0b746e5SOllivier Robert static void
378c0b746e5SOllivier Robert flush_pkt(void)
379c0b746e5SOllivier Robert {
380c0b746e5SOllivier Robert #ifdef DEBUG
381c0b746e5SOllivier Robert 	if (debug > 2)
382c0b746e5SOllivier Robert 	    printf("request: flushing packet, %d items\n", nitems);
383c0b746e5SOllivier Robert #endif
384c0b746e5SOllivier Robert 	/*
385c0b746e5SOllivier Robert 	 * Must send the last packet.  If nothing in here and nothing
386c0b746e5SOllivier Robert 	 * has been sent, send an error saying no data to be found.
387c0b746e5SOllivier Robert 	 */
388c0b746e5SOllivier Robert 	if (seqno == 0 && nitems == 0)
389c0b746e5SOllivier Robert 	    req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
390c0b746e5SOllivier Robert 		    INFO_ERR_NODATA);
391c0b746e5SOllivier Robert 	else {
392c0b746e5SOllivier Robert 		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
393c0b746e5SOllivier Robert 		rpkt.auth_seq = AUTH_SEQ(0, seqno);
394c0b746e5SOllivier Robert 		rpkt.err_nitems = htons((u_short)nitems);
395c0b746e5SOllivier Robert 		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
396c0b746e5SOllivier Robert 			RESP_HEADER_SIZE+databytes);
397c0b746e5SOllivier Robert 		numresppkts++;
398c0b746e5SOllivier Robert 	}
399c0b746e5SOllivier Robert }
400c0b746e5SOllivier Robert 
401c0b746e5SOllivier Robert 
402c0b746e5SOllivier Robert 
403c0b746e5SOllivier Robert /*
404c0b746e5SOllivier Robert  * process_private - process private mode (7) packets
405c0b746e5SOllivier Robert  */
406c0b746e5SOllivier Robert void
407c0b746e5SOllivier Robert process_private(
408c0b746e5SOllivier Robert 	struct recvbuf *rbufp,
409c0b746e5SOllivier Robert 	int mod_okay
410c0b746e5SOllivier Robert 	)
411c0b746e5SOllivier Robert {
412eb6d21b4SOllivier Robert 	static u_long quiet_until;
413c0b746e5SOllivier Robert 	struct req_pkt *inpkt;
414ce265a54SOllivier Robert 	struct req_pkt_tail *tailinpkt;
4159c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr;
416c0b746e5SOllivier Robert 	struct interface *inter;
417c0b746e5SOllivier Robert 	struct req_proc *proc;
418224ba2bdSOllivier Robert 	int ec;
4199c2daa00SOllivier Robert 	short temp_size;
420c0b746e5SOllivier Robert 
421c0b746e5SOllivier Robert 	/*
422c0b746e5SOllivier Robert 	 * Initialize pointers, for convenience
423c0b746e5SOllivier Robert 	 */
424c0b746e5SOllivier Robert 	inpkt = (struct req_pkt *)&rbufp->recv_pkt;
425c0b746e5SOllivier Robert 	srcadr = &rbufp->recv_srcadr;
426c0b746e5SOllivier Robert 	inter = rbufp->dstadr;
427c0b746e5SOllivier Robert 
428c0b746e5SOllivier Robert #ifdef DEBUG
429c0b746e5SOllivier Robert 	if (debug > 2)
430224ba2bdSOllivier Robert 	    printf("process_private: impl %d req %d\n",
431c0b746e5SOllivier Robert 		   inpkt->implementation, inpkt->request);
432c0b746e5SOllivier Robert #endif
433c0b746e5SOllivier Robert 
434c0b746e5SOllivier Robert 	/*
435c0b746e5SOllivier Robert 	 * Do some sanity checks on the packet.  Return a format
436c0b746e5SOllivier Robert 	 * error if it fails.
437c0b746e5SOllivier Robert 	 */
438224ba2bdSOllivier Robert 	ec = 0;
439224ba2bdSOllivier Robert 	if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))
440224ba2bdSOllivier Robert 	    || (++ec, ISMORE(inpkt->rm_vn_mode))
441224ba2bdSOllivier Robert 	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
442224ba2bdSOllivier Robert 	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
443224ba2bdSOllivier Robert 	    || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
444224ba2bdSOllivier Robert 	    || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
445224ba2bdSOllivier Robert 	    || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
446ce265a54SOllivier Robert 	    || (++ec, rbufp->recv_length < REQ_LEN_HDR)
447224ba2bdSOllivier Robert 		) {
448eb6d21b4SOllivier Robert 		NLOG(NLOG_SYSEVENT)
449eb6d21b4SOllivier Robert 			if (current_time >= quiet_until) {
450eb6d21b4SOllivier Robert 				msyslog(LOG_ERR,
451eb6d21b4SOllivier Robert 					"process_private: drop test %d"
452eb6d21b4SOllivier Robert 					" failed, pkt from %s",
453eb6d21b4SOllivier Robert 					ec, stoa(srcadr));
454eb6d21b4SOllivier Robert 				quiet_until = current_time + 60;
455eb6d21b4SOllivier Robert 			}
456c0b746e5SOllivier Robert 		return;
457c0b746e5SOllivier Robert 	}
458c0b746e5SOllivier Robert 
459c0b746e5SOllivier Robert 	reqver = INFO_VERSION(inpkt->rm_vn_mode);
460c0b746e5SOllivier Robert 
461c0b746e5SOllivier Robert 	/*
462c0b746e5SOllivier Robert 	 * Get the appropriate procedure list to search.
463c0b746e5SOllivier Robert 	 */
464c0b746e5SOllivier Robert 	if (inpkt->implementation == IMPL_UNIV)
465c0b746e5SOllivier Robert 	    proc = univ_codes;
4669c2daa00SOllivier Robert 	else if ((inpkt->implementation == IMPL_XNTPD) ||
4679c2daa00SOllivier Robert 		 (inpkt->implementation == IMPL_XNTPD_OLD))
468c0b746e5SOllivier Robert 	    proc = ntp_codes;
469c0b746e5SOllivier Robert 	else {
470c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
471c0b746e5SOllivier Robert 		return;
472c0b746e5SOllivier Robert 	}
473c0b746e5SOllivier Robert 
474c0b746e5SOllivier Robert 	/*
475c0b746e5SOllivier Robert 	 * Search the list for the request codes.  If it isn't one
476c0b746e5SOllivier Robert 	 * we know, return an error.
477c0b746e5SOllivier Robert 	 */
478c0b746e5SOllivier Robert 	while (proc->request_code != NO_REQUEST) {
479c0b746e5SOllivier Robert 		if (proc->request_code == (short) inpkt->request)
480c0b746e5SOllivier Robert 		    break;
481c0b746e5SOllivier Robert 		proc++;
482c0b746e5SOllivier Robert 	}
483c0b746e5SOllivier Robert 	if (proc->request_code == NO_REQUEST) {
484c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
485c0b746e5SOllivier Robert 		return;
486c0b746e5SOllivier Robert 	}
487c0b746e5SOllivier Robert 
488c0b746e5SOllivier Robert #ifdef DEBUG
489c0b746e5SOllivier Robert 	if (debug > 3)
490c0b746e5SOllivier Robert 	    printf("found request in tables\n");
491c0b746e5SOllivier Robert #endif
492c0b746e5SOllivier Robert 
493c0b746e5SOllivier Robert 	/*
4949c2daa00SOllivier Robert 	 * If we need data, check to see if we have some.  If we
4959c2daa00SOllivier Robert 	 * don't, check to see that there is none (picky, picky).
4969c2daa00SOllivier Robert 	 */
4979c2daa00SOllivier Robert 
4989c2daa00SOllivier Robert 	/* This part is a bit tricky, we want to be sure that the size
4999c2daa00SOllivier Robert 	 * returned is either the old or the new size.  We also can find
5009c2daa00SOllivier Robert 	 * out if the client can accept both types of messages this way.
5019c2daa00SOllivier Robert 	 *
5029c2daa00SOllivier Robert 	 * Handle the exception of REQ_CONFIG. It can have two data sizes.
5039c2daa00SOllivier Robert 	 */
5049c2daa00SOllivier Robert 	temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);
5059c2daa00SOllivier Robert 	if ((temp_size != proc->sizeofitem &&
5069c2daa00SOllivier Robert 	     temp_size != proc->v6_sizeofitem) &&
5079c2daa00SOllivier Robert 	    !(inpkt->implementation == IMPL_XNTPD &&
5089c2daa00SOllivier Robert 	      inpkt->request == REQ_CONFIG &&
5099c2daa00SOllivier Robert 	      temp_size == sizeof(struct old_conf_peer))) {
510ea906c41SOllivier Robert #ifdef DEBUG
5119c2daa00SOllivier Robert 		if (debug > 2)
5129c2daa00SOllivier Robert 			printf("process_private: wrong item size, received %d, should be %d or %d\n",
5139c2daa00SOllivier Robert 			    temp_size, proc->sizeofitem, proc->v6_sizeofitem);
514ea906c41SOllivier Robert #endif
5159c2daa00SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5169c2daa00SOllivier Robert 		return;
5179c2daa00SOllivier Robert 	}
5189c2daa00SOllivier Robert 	if ((proc->sizeofitem != 0) &&
5199c2daa00SOllivier Robert 	    ((temp_size * INFO_NITEMS(inpkt->err_nitems)) >
5209c2daa00SOllivier Robert 	    (rbufp->recv_length - REQ_LEN_HDR))) {
521ea906c41SOllivier Robert #ifdef DEBUG
5229c2daa00SOllivier Robert 		if (debug > 2)
5239c2daa00SOllivier Robert 			printf("process_private: not enough data\n");
524ea906c41SOllivier Robert #endif
5259c2daa00SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5269c2daa00SOllivier Robert 		return;
5279c2daa00SOllivier Robert 	}
5289c2daa00SOllivier Robert 
5299c2daa00SOllivier Robert 	switch (inpkt->implementation) {
5309c2daa00SOllivier Robert 	case IMPL_XNTPD:
5319c2daa00SOllivier Robert 		client_v6_capable = 1;
5329c2daa00SOllivier Robert 		break;
5339c2daa00SOllivier Robert 	case IMPL_XNTPD_OLD:
5349c2daa00SOllivier Robert 		client_v6_capable = 0;
5359c2daa00SOllivier Robert 		break;
5369c2daa00SOllivier Robert 	default:
5379c2daa00SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5389c2daa00SOllivier Robert 		return;
5399c2daa00SOllivier Robert 	}
5409c2daa00SOllivier Robert 
5419c2daa00SOllivier Robert 	/*
542c0b746e5SOllivier Robert 	 * If we need to authenticate, do so.  Note that an
543c0b746e5SOllivier Robert 	 * authenticatable packet must include a mac field, must
544c0b746e5SOllivier Robert 	 * have used key info_auth_keyid and must have included
545c0b746e5SOllivier Robert 	 * a time stamp in the appropriate field.  The time stamp
546c0b746e5SOllivier Robert 	 * must be within INFO_TS_MAXSKEW of the receive
547c0b746e5SOllivier Robert 	 * time stamp.
548c0b746e5SOllivier Robert 	 */
549c0b746e5SOllivier Robert 	if (proc->needs_auth && sys_authenticate) {
550c0b746e5SOllivier Robert 		l_fp ftmp;
551c0b746e5SOllivier Robert 		double dtemp;
552c0b746e5SOllivier Robert 
5539c2daa00SOllivier Robert 		if (rbufp->recv_length < (int)((REQ_LEN_HDR +
554ce265a54SOllivier Robert 		    (INFO_ITEMSIZE(inpkt->mbz_itemsize) *
555ce265a54SOllivier Robert 		    INFO_NITEMS(inpkt->err_nitems))
5569c2daa00SOllivier Robert 		    + sizeof(struct req_pkt_tail)))) {
557ce265a54SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
558ce265a54SOllivier Robert 		}
559ce265a54SOllivier Robert 		tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt +
560ce265a54SOllivier Robert 		    rbufp->recv_length - sizeof(struct req_pkt_tail));
561ce265a54SOllivier Robert 
562c0b746e5SOllivier Robert 		/*
563c0b746e5SOllivier Robert 		 * If this guy is restricted from doing this, don't let him
564c0b746e5SOllivier Robert 		 * If wrong key was used, or packet doesn't have mac, return.
565c0b746e5SOllivier Robert 		 */
566c0b746e5SOllivier Robert 		if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0
567ce265a54SOllivier Robert 		    || ntohl(tailinpkt->keyid) != info_auth_keyid) {
568c0b746e5SOllivier Robert #ifdef DEBUG
569c0b746e5SOllivier Robert 			if (debug > 4)
570c0b746e5SOllivier Robert 			    printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
571c0b746e5SOllivier Robert 				   INFO_IS_AUTH(inpkt->auth_seq),
572c0b746e5SOllivier Robert 				   (u_long)info_auth_keyid,
573ce265a54SOllivier Robert 				   (u_long)ntohl(tailinpkt->keyid));
5749c2daa00SOllivier Robert 			msyslog(LOG_DEBUG,
5759c2daa00SOllivier Robert 				"process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
5769c2daa00SOllivier Robert 				INFO_IS_AUTH(inpkt->auth_seq),
5779c2daa00SOllivier Robert 				(u_long)info_auth_keyid,
5789c2daa00SOllivier Robert 				(u_long)ntohl(tailinpkt->keyid));
579c0b746e5SOllivier Robert #endif
580c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
581c0b746e5SOllivier Robert 			return;
582c0b746e5SOllivier Robert 		}
583c0b746e5SOllivier Robert 		if (rbufp->recv_length > REQ_LEN_MAC) {
584c0b746e5SOllivier Robert #ifdef DEBUG
585c0b746e5SOllivier Robert 			if (debug > 4)
586c0b746e5SOllivier Robert 			    printf("bad pkt length %d\n",
587c0b746e5SOllivier Robert 				   rbufp->recv_length);
588c0b746e5SOllivier Robert #endif
589224ba2bdSOllivier Robert 			msyslog(LOG_ERR, "process_private: bad pkt length %d",
590224ba2bdSOllivier Robert 				rbufp->recv_length);
591c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
592c0b746e5SOllivier Robert 			return;
593c0b746e5SOllivier Robert 		}
594c0b746e5SOllivier Robert 		if (!mod_okay || !authhavekey(info_auth_keyid)) {
595c0b746e5SOllivier Robert #ifdef DEBUG
596c0b746e5SOllivier Robert 			if (debug > 4)
597c0b746e5SOllivier Robert 			    printf("failed auth mod_okay %d\n", mod_okay);
5989c2daa00SOllivier Robert 			msyslog(LOG_DEBUG,
5999c2daa00SOllivier Robert 				"process_private: failed auth mod_okay %d\n",
6009c2daa00SOllivier Robert 				mod_okay);
601c0b746e5SOllivier Robert #endif
602c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
603c0b746e5SOllivier Robert 			return;
604c0b746e5SOllivier Robert 		}
605c0b746e5SOllivier Robert 
606c0b746e5SOllivier Robert 		/*
607c0b746e5SOllivier Robert 		 * calculate absolute time difference between xmit time stamp
608c0b746e5SOllivier Robert 		 * and receive time stamp.  If too large, too bad.
609c0b746e5SOllivier Robert 		 */
610ce265a54SOllivier Robert 		NTOHL_FP(&tailinpkt->tstamp, &ftmp);
611c0b746e5SOllivier Robert 		L_SUB(&ftmp, &rbufp->recv_time);
612c0b746e5SOllivier Robert 		LFPTOD(&ftmp, dtemp);
613c0b746e5SOllivier Robert 		if (fabs(dtemp) >= INFO_TS_MAXSKEW) {
614c0b746e5SOllivier Robert 			/*
615c0b746e5SOllivier Robert 			 * He's a loser.  Tell him.
616c0b746e5SOllivier Robert 			 */
6179c2daa00SOllivier Robert #ifdef DEBUG
6189c2daa00SOllivier Robert 			if (debug > 4)
6199c2daa00SOllivier Robert 			    printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n");
6209c2daa00SOllivier Robert #endif
621c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
622c0b746e5SOllivier Robert 			return;
623c0b746e5SOllivier Robert 		}
624c0b746e5SOllivier Robert 
625c0b746e5SOllivier Robert 		/*
626c0b746e5SOllivier Robert 		 * So far so good.  See if decryption works out okay.
627c0b746e5SOllivier Robert 		 */
628c0b746e5SOllivier Robert 		if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
629ce265a54SOllivier Robert 		    rbufp->recv_length - sizeof(struct req_pkt_tail) +
630ce265a54SOllivier Robert 		    REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) {
6319c2daa00SOllivier Robert #ifdef DEBUG
6329c2daa00SOllivier Robert 			if (debug > 4)
6339c2daa00SOllivier Robert 			    printf("authdecrypt failed\n");
6349c2daa00SOllivier Robert #endif
635c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
636c0b746e5SOllivier Robert 			return;
637c0b746e5SOllivier Robert 		}
638c0b746e5SOllivier Robert 	}
639c0b746e5SOllivier Robert 
640c0b746e5SOllivier Robert #ifdef DEBUG
641c0b746e5SOllivier Robert 	if (debug > 3)
642c0b746e5SOllivier Robert 	    printf("process_private: all okay, into handler\n");
643c0b746e5SOllivier Robert #endif
644c0b746e5SOllivier Robert 
645c0b746e5SOllivier Robert 	/*
646c0b746e5SOllivier Robert 	 * Packet is okay.  Call the handler to send him data.
647c0b746e5SOllivier Robert 	 */
648c0b746e5SOllivier Robert 	(proc->handler)(srcadr, inter, inpkt);
649c0b746e5SOllivier Robert }
650c0b746e5SOllivier Robert 
651c0b746e5SOllivier Robert 
652c0b746e5SOllivier Robert /*
653c0b746e5SOllivier Robert  * peer_list - send a list of the peers
654c0b746e5SOllivier Robert  */
655c0b746e5SOllivier Robert static void
656c0b746e5SOllivier Robert peer_list(
6579c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
658c0b746e5SOllivier Robert 	struct interface *inter,
659c0b746e5SOllivier Robert 	struct req_pkt *inpkt
660c0b746e5SOllivier Robert 	)
661c0b746e5SOllivier Robert {
662c0b746e5SOllivier Robert 	register struct info_peer_list *ip;
663c0b746e5SOllivier Robert 	register struct peer *pp;
664c0b746e5SOllivier Robert 	register int i;
6659c2daa00SOllivier Robert 	register int skip = 0;
666c0b746e5SOllivier Robert 
667c0b746e5SOllivier Robert 	ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
6689c2daa00SOllivier Robert 	    v6sizeof(struct info_peer_list));
669ea906c41SOllivier Robert 	for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) {
670c0b746e5SOllivier Robert 		pp = peer_hash[i];
671c0b746e5SOllivier Robert 		while (pp != 0 && ip != 0) {
6729c2daa00SOllivier Robert 			if (pp->srcadr.ss_family == AF_INET6) {
6739c2daa00SOllivier Robert 				if (client_v6_capable) {
6749c2daa00SOllivier Robert 					ip->addr6 = GET_INADDR6(pp->srcadr);
6759c2daa00SOllivier Robert 					ip->v6_flag = 1;
6769c2daa00SOllivier Robert 					skip = 0;
6779c2daa00SOllivier Robert 				} else {
6789c2daa00SOllivier Robert 					skip = 1;
6799c2daa00SOllivier Robert 					break;
6809c2daa00SOllivier Robert 				}
6819c2daa00SOllivier Robert 			} else {
6829c2daa00SOllivier Robert 				ip->addr = GET_INADDR(pp->srcadr);
6839c2daa00SOllivier Robert 				if (client_v6_capable)
6849c2daa00SOllivier Robert 					ip->v6_flag = 0;
6859c2daa00SOllivier Robert 				skip = 0;
6869c2daa00SOllivier Robert 			}
6879c2daa00SOllivier Robert 
6889c2daa00SOllivier Robert 			if(!skip) {
6899c2daa00SOllivier Robert 				ip->port = NSRCPORT(&pp->srcadr);
690c0b746e5SOllivier Robert 				ip->hmode = pp->hmode;
691c0b746e5SOllivier Robert 				ip->flags = 0;
692c0b746e5SOllivier Robert 				if (pp->flags & FLAG_CONFIG)
693c0b746e5SOllivier Robert 				    ip->flags |= INFO_FLAG_CONFIG;
694c0b746e5SOllivier Robert 				if (pp == sys_peer)
695c0b746e5SOllivier Robert 				    ip->flags |= INFO_FLAG_SYSPEER;
696c0b746e5SOllivier Robert 				if (pp->status == CTL_PST_SEL_SYNCCAND)
697c0b746e5SOllivier Robert 				    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
698c0b746e5SOllivier Robert 				if (pp->status >= CTL_PST_SEL_SYSPEER)
699c0b746e5SOllivier Robert 				    ip->flags |= INFO_FLAG_SHORTLIST;
700c0b746e5SOllivier Robert 				ip = (struct info_peer_list *)more_pkt();
7019c2daa00SOllivier Robert 			}
702c0b746e5SOllivier Robert 			pp = pp->next;
703c0b746e5SOllivier Robert 		}
704c0b746e5SOllivier Robert 	}
705c0b746e5SOllivier Robert 	flush_pkt();
706c0b746e5SOllivier Robert }
707c0b746e5SOllivier Robert 
708c0b746e5SOllivier Robert 
709c0b746e5SOllivier Robert /*
710c0b746e5SOllivier Robert  * peer_list_sum - return extended peer list
711c0b746e5SOllivier Robert  */
712c0b746e5SOllivier Robert static void
713c0b746e5SOllivier Robert peer_list_sum(
7149c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
715c0b746e5SOllivier Robert 	struct interface *inter,
716c0b746e5SOllivier Robert 	struct req_pkt *inpkt
717c0b746e5SOllivier Robert 	)
718c0b746e5SOllivier Robert {
719c0b746e5SOllivier Robert 	register struct info_peer_summary *ips;
720c0b746e5SOllivier Robert 	register struct peer *pp;
721c0b746e5SOllivier Robert 	register int i;
722c0b746e5SOllivier Robert 	l_fp ltmp;
7239c2daa00SOllivier Robert 	register int skip;
724c0b746e5SOllivier Robert 
725c0b746e5SOllivier Robert #ifdef DEBUG
726c0b746e5SOllivier Robert 	if (debug > 2)
727c0b746e5SOllivier Robert 	    printf("wants peer list summary\n");
728c0b746e5SOllivier Robert #endif
729c0b746e5SOllivier Robert 	ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
7309c2daa00SOllivier Robert 	    v6sizeof(struct info_peer_summary));
731ea906c41SOllivier Robert 	for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) {
732c0b746e5SOllivier Robert 		pp = peer_hash[i];
733c0b746e5SOllivier Robert 		while (pp != 0 && ips != 0) {
734c0b746e5SOllivier Robert #ifdef DEBUG
735c0b746e5SOllivier Robert 			if (debug > 3)
736c0b746e5SOllivier Robert 			    printf("sum: got one\n");
737c0b746e5SOllivier Robert #endif
7389c2daa00SOllivier Robert 			/*
7399c2daa00SOllivier Robert 			 * Be careful here not to return v6 peers when we
7409c2daa00SOllivier Robert 			 * want only v4.
7419c2daa00SOllivier Robert 			 */
7429c2daa00SOllivier Robert 			if (pp->srcadr.ss_family == AF_INET6) {
7439c2daa00SOllivier Robert 				if (client_v6_capable) {
7449c2daa00SOllivier Robert 					ips->srcadr6 = GET_INADDR6(pp->srcadr);
7459c2daa00SOllivier Robert 					ips->v6_flag = 1;
746ea906c41SOllivier Robert 					if (pp->dstadr)
7479c2daa00SOllivier Robert 						ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
748ea906c41SOllivier Robert 					else
749ea906c41SOllivier Robert 						memset(&ips->dstadr6, 0, sizeof(ips->dstadr6));
7509c2daa00SOllivier Robert 					skip = 0;
7519c2daa00SOllivier Robert 				} else {
7529c2daa00SOllivier Robert 					skip = 1;
7539c2daa00SOllivier Robert 					break;
7549c2daa00SOllivier Robert 				}
7559c2daa00SOllivier Robert 			} else {
7569c2daa00SOllivier Robert 				ips->srcadr = GET_INADDR(pp->srcadr);
7579c2daa00SOllivier Robert 				if (client_v6_capable)
7589c2daa00SOllivier Robert 					ips->v6_flag = 0;
7599c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
760ea906c41SOllivier Robert 
761ea906c41SOllivier Robert 				if (pp->dstadr)
7629c2daa00SOllivier Robert 					ips->dstadr = (pp->processed) ?
7639c2daa00SOllivier Robert 						pp->cast_flags == MDF_BCAST ?
7649c2daa00SOllivier Robert 						GET_INADDR(pp->dstadr->bcast):
7659c2daa00SOllivier Robert 						pp->cast_flags ?
7669c2daa00SOllivier Robert 						GET_INADDR(pp->dstadr->sin) ?
7679c2daa00SOllivier Robert 						GET_INADDR(pp->dstadr->sin):
7689c2daa00SOllivier Robert 						GET_INADDR(pp->dstadr->bcast):
7699c2daa00SOllivier Robert 						1 : GET_INADDR(pp->dstadr->sin);
770ea906c41SOllivier Robert 				else
771ea906c41SOllivier Robert 						memset(&ips->dstadr, 0, sizeof(ips->dstadr));
7729c2daa00SOllivier Robert 
7739c2daa00SOllivier Robert 				skip = 0;
7749c2daa00SOllivier Robert 			}
775ea906c41SOllivier Robert 
7769c2daa00SOllivier Robert 			if (!skip){
7779c2daa00SOllivier Robert 				ips->srcport = NSRCPORT(&pp->srcadr);
778c0b746e5SOllivier Robert 				ips->stratum = pp->stratum;
779c0b746e5SOllivier Robert 				ips->hpoll = pp->hpoll;
780c0b746e5SOllivier Robert 				ips->ppoll = pp->ppoll;
781c0b746e5SOllivier Robert 				ips->reach = pp->reach;
782c0b746e5SOllivier Robert 				ips->flags = 0;
783c0b746e5SOllivier Robert 				if (pp == sys_peer)
784c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_SYSPEER;
785c0b746e5SOllivier Robert 				if (pp->flags & FLAG_CONFIG)
786c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_CONFIG;
787c0b746e5SOllivier Robert 				if (pp->flags & FLAG_REFCLOCK)
788c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_REFCLOCK;
789c0b746e5SOllivier Robert 				if (pp->flags & FLAG_AUTHENABLE)
790c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_AUTHENABLE;
791c0b746e5SOllivier Robert 				if (pp->flags & FLAG_PREFER)
792c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_PREFER;
793c0b746e5SOllivier Robert 				if (pp->flags & FLAG_BURST)
794c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_BURST;
795c0b746e5SOllivier Robert 				if (pp->status == CTL_PST_SEL_SYNCCAND)
796c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_SEL_CANDIDATE;
797c0b746e5SOllivier Robert 				if (pp->status >= CTL_PST_SEL_SYSPEER)
798c0b746e5SOllivier Robert 				    ips->flags |= INFO_FLAG_SHORTLIST;
799c0b746e5SOllivier Robert 				ips->hmode = pp->hmode;
800c0b746e5SOllivier Robert 				ips->delay = HTONS_FP(DTOFP(pp->delay));
801c0b746e5SOllivier Robert 				DTOLFP(pp->offset, &ltmp);
802c0b746e5SOllivier Robert 				HTONL_FP(&ltmp, &ips->offset);
803ea906c41SOllivier Robert 				ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
8049c2daa00SOllivier Robert 			}
805c0b746e5SOllivier Robert 			pp = pp->next;
806c0b746e5SOllivier Robert 			ips = (struct info_peer_summary *)more_pkt();
807c0b746e5SOllivier Robert 		}
808c0b746e5SOllivier Robert 	}
809c0b746e5SOllivier Robert 	flush_pkt();
810c0b746e5SOllivier Robert }
811c0b746e5SOllivier Robert 
812c0b746e5SOllivier Robert 
813c0b746e5SOllivier Robert /*
814c0b746e5SOllivier Robert  * peer_info - send information for one or more peers
815c0b746e5SOllivier Robert  */
816c0b746e5SOllivier Robert static void
817c0b746e5SOllivier Robert peer_info (
8189c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
819c0b746e5SOllivier Robert 	struct interface *inter,
820c0b746e5SOllivier Robert 	struct req_pkt *inpkt
821c0b746e5SOllivier Robert 	)
822c0b746e5SOllivier Robert {
823c0b746e5SOllivier Robert 	register struct info_peer_list *ipl;
824c0b746e5SOllivier Robert 	register struct peer *pp;
825c0b746e5SOllivier Robert 	register struct info_peer *ip;
826c0b746e5SOllivier Robert 	register int items;
827c0b746e5SOllivier Robert 	register int i, j;
8289c2daa00SOllivier Robert 	struct sockaddr_storage addr;
829c0b746e5SOllivier Robert 	extern struct peer *sys_peer;
830c0b746e5SOllivier Robert 	l_fp ltmp;
831c0b746e5SOllivier Robert 
832c0b746e5SOllivier Robert 	memset((char *)&addr, 0, sizeof addr);
833c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
834c0b746e5SOllivier Robert 	ipl = (struct info_peer_list *) inpkt->data;
8359c2daa00SOllivier Robert 
836c0b746e5SOllivier Robert 	ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
8379c2daa00SOllivier Robert 	    v6sizeof(struct info_peer));
838c0b746e5SOllivier Robert 	while (items-- > 0 && ip != 0) {
8399c2daa00SOllivier Robert 		memset((char *)&addr, 0, sizeof(addr));
8409c2daa00SOllivier Robert 		NSRCPORT(&addr) = ipl->port;
8419c2daa00SOllivier Robert 		if (client_v6_capable && ipl->v6_flag != 0) {
8429c2daa00SOllivier Robert 			addr.ss_family = AF_INET6;
8439c2daa00SOllivier Robert 			GET_INADDR6(addr) = ipl->addr6;
8449c2daa00SOllivier Robert 		} else {
8459c2daa00SOllivier Robert 			addr.ss_family = AF_INET;
8469c2daa00SOllivier Robert 			GET_INADDR(addr) = ipl->addr;
8479c2daa00SOllivier Robert 		}
8489c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
8499c2daa00SOllivier Robert 		addr.ss_len = SOCKLEN(&addr);
8509c2daa00SOllivier Robert #endif
851c0b746e5SOllivier Robert 		ipl++;
852c0b746e5SOllivier Robert 		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
853c0b746e5SOllivier Robert 		    continue;
8549c2daa00SOllivier Robert 		if (pp->srcadr.ss_family == AF_INET6) {
855ea906c41SOllivier Robert 			if (pp->dstadr)
8569c2daa00SOllivier Robert 				ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
8579c2daa00SOllivier Robert 					GET_INADDR6(pp->dstadr->bcast) :
8589c2daa00SOllivier Robert 					GET_INADDR6(pp->dstadr->sin);
859ea906c41SOllivier Robert 			else
860ea906c41SOllivier Robert 				memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
861ea906c41SOllivier Robert 
8629c2daa00SOllivier Robert 			ip->srcadr6 = GET_INADDR6(pp->srcadr);
8639c2daa00SOllivier Robert 			ip->v6_flag = 1;
8649c2daa00SOllivier Robert 		} else {
8659c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
866ea906c41SOllivier Robert 			if (pp->dstadr)
8679c2daa00SOllivier Robert 				ip->dstadr = (pp->processed) ?
8689c2daa00SOllivier Robert 					pp->cast_flags == MDF_BCAST ?
8699c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->bcast):
8709c2daa00SOllivier Robert 					pp->cast_flags ?
8719c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->sin) ?
8729c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->sin):
8739c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->bcast):
8749c2daa00SOllivier Robert 					2 : GET_INADDR(pp->dstadr->sin);
875ea906c41SOllivier Robert 			else
876ea906c41SOllivier Robert 				memset(&ip->dstadr, 0, sizeof(ip->dstadr));
8779c2daa00SOllivier Robert 
8789c2daa00SOllivier Robert 			ip->srcadr = GET_INADDR(pp->srcadr);
8799c2daa00SOllivier Robert 			if (client_v6_capable)
8809c2daa00SOllivier Robert 				ip->v6_flag = 0;
8819c2daa00SOllivier Robert 		}
882c0b746e5SOllivier Robert 		ip->srcport = NSRCPORT(&pp->srcadr);
883c0b746e5SOllivier Robert 		ip->flags = 0;
884c0b746e5SOllivier Robert 		if (pp == sys_peer)
885c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SYSPEER;
886c0b746e5SOllivier Robert 		if (pp->flags & FLAG_CONFIG)
887c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_CONFIG;
888c0b746e5SOllivier Robert 		if (pp->flags & FLAG_REFCLOCK)
889c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_REFCLOCK;
890c0b746e5SOllivier Robert 		if (pp->flags & FLAG_AUTHENABLE)
891c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_AUTHENABLE;
892c0b746e5SOllivier Robert 		if (pp->flags & FLAG_PREFER)
893c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_PREFER;
894c0b746e5SOllivier Robert 		if (pp->flags & FLAG_BURST)
895c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_BURST;
896c0b746e5SOllivier Robert 		if (pp->status == CTL_PST_SEL_SYNCCAND)
897c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
898c0b746e5SOllivier Robert 		if (pp->status >= CTL_PST_SEL_SYSPEER)
899c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SHORTLIST;
900c0b746e5SOllivier Robert 		ip->leap = pp->leap;
901c0b746e5SOllivier Robert 		ip->hmode = pp->hmode;
902c0b746e5SOllivier Robert 		ip->keyid = pp->keyid;
903c0b746e5SOllivier Robert 		ip->stratum = pp->stratum;
904c0b746e5SOllivier Robert 		ip->ppoll = pp->ppoll;
905c0b746e5SOllivier Robert 		ip->hpoll = pp->hpoll;
906c0b746e5SOllivier Robert 		ip->precision = pp->precision;
907c0b746e5SOllivier Robert 		ip->version = pp->version;
908c0b746e5SOllivier Robert 		ip->reach = pp->reach;
9099c2daa00SOllivier Robert 		ip->unreach = (u_char) pp->unreach;
910c0b746e5SOllivier Robert 		ip->flash = (u_char)pp->flash;
9119c2daa00SOllivier Robert 		ip->flash2 = (u_short) pp->flash;
912c0b746e5SOllivier Robert 		ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
913c0b746e5SOllivier Robert 		ip->ttl = pp->ttl;
914c0b746e5SOllivier Robert 		ip->associd = htons(pp->associd);
915c0b746e5SOllivier Robert 		ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
916c0b746e5SOllivier Robert 		ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion));
917c0b746e5SOllivier Robert 		ip->refid = pp->refid;
918c0b746e5SOllivier Robert 		HTONL_FP(&pp->reftime, &ip->reftime);
919c0b746e5SOllivier Robert 		HTONL_FP(&pp->org, &ip->org);
920c0b746e5SOllivier Robert 		HTONL_FP(&pp->rec, &ip->rec);
921c0b746e5SOllivier Robert 		HTONL_FP(&pp->xmt, &ip->xmt);
922c0b746e5SOllivier Robert 		j = pp->filter_nextpt - 1;
923c0b746e5SOllivier Robert 		for (i = 0; i < NTP_SHIFT; i++, j--) {
924c0b746e5SOllivier Robert 			if (j < 0)
925c0b746e5SOllivier Robert 			    j = NTP_SHIFT-1;
926c0b746e5SOllivier Robert 			ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
927c0b746e5SOllivier Robert 			DTOLFP(pp->filter_offset[j], &ltmp);
928c0b746e5SOllivier Robert 			HTONL_FP(&ltmp, &ip->filtoffset[i]);
9299c2daa00SOllivier Robert 			ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1)
9309c2daa00SOllivier Robert 				- pp->filter_order[i]);
931c0b746e5SOllivier Robert 			if (ip->order[i] >= NTP_SHIFT)
932c0b746e5SOllivier Robert 			    ip->order[i] -= NTP_SHIFT;
933c0b746e5SOllivier Robert 		}
934c0b746e5SOllivier Robert 		DTOLFP(pp->offset, &ltmp);
935c0b746e5SOllivier Robert 		HTONL_FP(&ltmp, &ip->offset);
936c0b746e5SOllivier Robert 		ip->delay = HTONS_FP(DTOFP(pp->delay));
937c0b746e5SOllivier Robert 		ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
938224ba2bdSOllivier Robert 		ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
939c0b746e5SOllivier Robert 		ip = (struct info_peer *)more_pkt();
940c0b746e5SOllivier Robert 	}
941c0b746e5SOllivier Robert 	flush_pkt();
942c0b746e5SOllivier Robert }
943c0b746e5SOllivier Robert 
944c0b746e5SOllivier Robert 
945c0b746e5SOllivier Robert /*
946c0b746e5SOllivier Robert  * peer_stats - send statistics for one or more peers
947c0b746e5SOllivier Robert  */
948c0b746e5SOllivier Robert static void
949c0b746e5SOllivier Robert peer_stats (
9509c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
951c0b746e5SOllivier Robert 	struct interface *inter,
952c0b746e5SOllivier Robert 	struct req_pkt *inpkt
953c0b746e5SOllivier Robert 	)
954c0b746e5SOllivier Robert {
955c0b746e5SOllivier Robert 	register struct info_peer_list *ipl;
956c0b746e5SOllivier Robert 	register struct peer *pp;
957c0b746e5SOllivier Robert 	register struct info_peer_stats *ip;
958c0b746e5SOllivier Robert 	register int items;
9599c2daa00SOllivier Robert 	struct sockaddr_storage addr;
960c0b746e5SOllivier Robert 	extern struct peer *sys_peer;
961c0b746e5SOllivier Robert 
962ea906c41SOllivier Robert #ifdef DEBUG
963ea906c41SOllivier Robert 	if (debug)
9649c2daa00SOllivier Robert 	     printf("peer_stats: called\n");
965ea906c41SOllivier Robert #endif
966c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
967c0b746e5SOllivier Robert 	ipl = (struct info_peer_list *) inpkt->data;
968c0b746e5SOllivier Robert 	ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
9699c2daa00SOllivier Robert 	    v6sizeof(struct info_peer_stats));
970c0b746e5SOllivier Robert 	while (items-- > 0 && ip != 0) {
9719c2daa00SOllivier Robert 		memset((char *)&addr, 0, sizeof(addr));
9729c2daa00SOllivier Robert 		NSRCPORT(&addr) = ipl->port;
9739c2daa00SOllivier Robert 		if (client_v6_capable && ipl->v6_flag) {
9749c2daa00SOllivier Robert 			addr.ss_family = AF_INET6;
9759c2daa00SOllivier Robert 			GET_INADDR6(addr) = ipl->addr6;
9769c2daa00SOllivier Robert 		} else {
9779c2daa00SOllivier Robert 			addr.ss_family = AF_INET;
9789c2daa00SOllivier Robert 			GET_INADDR(addr) = ipl->addr;
9799c2daa00SOllivier Robert 		}
9809c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
9819c2daa00SOllivier Robert 		addr.ss_len = SOCKLEN(&addr);
9829c2daa00SOllivier Robert #endif
983ea906c41SOllivier Robert #ifdef DEBUG
984ea906c41SOllivier Robert 		if (debug)
9859c2daa00SOllivier Robert 		    printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
9869c2daa00SOllivier Robert 		    ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);
987ea906c41SOllivier Robert #endif
9889c2daa00SOllivier Robert 		ipl = (struct info_peer_list *)((char *)ipl +
9899c2daa00SOllivier Robert 		    INFO_ITEMSIZE(inpkt->mbz_itemsize));
9909c2daa00SOllivier Robert 
991c0b746e5SOllivier Robert 		if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
992c0b746e5SOllivier Robert 		    continue;
993ea906c41SOllivier Robert #ifdef DEBUG
994ea906c41SOllivier Robert 		if (debug)
9959c2daa00SOllivier Robert 		     printf("peer_stats: found %s\n", stoa(&addr));
996ea906c41SOllivier Robert #endif
9979c2daa00SOllivier Robert 		if (pp->srcadr.ss_family == AF_INET) {
998ea906c41SOllivier Robert 			if (pp->dstadr)
9999c2daa00SOllivier Robert 				ip->dstadr = (pp->processed) ?
10009c2daa00SOllivier Robert 					pp->cast_flags == MDF_BCAST ?
10019c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->bcast):
10029c2daa00SOllivier Robert 					pp->cast_flags ?
10039c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->sin) ?
10049c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->sin):
10059c2daa00SOllivier Robert 					GET_INADDR(pp->dstadr->bcast):
10069c2daa00SOllivier Robert 					3 : 7;
1007ea906c41SOllivier Robert 			else
1008ea906c41SOllivier Robert 				memset(&ip->dstadr, 0, sizeof(ip->dstadr));
1009ea906c41SOllivier Robert 
10109c2daa00SOllivier Robert 			ip->srcadr = GET_INADDR(pp->srcadr);
10119c2daa00SOllivier Robert 			if (client_v6_capable)
10129c2daa00SOllivier Robert 				ip->v6_flag = 0;
10139c2daa00SOllivier Robert 		} else {
1014ea906c41SOllivier Robert 			if (pp->dstadr)
10159c2daa00SOllivier Robert 				ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
10169c2daa00SOllivier Robert 					GET_INADDR6(pp->dstadr->bcast):
10179c2daa00SOllivier Robert 					GET_INADDR6(pp->dstadr->sin);
1018ea906c41SOllivier Robert 			else
1019ea906c41SOllivier Robert 				memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
1020ea906c41SOllivier Robert 
10219c2daa00SOllivier Robert 			ip->srcadr6 = GET_INADDR6(pp->srcadr);
10229c2daa00SOllivier Robert 			ip->v6_flag = 1;
10239c2daa00SOllivier Robert 		}
1024c0b746e5SOllivier Robert 		ip->srcport = NSRCPORT(&pp->srcadr);
1025c0b746e5SOllivier Robert 		ip->flags = 0;
1026c0b746e5SOllivier Robert 		if (pp == sys_peer)
1027c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SYSPEER;
1028c0b746e5SOllivier Robert 		if (pp->flags & FLAG_CONFIG)
1029c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_CONFIG;
1030c0b746e5SOllivier Robert 		if (pp->flags & FLAG_REFCLOCK)
1031c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_REFCLOCK;
1032c0b746e5SOllivier Robert 		if (pp->flags & FLAG_AUTHENABLE)
1033c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_AUTHENABLE;
1034c0b746e5SOllivier Robert 		if (pp->flags & FLAG_PREFER)
1035c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_PREFER;
1036c0b746e5SOllivier Robert 		if (pp->flags & FLAG_BURST)
1037c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_BURST;
1038ea906c41SOllivier Robert 		if (pp->flags & FLAG_IBURST)
1039ea906c41SOllivier Robert 		    ip->flags |= INFO_FLAG_IBURST;
1040c0b746e5SOllivier Robert 		if (pp->status == CTL_PST_SEL_SYNCCAND)
1041c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
1042c0b746e5SOllivier Robert 		if (pp->status >= CTL_PST_SEL_SYSPEER)
1043c0b746e5SOllivier Robert 		    ip->flags |= INFO_FLAG_SHORTLIST;
1044ea906c41SOllivier Robert 		ip->flags = htons(ip->flags);
1045c0b746e5SOllivier Robert 		ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
1046c0b746e5SOllivier Robert 		ip->timetosend = htonl(pp->nextdate - current_time);
1047c0b746e5SOllivier Robert 		ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
1048c0b746e5SOllivier Robert 		ip->sent = htonl((u_int32)(pp->sent));
1049c0b746e5SOllivier Robert 		ip->processed = htonl((u_int32)(pp->processed));
1050c0b746e5SOllivier Robert 		ip->badauth = htonl((u_int32)(pp->badauth));
1051c0b746e5SOllivier Robert 		ip->bogusorg = htonl((u_int32)(pp->bogusorg));
1052c0b746e5SOllivier Robert 		ip->oldpkt = htonl((u_int32)(pp->oldpkt));
1053c0b746e5SOllivier Robert 		ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
1054c0b746e5SOllivier Robert 		ip->selbroken = htonl((u_int32)(pp->selbroken));
1055c0b746e5SOllivier Robert 		ip->candidate = pp->status;
1056c0b746e5SOllivier Robert 		ip = (struct info_peer_stats *)more_pkt();
1057c0b746e5SOllivier Robert 	}
1058c0b746e5SOllivier Robert 	flush_pkt();
1059c0b746e5SOllivier Robert }
1060c0b746e5SOllivier Robert 
1061c0b746e5SOllivier Robert 
1062c0b746e5SOllivier Robert /*
1063c0b746e5SOllivier Robert  * sys_info - return system info
1064c0b746e5SOllivier Robert  */
1065c0b746e5SOllivier Robert static void
1066c0b746e5SOllivier Robert sys_info(
10679c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1068c0b746e5SOllivier Robert 	struct interface *inter,
1069c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1070c0b746e5SOllivier Robert 	)
1071c0b746e5SOllivier Robert {
1072c0b746e5SOllivier Robert 	register struct info_sys *is;
1073c0b746e5SOllivier Robert 
1074c0b746e5SOllivier Robert 	is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
10759c2daa00SOllivier Robert 	    v6sizeof(struct info_sys));
1076c0b746e5SOllivier Robert 
1077c0b746e5SOllivier Robert 	if (sys_peer != 0) {
10789c2daa00SOllivier Robert 		if (sys_peer->srcadr.ss_family == AF_INET) {
10799c2daa00SOllivier Robert 			is->peer = GET_INADDR(sys_peer->srcadr);
10809c2daa00SOllivier Robert 			if (client_v6_capable)
10819c2daa00SOllivier Robert 				is->v6_flag = 0;
10829c2daa00SOllivier Robert 		} else if (client_v6_capable) {
10839c2daa00SOllivier Robert 			is->peer6 = GET_INADDR6(sys_peer->srcadr);
10849c2daa00SOllivier Robert 			is->v6_flag = 1;
10859c2daa00SOllivier Robert 		}
1086c0b746e5SOllivier Robert 		is->peer_mode = sys_peer->hmode;
1087c0b746e5SOllivier Robert 	} else {
1088c0b746e5SOllivier Robert 		is->peer = 0;
10899c2daa00SOllivier Robert 		if (client_v6_capable) {
10909c2daa00SOllivier Robert 			is->v6_flag = 0;
10919c2daa00SOllivier Robert 		}
1092c0b746e5SOllivier Robert 		is->peer_mode = 0;
1093c0b746e5SOllivier Robert 	}
10949c2daa00SOllivier Robert 
1095c0b746e5SOllivier Robert 	is->leap = sys_leap;
1096c0b746e5SOllivier Robert 	is->stratum = sys_stratum;
1097c0b746e5SOllivier Robert 	is->precision = sys_precision;
1098c0b746e5SOllivier Robert 	is->rootdelay = htonl(DTOFP(sys_rootdelay));
1099c0b746e5SOllivier Robert 	is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
1100224ba2bdSOllivier Robert 	is->frequency = htonl(DTOFP(sys_jitter));
1101ea906c41SOllivier Robert 	is->stability = htonl(DTOUFP(clock_stability));
1102c0b746e5SOllivier Robert 	is->refid = sys_refid;
1103c0b746e5SOllivier Robert 	HTONL_FP(&sys_reftime, &is->reftime);
1104c0b746e5SOllivier Robert 
1105c0b746e5SOllivier Robert 	is->poll = sys_poll;
1106c0b746e5SOllivier Robert 
1107c0b746e5SOllivier Robert 	is->flags = 0;
1108c0b746e5SOllivier Robert 	if (sys_authenticate)
1109c0b746e5SOllivier Robert 		is->flags |= INFO_FLAG_AUTHENTICATE;
1110ce265a54SOllivier Robert 	if (sys_bclient)
1111ce265a54SOllivier Robert 		is->flags |= INFO_FLAG_BCLIENT;
1112ce265a54SOllivier Robert #ifdef REFCLOCK
1113ce265a54SOllivier Robert 	if (cal_enable)
1114ce265a54SOllivier Robert 		is->flags |= INFO_FLAG_CAL;
1115ce265a54SOllivier Robert #endif /* REFCLOCK */
1116c0b746e5SOllivier Robert 	if (kern_enable)
1117c0b746e5SOllivier Robert 		is->flags |= INFO_FLAG_KERNEL;
1118c0b746e5SOllivier Robert 	if (mon_enabled != MON_OFF)
1119c0b746e5SOllivier Robert 		is->flags |= INFO_FLAG_MONITOR;
1120ce265a54SOllivier Robert 	if (ntp_enable)
1121ce265a54SOllivier Robert 		is->flags |= INFO_FLAG_NTP;
1122ce265a54SOllivier Robert 	if (pps_enable)
1123ce265a54SOllivier Robert 		is->flags |= INFO_FLAG_PPS_SYNC;
1124c0b746e5SOllivier Robert 	if (stats_control)
1125c0b746e5SOllivier Robert 		is->flags |= INFO_FLAG_FILEGEN;
1126c0b746e5SOllivier Robert 	is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
1127c0b746e5SOllivier Robert 	HTONL_UF(sys_authdelay.l_f, &is->authdelay);
1128c0b746e5SOllivier Robert 
1129c0b746e5SOllivier Robert 	(void) more_pkt();
1130c0b746e5SOllivier Robert 	flush_pkt();
1131c0b746e5SOllivier Robert }
1132c0b746e5SOllivier Robert 
1133c0b746e5SOllivier Robert 
1134c0b746e5SOllivier Robert /*
1135c0b746e5SOllivier Robert  * sys_stats - return system statistics
1136c0b746e5SOllivier Robert  */
1137c0b746e5SOllivier Robert static void
1138c0b746e5SOllivier Robert sys_stats(
11399c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1140c0b746e5SOllivier Robert 	struct interface *inter,
1141c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1142c0b746e5SOllivier Robert 	)
1143c0b746e5SOllivier Robert {
1144c0b746e5SOllivier Robert 	register struct info_sys_stats *ss;
1145c0b746e5SOllivier Robert 
1146c0b746e5SOllivier Robert 	/*
1147c0b746e5SOllivier Robert 	 * Importations from the protocol module
1148c0b746e5SOllivier Robert 	 */
1149c0b746e5SOllivier Robert 	ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
1150c0b746e5SOllivier Robert 		sizeof(struct info_sys_stats));
1151c0b746e5SOllivier Robert 	ss->timeup = htonl((u_int32)current_time);
1152c0b746e5SOllivier Robert 	ss->timereset = htonl((u_int32)(current_time - sys_stattime));
11539c2daa00SOllivier Robert 	ss->denied = htonl((u_int32)sys_restricted);
1154c0b746e5SOllivier Robert 	ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt);
1155c0b746e5SOllivier Robert 	ss->newversionpkt = htonl((u_int32)sys_newversionpkt);
1156c0b746e5SOllivier Robert 	ss->unknownversion = htonl((u_int32)sys_unknownversion);
1157c0b746e5SOllivier Robert 	ss->badlength = htonl((u_int32)sys_badlength);
1158c0b746e5SOllivier Robert 	ss->processed = htonl((u_int32)sys_processed);
1159c0b746e5SOllivier Robert 	ss->badauth = htonl((u_int32)sys_badauth);
1160c0b746e5SOllivier Robert 	ss->limitrejected = htonl((u_int32)sys_limitrejected);
11619c2daa00SOllivier Robert 	ss->received = htonl((u_int32)sys_received);
1162c0b746e5SOllivier Robert 	(void) more_pkt();
1163c0b746e5SOllivier Robert 	flush_pkt();
1164c0b746e5SOllivier Robert }
1165c0b746e5SOllivier Robert 
1166c0b746e5SOllivier Robert 
1167c0b746e5SOllivier Robert /*
1168c0b746e5SOllivier Robert  * mem_stats - return memory statistics
1169c0b746e5SOllivier Robert  */
1170c0b746e5SOllivier Robert static void
1171c0b746e5SOllivier Robert mem_stats(
11729c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1173c0b746e5SOllivier Robert 	struct interface *inter,
1174c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1175c0b746e5SOllivier Robert 	)
1176c0b746e5SOllivier Robert {
1177c0b746e5SOllivier Robert 	register struct info_mem_stats *ms;
1178c0b746e5SOllivier Robert 	register int i;
1179c0b746e5SOllivier Robert 
1180c0b746e5SOllivier Robert 	/*
1181c0b746e5SOllivier Robert 	 * Importations from the peer module
1182c0b746e5SOllivier Robert 	 */
1183ea906c41SOllivier Robert 	extern int peer_hash_count[NTP_HASH_SIZE];
1184c0b746e5SOllivier Robert 	extern int peer_free_count;
1185c0b746e5SOllivier Robert 	extern u_long peer_timereset;
1186c0b746e5SOllivier Robert 	extern u_long findpeer_calls;
1187c0b746e5SOllivier Robert 	extern u_long peer_allocations;
1188c0b746e5SOllivier Robert 	extern u_long peer_demobilizations;
1189c0b746e5SOllivier Robert 	extern int total_peer_structs;
1190c0b746e5SOllivier Robert 
1191c0b746e5SOllivier Robert 	ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
1192c0b746e5SOllivier Robert 						  sizeof(struct info_mem_stats));
1193c0b746e5SOllivier Robert 
1194c0b746e5SOllivier Robert 	ms->timereset = htonl((u_int32)(current_time - peer_timereset));
1195c0b746e5SOllivier Robert 	ms->totalpeermem = htons((u_short)total_peer_structs);
1196c0b746e5SOllivier Robert 	ms->freepeermem = htons((u_short)peer_free_count);
1197c0b746e5SOllivier Robert 	ms->findpeer_calls = htonl((u_int32)findpeer_calls);
1198c0b746e5SOllivier Robert 	ms->allocations = htonl((u_int32)peer_allocations);
1199c0b746e5SOllivier Robert 	ms->demobilizations = htonl((u_int32)peer_demobilizations);
1200c0b746e5SOllivier Robert 
1201ea906c41SOllivier Robert 	for (i = 0; i < NTP_HASH_SIZE; i++) {
1202c0b746e5SOllivier Robert 		if (peer_hash_count[i] > 255)
1203c0b746e5SOllivier Robert 		    ms->hashcount[i] = 255;
1204c0b746e5SOllivier Robert 		else
1205c0b746e5SOllivier Robert 		    ms->hashcount[i] = (u_char)peer_hash_count[i];
1206c0b746e5SOllivier Robert 	}
1207c0b746e5SOllivier Robert 
1208c0b746e5SOllivier Robert 	(void) more_pkt();
1209c0b746e5SOllivier Robert 	flush_pkt();
1210c0b746e5SOllivier Robert }
1211c0b746e5SOllivier Robert 
1212c0b746e5SOllivier Robert 
1213c0b746e5SOllivier Robert /*
1214c0b746e5SOllivier Robert  * io_stats - return io statistics
1215c0b746e5SOllivier Robert  */
1216c0b746e5SOllivier Robert static void
1217c0b746e5SOllivier Robert io_stats(
12189c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1219c0b746e5SOllivier Robert 	struct interface *inter,
1220c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1221c0b746e5SOllivier Robert 	)
1222c0b746e5SOllivier Robert {
1223c0b746e5SOllivier Robert 	register struct info_io_stats *io;
1224c0b746e5SOllivier Robert 
1225c0b746e5SOllivier Robert 	/*
1226c0b746e5SOllivier Robert 	 * Importations from the io module
1227c0b746e5SOllivier Robert 	 */
1228c0b746e5SOllivier Robert 	extern u_long io_timereset;
1229c0b746e5SOllivier Robert 
1230c0b746e5SOllivier Robert 	io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
1231c0b746e5SOllivier Robert 						 sizeof(struct info_io_stats));
1232c0b746e5SOllivier Robert 
1233c0b746e5SOllivier Robert 	io->timereset = htonl((u_int32)(current_time - io_timereset));
1234c0b746e5SOllivier Robert 	io->totalrecvbufs = htons((u_short) total_recvbuffs());
1235c0b746e5SOllivier Robert 	io->freerecvbufs = htons((u_short) free_recvbuffs());
1236c0b746e5SOllivier Robert 	io->fullrecvbufs = htons((u_short) full_recvbuffs());
1237c0b746e5SOllivier Robert 	io->lowwater = htons((u_short) lowater_additions());
1238c0b746e5SOllivier Robert 	io->dropped = htonl((u_int32)packets_dropped);
1239c0b746e5SOllivier Robert 	io->ignored = htonl((u_int32)packets_ignored);
1240c0b746e5SOllivier Robert 	io->received = htonl((u_int32)packets_received);
1241c0b746e5SOllivier Robert 	io->sent = htonl((u_int32)packets_sent);
1242c0b746e5SOllivier Robert 	io->notsent = htonl((u_int32)packets_notsent);
1243c0b746e5SOllivier Robert 	io->interrupts = htonl((u_int32)handler_calls);
1244c0b746e5SOllivier Robert 	io->int_received = htonl((u_int32)handler_pkts);
1245c0b746e5SOllivier Robert 
1246c0b746e5SOllivier Robert 	(void) more_pkt();
1247c0b746e5SOllivier Robert 	flush_pkt();
1248c0b746e5SOllivier Robert }
1249c0b746e5SOllivier Robert 
1250c0b746e5SOllivier Robert 
1251c0b746e5SOllivier Robert /*
1252c0b746e5SOllivier Robert  * timer_stats - return timer statistics
1253c0b746e5SOllivier Robert  */
1254c0b746e5SOllivier Robert static void
1255c0b746e5SOllivier Robert timer_stats(
12569c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1257c0b746e5SOllivier Robert 	struct interface *inter,
1258c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1259c0b746e5SOllivier Robert 	)
1260c0b746e5SOllivier Robert {
1261c0b746e5SOllivier Robert 	register struct info_timer_stats *ts;
1262c0b746e5SOllivier Robert 
1263c0b746e5SOllivier Robert 	/*
1264c0b746e5SOllivier Robert 	 * Importations from the timer module
1265c0b746e5SOllivier Robert 	 */
1266c0b746e5SOllivier Robert 	extern u_long timer_timereset;
1267c0b746e5SOllivier Robert 	extern u_long timer_overflows;
1268c0b746e5SOllivier Robert 	extern u_long timer_xmtcalls;
1269c0b746e5SOllivier Robert 
1270c0b746e5SOllivier Robert 	ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt,
1271c0b746e5SOllivier Robert 						    sizeof(struct info_timer_stats));
1272c0b746e5SOllivier Robert 
1273c0b746e5SOllivier Robert 	ts->timereset = htonl((u_int32)(current_time - timer_timereset));
1274c0b746e5SOllivier Robert 	ts->alarms = htonl((u_int32)alarm_overflow);
1275c0b746e5SOllivier Robert 	ts->overflows = htonl((u_int32)timer_overflows);
1276c0b746e5SOllivier Robert 	ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
1277c0b746e5SOllivier Robert 
1278c0b746e5SOllivier Robert 	(void) more_pkt();
1279c0b746e5SOllivier Robert 	flush_pkt();
1280c0b746e5SOllivier Robert }
1281c0b746e5SOllivier Robert 
1282c0b746e5SOllivier Robert 
1283c0b746e5SOllivier Robert /*
1284c0b746e5SOllivier Robert  * loop_info - return the current state of the loop filter
1285c0b746e5SOllivier Robert  */
1286c0b746e5SOllivier Robert static void
1287c0b746e5SOllivier Robert loop_info(
12889c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1289c0b746e5SOllivier Robert 	struct interface *inter,
1290c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1291c0b746e5SOllivier Robert 	)
1292c0b746e5SOllivier Robert {
1293c0b746e5SOllivier Robert 	register struct info_loop *li;
1294c0b746e5SOllivier Robert 	l_fp ltmp;
1295c0b746e5SOllivier Robert 
1296c0b746e5SOllivier Robert 	/*
1297c0b746e5SOllivier Robert 	 * Importations from the loop filter module
1298c0b746e5SOllivier Robert 	 */
1299c0b746e5SOllivier Robert 	extern double last_offset;
1300c0b746e5SOllivier Robert 	extern double drift_comp;
1301c0b746e5SOllivier Robert 	extern int tc_counter;
1302ea906c41SOllivier Robert 	extern u_long sys_clocktime;
1303c0b746e5SOllivier Robert 
1304c0b746e5SOllivier Robert 	li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
1305c0b746e5SOllivier Robert 	    sizeof(struct info_loop));
1306c0b746e5SOllivier Robert 
1307c0b746e5SOllivier Robert 	DTOLFP(last_offset, &ltmp);
1308c0b746e5SOllivier Robert 	HTONL_FP(&ltmp, &li->last_offset);
1309c0b746e5SOllivier Robert 	DTOLFP(drift_comp * 1e6, &ltmp);
1310c0b746e5SOllivier Robert 	HTONL_FP(&ltmp, &li->drift_comp);
1311c0b746e5SOllivier Robert 	li->compliance = htonl((u_int32)(tc_counter));
1312ea906c41SOllivier Robert 	li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime));
1313c0b746e5SOllivier Robert 
1314c0b746e5SOllivier Robert 	(void) more_pkt();
1315c0b746e5SOllivier Robert 	flush_pkt();
1316c0b746e5SOllivier Robert }
1317c0b746e5SOllivier Robert 
1318c0b746e5SOllivier Robert 
1319c0b746e5SOllivier Robert /*
1320c0b746e5SOllivier Robert  * do_conf - add a peer to the configuration list
1321c0b746e5SOllivier Robert  */
1322c0b746e5SOllivier Robert static void
1323c0b746e5SOllivier Robert do_conf(
13249c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1325c0b746e5SOllivier Robert 	struct interface *inter,
1326c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1327c0b746e5SOllivier Robert 	)
1328c0b746e5SOllivier Robert {
1329eb6d21b4SOllivier Robert 	static u_long soonest_ifrescan_time = 0;
13309c2daa00SOllivier Robert 	int items;
1331224ba2bdSOllivier Robert 	u_int fl;
1332ce265a54SOllivier Robert 	struct conf_peer *cp;
13339c2daa00SOllivier Robert 	struct conf_peer temp_cp;
13349c2daa00SOllivier Robert 	struct sockaddr_storage peeraddr;
13359c2daa00SOllivier Robert 	struct sockaddr_in tmp_clock;
1336c0b746e5SOllivier Robert 
1337c0b746e5SOllivier Robert 	/*
1338c0b746e5SOllivier Robert 	 * Do a check of everything to see that it looks
1339c0b746e5SOllivier Robert 	 * okay.  If not, complain about it.  Note we are
1340c0b746e5SOllivier Robert 	 * very picky here.
1341c0b746e5SOllivier Robert 	 */
1342c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1343c0b746e5SOllivier Robert 	cp = (struct conf_peer *)inpkt->data;
13449c2daa00SOllivier Robert 	memset(&temp_cp, 0, sizeof(struct conf_peer));
13459c2daa00SOllivier Robert 	memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1346c0b746e5SOllivier Robert 	fl = 0;
1347c0b746e5SOllivier Robert 	while (items-- > 0 && !fl) {
13489c2daa00SOllivier Robert 		if (((temp_cp.version) > NTP_VERSION)
13499c2daa00SOllivier Robert 		    || ((temp_cp.version) < NTP_OLDVERSION))
1350c0b746e5SOllivier Robert 		    fl = 1;
13519c2daa00SOllivier Robert 		if (temp_cp.hmode != MODE_ACTIVE
13529c2daa00SOllivier Robert 		    && temp_cp.hmode != MODE_CLIENT
13539c2daa00SOllivier Robert 		    && temp_cp.hmode != MODE_BROADCAST)
1354c0b746e5SOllivier Robert 		    fl = 1;
13559c2daa00SOllivier Robert 		if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
1356ea906c41SOllivier Robert 				  | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY))
1357c0b746e5SOllivier Robert 		    fl = 1;
13589c2daa00SOllivier Robert 		cp = (struct conf_peer *)
13599c2daa00SOllivier Robert 		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1360c0b746e5SOllivier Robert 	}
1361c0b746e5SOllivier Robert 
1362c0b746e5SOllivier Robert 	if (fl) {
1363c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1364c0b746e5SOllivier Robert 		return;
1365c0b746e5SOllivier Robert 	}
1366c0b746e5SOllivier Robert 
1367c0b746e5SOllivier Robert 	/*
1368c0b746e5SOllivier Robert 	 * Looks okay, try it out
1369c0b746e5SOllivier Robert 	 */
1370c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1371c0b746e5SOllivier Robert 	cp = (struct conf_peer *)inpkt->data;
1372c0b746e5SOllivier Robert 
13739c2daa00SOllivier Robert 	while (items-- > 0) {
13749c2daa00SOllivier Robert 		memset(&temp_cp, 0, sizeof(struct conf_peer));
13759c2daa00SOllivier Robert 		memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
13769c2daa00SOllivier Robert 		memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage));
13779c2daa00SOllivier Robert 
13789c2daa00SOllivier Robert 		fl = 0;
13799c2daa00SOllivier Robert 		if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
13809c2daa00SOllivier Robert 			fl |= FLAG_AUTHENABLE;
13819c2daa00SOllivier Robert 		if (temp_cp.flags & CONF_FLAG_PREFER)
13829c2daa00SOllivier Robert 			fl |= FLAG_PREFER;
13839c2daa00SOllivier Robert 		if (temp_cp.flags & CONF_FLAG_BURST)
13849c2daa00SOllivier Robert 		    fl |= FLAG_BURST;
1385ea906c41SOllivier Robert 		if (temp_cp.flags & CONF_FLAG_IBURST)
1386ea906c41SOllivier Robert 		    fl |= FLAG_IBURST;
13879c2daa00SOllivier Robert 		if (temp_cp.flags & CONF_FLAG_SKEY)
13889c2daa00SOllivier Robert 			fl |= FLAG_SKEY;
1389ea906c41SOllivier Robert 
13909c2daa00SOllivier Robert 		if (client_v6_capable && temp_cp.v6_flag != 0) {
13919c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET6;
13929c2daa00SOllivier Robert 			GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
13939c2daa00SOllivier Robert 		} else {
13949c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET;
13959c2daa00SOllivier Robert 			GET_INADDR(peeraddr) = temp_cp.peeraddr;
1396c0b746e5SOllivier Robert 			/*
1397c0b746e5SOllivier Robert 			 * Make sure the address is valid
1398c0b746e5SOllivier Robert 			 */
13999c2daa00SOllivier Robert 			tmp_clock = *CAST_V4(peeraddr);
1400c0b746e5SOllivier Robert 			if (
1401c0b746e5SOllivier Robert #ifdef REFCLOCK
14029c2daa00SOllivier Robert 				!ISREFCLOCKADR(&tmp_clock) &&
1403c0b746e5SOllivier Robert #endif
14049c2daa00SOllivier Robert 				ISBADADR(&tmp_clock)) {
1405c0b746e5SOllivier Robert 				req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1406c0b746e5SOllivier Robert 				return;
1407c0b746e5SOllivier Robert 			}
1408c0b746e5SOllivier Robert 
14099c2daa00SOllivier Robert 		}
14109c2daa00SOllivier Robert 		NSRCPORT(&peeraddr) = htons(NTP_PORT);
14119c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
14129c2daa00SOllivier Robert 		peeraddr.ss_len = SOCKLEN(&peeraddr);
14139c2daa00SOllivier Robert #endif
14149c2daa00SOllivier Robert 
1415c0b746e5SOllivier Robert 		/* XXX W2DO? minpoll/maxpoll arguments ??? */
14169c2daa00SOllivier Robert 		if (peer_config(&peeraddr, (struct interface *)0,
14179c2daa00SOllivier Robert 		    temp_cp.hmode, temp_cp.version, temp_cp.minpoll,
14189c2daa00SOllivier Robert 		    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
14199c2daa00SOllivier Robert 		    NULL) == 0) {
1420c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1421c0b746e5SOllivier Robert 			return;
1422c0b746e5SOllivier Robert 		}
1423eb6d21b4SOllivier Robert 
1424eb6d21b4SOllivier Robert 		/*
1425eb6d21b4SOllivier Robert 		 * ntp_intres.c uses REQ_CONFIG/doconf() to add each
1426eb6d21b4SOllivier Robert 		 * server after its name is resolved.  If we have been
1427eb6d21b4SOllivier Robert 		 * disconnected from the network, it may notice the
1428eb6d21b4SOllivier Robert 		 * network has returned and add the first server while
1429eb6d21b4SOllivier Robert 		 * the relevant interface is still disabled, awaiting
1430eb6d21b4SOllivier Robert 		 * the next interface rescan.  To get things moving
1431eb6d21b4SOllivier Robert 		 * more quickly, trigger an interface scan now, except
1432eb6d21b4SOllivier Robert 		 * if we have done so in the last half minute.
1433eb6d21b4SOllivier Robert 		 */
1434eb6d21b4SOllivier Robert 		if (soonest_ifrescan_time < current_time) {
1435eb6d21b4SOllivier Robert 			soonest_ifrescan_time = current_time + 30;
1436eb6d21b4SOllivier Robert 			timer_interfacetimeout(current_time);
1437eb6d21b4SOllivier Robert 			DPRINTF(1, ("do_conf triggering interface rescan\n"));
1438eb6d21b4SOllivier Robert 		}
1439eb6d21b4SOllivier Robert 
14409c2daa00SOllivier Robert 		cp = (struct conf_peer *)
14419c2daa00SOllivier Robert 		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1442c0b746e5SOllivier Robert 	}
1443c0b746e5SOllivier Robert 
1444c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1445c0b746e5SOllivier Robert }
1446c0b746e5SOllivier Robert 
14479c2daa00SOllivier Robert #if 0
14489c2daa00SOllivier Robert /* XXX */
1449c0b746e5SOllivier Robert /*
1450224ba2bdSOllivier Robert  * dns_a - Snarf DNS info for an association ID
1451224ba2bdSOllivier Robert  */
1452224ba2bdSOllivier Robert static void
1453224ba2bdSOllivier Robert dns_a(
14549c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1455224ba2bdSOllivier Robert 	struct interface *inter,
1456224ba2bdSOllivier Robert 	struct req_pkt *inpkt
1457224ba2bdSOllivier Robert 	)
1458224ba2bdSOllivier Robert {
1459224ba2bdSOllivier Robert 	register struct info_dns_assoc *dp;
1460224ba2bdSOllivier Robert 	register int items;
1461224ba2bdSOllivier Robert 	struct sockaddr_in peeraddr;
1462224ba2bdSOllivier Robert 
1463224ba2bdSOllivier Robert 	/*
1464224ba2bdSOllivier Robert 	 * Do a check of everything to see that it looks
1465224ba2bdSOllivier Robert 	 * okay.  If not, complain about it.  Note we are
1466224ba2bdSOllivier Robert 	 * very picky here.
1467224ba2bdSOllivier Robert 	 */
1468224ba2bdSOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1469224ba2bdSOllivier Robert 	dp = (struct info_dns_assoc *)inpkt->data;
1470224ba2bdSOllivier Robert 
1471224ba2bdSOllivier Robert 	/*
1472224ba2bdSOllivier Robert 	 * Looks okay, try it out
1473224ba2bdSOllivier Robert 	 */
1474224ba2bdSOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1475224ba2bdSOllivier Robert 	dp = (struct info_dns_assoc *)inpkt->data;
1476224ba2bdSOllivier Robert 	memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
1477224ba2bdSOllivier Robert 	peeraddr.sin_family = AF_INET;
1478224ba2bdSOllivier Robert 	peeraddr.sin_port = htons(NTP_PORT);
1479224ba2bdSOllivier Robert 
1480224ba2bdSOllivier Robert 	/*
1481224ba2bdSOllivier Robert 	 * Make sure the address is valid
1482224ba2bdSOllivier Robert 	 */
1483224ba2bdSOllivier Robert 	if (
1484224ba2bdSOllivier Robert #ifdef REFCLOCK
1485224ba2bdSOllivier Robert 		!ISREFCLOCKADR(&peeraddr) &&
1486224ba2bdSOllivier Robert #endif
1487224ba2bdSOllivier Robert 		ISBADADR(&peeraddr)) {
1488224ba2bdSOllivier Robert #ifdef REFCLOCK
1489224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
1490224ba2bdSOllivier Robert #else
1491224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "dns_a: ISBADADR");
1492224ba2bdSOllivier Robert #endif
1493224ba2bdSOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1494224ba2bdSOllivier Robert 		return;
1495224ba2bdSOllivier Robert 	}
1496224ba2bdSOllivier Robert 
1497224ba2bdSOllivier Robert 	while (items-- > 0) {
1498224ba2bdSOllivier Robert 		associd_t associd;
1499224ba2bdSOllivier Robert 		size_t hnl;
1500224ba2bdSOllivier Robert 		struct peer *peer;
1501224ba2bdSOllivier Robert 		int bogon = 0;
1502224ba2bdSOllivier Robert 
1503224ba2bdSOllivier Robert 		associd = dp->associd;
1504224ba2bdSOllivier Robert 		peer = findpeerbyassoc(associd);
1505224ba2bdSOllivier Robert 		if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
1506224ba2bdSOllivier Robert 			msyslog(LOG_ERR, "dns_a: %s",
1507224ba2bdSOllivier Robert 				(peer == 0)
1508224ba2bdSOllivier Robert 				? "peer == 0"
1509224ba2bdSOllivier Robert 				: "peer->flags & FLAG_REFCLOCK");
1510224ba2bdSOllivier Robert 			++bogon;
1511224ba2bdSOllivier Robert 		}
1512224ba2bdSOllivier Robert 		peeraddr.sin_addr.s_addr = dp->peeraddr;
1513224ba2bdSOllivier Robert 		for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
1514224ba2bdSOllivier Robert 		if (hnl >= sizeof dp->hostname) {
1515224ba2bdSOllivier Robert 			msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
1516224ba2bdSOllivier Robert 				(long)hnl, (long)sizeof dp->hostname);
1517224ba2bdSOllivier Robert 			++bogon;
1518224ba2bdSOllivier Robert 		}
1519224ba2bdSOllivier Robert 
1520224ba2bdSOllivier Robert 		msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
15219c2daa00SOllivier Robert 			dp->hostname,
15229c2daa00SOllivier Robert 			stoa((struct sockaddr_storage *)&peeraddr), associd,
1523224ba2bdSOllivier Robert 			bogon);
1524224ba2bdSOllivier Robert 
1525224ba2bdSOllivier Robert 		if (bogon) {
1526224ba2bdSOllivier Robert 			/* If it didn't work */
1527224ba2bdSOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1528224ba2bdSOllivier Robert 			return;
1529224ba2bdSOllivier Robert 		} else {
1530224ba2bdSOllivier Robert #if 0
1531224ba2bdSOllivier Robert #ifdef PUBKEY
1532224ba2bdSOllivier Robert 			crypto_public(peer, dp->hostname);
1533224ba2bdSOllivier Robert #endif /* PUBKEY */
1534224ba2bdSOllivier Robert #endif
1535224ba2bdSOllivier Robert 		}
1536224ba2bdSOllivier Robert 
1537224ba2bdSOllivier Robert 		dp++;
1538224ba2bdSOllivier Robert 	}
1539224ba2bdSOllivier Robert 
1540224ba2bdSOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1541224ba2bdSOllivier Robert }
15429c2daa00SOllivier Robert #endif /* 0 */
1543224ba2bdSOllivier Robert 
1544224ba2bdSOllivier Robert /*
1545c0b746e5SOllivier Robert  * do_unconf - remove a peer from the configuration list
1546c0b746e5SOllivier Robert  */
1547c0b746e5SOllivier Robert static void
1548c0b746e5SOllivier Robert do_unconf(
15499c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1550c0b746e5SOllivier Robert 	struct interface *inter,
1551c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1552c0b746e5SOllivier Robert 	)
1553c0b746e5SOllivier Robert {
1554c0b746e5SOllivier Robert 	register struct conf_unpeer *cp;
15559c2daa00SOllivier Robert 	struct conf_unpeer temp_cp;
1556c0b746e5SOllivier Robert 	register int items;
1557c0b746e5SOllivier Robert 	register struct peer *peer;
15589c2daa00SOllivier Robert 	struct sockaddr_storage peeraddr;
1559c0b746e5SOllivier Robert 	int bad, found;
1560c0b746e5SOllivier Robert 
1561c0b746e5SOllivier Robert 	/*
1562c0b746e5SOllivier Robert 	 * This is a bit unstructured, but I like to be careful.
1563c0b746e5SOllivier Robert 	 * We check to see that every peer exists and is actually
1564c0b746e5SOllivier Robert 	 * configured.  If so, we remove them.  If not, we return
1565c0b746e5SOllivier Robert 	 * an error.
1566c0b746e5SOllivier Robert 	 */
1567c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1568c0b746e5SOllivier Robert 	cp = (struct conf_unpeer *)inpkt->data;
1569c0b746e5SOllivier Robert 
1570c0b746e5SOllivier Robert 	bad = 0;
1571c0b746e5SOllivier Robert 	while (items-- > 0 && !bad) {
15729c2daa00SOllivier Robert 		memset(&temp_cp, 0, sizeof(temp_cp));
15739c2daa00SOllivier Robert 		memset(&peeraddr, 0, sizeof(peeraddr));
15749c2daa00SOllivier Robert 		memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
15759c2daa00SOllivier Robert 		if (client_v6_capable && temp_cp.v6_flag != 0) {
15769c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET6;
15779c2daa00SOllivier Robert 			GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
15789c2daa00SOllivier Robert 		} else {
15799c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET;
15809c2daa00SOllivier Robert 			GET_INADDR(peeraddr) = temp_cp.peeraddr;
15819c2daa00SOllivier Robert 		}
15829c2daa00SOllivier Robert 		NSRCPORT(&peeraddr) = htons(NTP_PORT);
15839c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
15849c2daa00SOllivier Robert 		peeraddr.ss_len = SOCKLEN(&peeraddr);
15859c2daa00SOllivier Robert #endif
1586c0b746e5SOllivier Robert 		found = 0;
1587c0b746e5SOllivier Robert 		peer = (struct peer *)0;
1588ea906c41SOllivier Robert #ifdef DEBUG
1589ea906c41SOllivier Robert 		if (debug)
15909c2daa00SOllivier Robert 		     printf("searching for %s\n", stoa(&peeraddr));
1591ea906c41SOllivier Robert #endif
1592c0b746e5SOllivier Robert 		while (!found) {
1593c0b746e5SOllivier Robert 			peer = findexistingpeer(&peeraddr, peer, -1);
1594c0b746e5SOllivier Robert 			if (peer == (struct peer *)0)
1595c0b746e5SOllivier Robert 			    break;
1596c0b746e5SOllivier Robert 			if (peer->flags & FLAG_CONFIG)
1597c0b746e5SOllivier Robert 			    found = 1;
1598c0b746e5SOllivier Robert 		}
1599c0b746e5SOllivier Robert 		if (!found)
1600c0b746e5SOllivier Robert 		    bad = 1;
16019c2daa00SOllivier Robert 		cp = (struct conf_unpeer *)
16029c2daa00SOllivier Robert 		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1603c0b746e5SOllivier Robert 	}
1604c0b746e5SOllivier Robert 
1605c0b746e5SOllivier Robert 	if (bad) {
1606c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1607c0b746e5SOllivier Robert 		return;
1608c0b746e5SOllivier Robert 	}
1609c0b746e5SOllivier Robert 
1610c0b746e5SOllivier Robert 	/*
1611c0b746e5SOllivier Robert 	 * Now do it in earnest.
1612c0b746e5SOllivier Robert 	 */
1613c0b746e5SOllivier Robert 
1614c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1615c0b746e5SOllivier Robert 	cp = (struct conf_unpeer *)inpkt->data;
1616c0b746e5SOllivier Robert 	while (items-- > 0) {
16179c2daa00SOllivier Robert 		memset(&temp_cp, 0, sizeof(temp_cp));
16189c2daa00SOllivier Robert 		memset(&peeraddr, 0, sizeof(peeraddr));
16199c2daa00SOllivier Robert 		memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
16209c2daa00SOllivier Robert 		if (client_v6_capable && temp_cp.v6_flag != 0) {
16219c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET6;
16229c2daa00SOllivier Robert 			GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
16239c2daa00SOllivier Robert 		} else {
16249c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET;
16259c2daa00SOllivier Robert 			GET_INADDR(peeraddr) = temp_cp.peeraddr;
16269c2daa00SOllivier Robert 		}
16279c2daa00SOllivier Robert 		NSRCPORT(&peeraddr) = htons(NTP_PORT);
16289c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
16299c2daa00SOllivier Robert 		peeraddr.ss_len = SOCKLEN(&peeraddr);
16309c2daa00SOllivier Robert #endif
1631c0b746e5SOllivier Robert 		peer_unconfig(&peeraddr, (struct interface *)0, -1);
16329c2daa00SOllivier Robert 		cp = (struct conf_unpeer *)
16339c2daa00SOllivier Robert 		    ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1634c0b746e5SOllivier Robert 	}
1635c0b746e5SOllivier Robert 
1636c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1637c0b746e5SOllivier Robert }
1638c0b746e5SOllivier Robert 
1639c0b746e5SOllivier Robert 
1640c0b746e5SOllivier Robert /*
1641c0b746e5SOllivier Robert  * set_sys_flag - set system flags
1642c0b746e5SOllivier Robert  */
1643c0b746e5SOllivier Robert static void
1644c0b746e5SOllivier Robert set_sys_flag(
16459c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1646c0b746e5SOllivier Robert 	struct interface *inter,
1647c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1648c0b746e5SOllivier Robert 	)
1649c0b746e5SOllivier Robert {
1650c0b746e5SOllivier Robert 	setclr_flags(srcadr, inter, inpkt, 1);
1651c0b746e5SOllivier Robert }
1652c0b746e5SOllivier Robert 
1653c0b746e5SOllivier Robert 
1654c0b746e5SOllivier Robert /*
1655c0b746e5SOllivier Robert  * clr_sys_flag - clear system flags
1656c0b746e5SOllivier Robert  */
1657c0b746e5SOllivier Robert static void
1658c0b746e5SOllivier Robert clr_sys_flag(
16599c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1660c0b746e5SOllivier Robert 	struct interface *inter,
1661c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1662c0b746e5SOllivier Robert 	)
1663c0b746e5SOllivier Robert {
1664c0b746e5SOllivier Robert 	setclr_flags(srcadr, inter, inpkt, 0);
1665c0b746e5SOllivier Robert }
1666c0b746e5SOllivier Robert 
1667c0b746e5SOllivier Robert 
1668c0b746e5SOllivier Robert /*
1669c0b746e5SOllivier Robert  * setclr_flags - do the grunge work of flag setting/clearing
1670c0b746e5SOllivier Robert  */
1671c0b746e5SOllivier Robert static void
1672c0b746e5SOllivier Robert setclr_flags(
16739c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1674c0b746e5SOllivier Robert 	struct interface *inter,
1675c0b746e5SOllivier Robert 	struct req_pkt *inpkt,
1676c0b746e5SOllivier Robert 	u_long set
1677c0b746e5SOllivier Robert 	)
1678c0b746e5SOllivier Robert {
1679224ba2bdSOllivier Robert 	register u_int flags;
1680ea906c41SOllivier Robert 	int prev_kern_enable;
1681c0b746e5SOllivier Robert 
1682ea906c41SOllivier Robert 	prev_kern_enable = kern_enable;
1683c0b746e5SOllivier Robert 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1684224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
1685c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1686c0b746e5SOllivier Robert 		return;
1687c0b746e5SOllivier Robert 	}
1688c0b746e5SOllivier Robert 
1689c0b746e5SOllivier Robert 	flags = ((struct conf_sys_flags *)inpkt->data)->flags;
1690ea906c41SOllivier Robert 	flags = ntohl(flags);
1691c0b746e5SOllivier Robert 
1692224ba2bdSOllivier Robert 	if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1693c0b746e5SOllivier Robert 		      SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
1694ce265a54SOllivier Robert 		      SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
1695224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
1696224ba2bdSOllivier Robert 			flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1697224ba2bdSOllivier Robert 				  SYS_FLAG_NTP | SYS_FLAG_KERNEL |
1698ce265a54SOllivier Robert 				  SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
1699ce265a54SOllivier Robert 				  SYS_FLAG_AUTH | SYS_FLAG_CAL));
1700c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1701c0b746e5SOllivier Robert 		return;
1702c0b746e5SOllivier Robert 	}
1703c0b746e5SOllivier Robert 
1704c0b746e5SOllivier Robert 	if (flags & SYS_FLAG_BCLIENT)
17059c2daa00SOllivier Robert 		proto_config(PROTO_BROADCLIENT, set, 0., NULL);
1706224ba2bdSOllivier Robert 	if (flags & SYS_FLAG_PPS)
17079c2daa00SOllivier Robert 		proto_config(PROTO_PPS, set, 0., NULL);
1708c0b746e5SOllivier Robert 	if (flags & SYS_FLAG_NTP)
17099c2daa00SOllivier Robert 		proto_config(PROTO_NTP, set, 0., NULL);
1710c0b746e5SOllivier Robert 	if (flags & SYS_FLAG_KERNEL)
17119c2daa00SOllivier Robert 		proto_config(PROTO_KERNEL, set, 0., NULL);
1712c0b746e5SOllivier Robert 	if (flags & SYS_FLAG_MONITOR)
17139c2daa00SOllivier Robert 		proto_config(PROTO_MONITOR, set, 0., NULL);
1714c0b746e5SOllivier Robert 	if (flags & SYS_FLAG_FILEGEN)
17159c2daa00SOllivier Robert 		proto_config(PROTO_FILEGEN, set, 0., NULL);
1716ce265a54SOllivier Robert 	if (flags & SYS_FLAG_AUTH)
17179c2daa00SOllivier Robert 		proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
1718ce265a54SOllivier Robert 	if (flags & SYS_FLAG_CAL)
17199c2daa00SOllivier Robert 		proto_config(PROTO_CAL, set, 0., NULL);
1720c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1721ea906c41SOllivier Robert 
1722ea906c41SOllivier Robert 	/* Reset the kernel ntp parameters if the kernel flag changed. */
1723ea906c41SOllivier Robert 	if (prev_kern_enable && !kern_enable)
1724ea906c41SOllivier Robert 	     	loop_config(LOOP_KERN_CLEAR, 0.0);
1725ea906c41SOllivier Robert 	if (!prev_kern_enable && kern_enable)
1726ea906c41SOllivier Robert 	     	loop_config(LOOP_DRIFTCOMP, drift_comp);
1727c0b746e5SOllivier Robert }
1728c0b746e5SOllivier Robert 
1729c0b746e5SOllivier Robert 
1730c0b746e5SOllivier Robert /*
1731c0b746e5SOllivier Robert  * list_restrict - return the restrict list
1732c0b746e5SOllivier Robert  */
1733c0b746e5SOllivier Robert static void
1734c0b746e5SOllivier Robert list_restrict(
17359c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1736c0b746e5SOllivier Robert 	struct interface *inter,
1737c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1738c0b746e5SOllivier Robert 	)
1739c0b746e5SOllivier Robert {
1740c0b746e5SOllivier Robert 	register struct info_restrict *ir;
1741c0b746e5SOllivier Robert 	register struct restrictlist *rl;
17429c2daa00SOllivier Robert 	register struct restrictlist6 *rl6;
1743c0b746e5SOllivier Robert 
1744c0b746e5SOllivier Robert #ifdef DEBUG
1745c0b746e5SOllivier Robert 	if (debug > 2)
17469c2daa00SOllivier Robert 	    printf("wants restrict list summary\n");
1747c0b746e5SOllivier Robert #endif
1748c0b746e5SOllivier Robert 
1749c0b746e5SOllivier Robert 	ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
17509c2daa00SOllivier Robert 	    v6sizeof(struct info_restrict));
17519c2daa00SOllivier Robert 
1752c0b746e5SOllivier Robert 	for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
1753c0b746e5SOllivier Robert 		ir->addr = htonl(rl->addr);
17549c2daa00SOllivier Robert 		if (client_v6_capable)
17559c2daa00SOllivier Robert 			ir->v6_flag = 0;
1756c0b746e5SOllivier Robert 		ir->mask = htonl(rl->mask);
1757c0b746e5SOllivier Robert 		ir->count = htonl((u_int32)rl->count);
1758c0b746e5SOllivier Robert 		ir->flags = htons(rl->flags);
1759c0b746e5SOllivier Robert 		ir->mflags = htons(rl->mflags);
1760c0b746e5SOllivier Robert 		ir = (struct info_restrict *)more_pkt();
1761c0b746e5SOllivier Robert 	}
17629c2daa00SOllivier Robert 	if (client_v6_capable)
17639c2daa00SOllivier Robert 		for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
17649c2daa00SOllivier Robert 			ir->addr6 = rl6->addr6;
17659c2daa00SOllivier Robert 			ir->mask6 = rl6->mask6;
17669c2daa00SOllivier Robert 			ir->v6_flag = 1;
17679c2daa00SOllivier Robert 			ir->count = htonl((u_int32)rl6->count);
17689c2daa00SOllivier Robert 			ir->flags = htons(rl6->flags);
17699c2daa00SOllivier Robert 			ir->mflags = htons(rl6->mflags);
17709c2daa00SOllivier Robert 			ir = (struct info_restrict *)more_pkt();
17719c2daa00SOllivier Robert 		}
1772c0b746e5SOllivier Robert 	flush_pkt();
1773c0b746e5SOllivier Robert }
1774c0b746e5SOllivier Robert 
1775c0b746e5SOllivier Robert 
1776c0b746e5SOllivier Robert 
1777c0b746e5SOllivier Robert /*
1778c0b746e5SOllivier Robert  * do_resaddflags - add flags to a restrict entry (or create one)
1779c0b746e5SOllivier Robert  */
1780c0b746e5SOllivier Robert static void
1781c0b746e5SOllivier Robert do_resaddflags(
17829c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1783c0b746e5SOllivier Robert 	struct interface *inter,
1784c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1785c0b746e5SOllivier Robert 	)
1786c0b746e5SOllivier Robert {
1787c0b746e5SOllivier Robert 	do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
1788c0b746e5SOllivier Robert }
1789c0b746e5SOllivier Robert 
1790c0b746e5SOllivier Robert 
1791c0b746e5SOllivier Robert 
1792c0b746e5SOllivier Robert /*
1793c0b746e5SOllivier Robert  * do_ressubflags - remove flags from a restrict entry
1794c0b746e5SOllivier Robert  */
1795c0b746e5SOllivier Robert static void
1796c0b746e5SOllivier Robert do_ressubflags(
17979c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1798c0b746e5SOllivier Robert 	struct interface *inter,
1799c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1800c0b746e5SOllivier Robert 	)
1801c0b746e5SOllivier Robert {
1802c0b746e5SOllivier Robert 	do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
1803c0b746e5SOllivier Robert }
1804c0b746e5SOllivier Robert 
1805c0b746e5SOllivier Robert 
1806c0b746e5SOllivier Robert /*
1807c0b746e5SOllivier Robert  * do_unrestrict - remove a restrict entry from the list
1808c0b746e5SOllivier Robert  */
1809c0b746e5SOllivier Robert static void
1810c0b746e5SOllivier Robert do_unrestrict(
18119c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1812c0b746e5SOllivier Robert 	struct interface *inter,
1813c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1814c0b746e5SOllivier Robert 	)
1815c0b746e5SOllivier Robert {
1816c0b746e5SOllivier Robert 	do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
1817c0b746e5SOllivier Robert }
1818c0b746e5SOllivier Robert 
1819c0b746e5SOllivier Robert 
1820c0b746e5SOllivier Robert 
1821c0b746e5SOllivier Robert 
1822c0b746e5SOllivier Robert 
1823c0b746e5SOllivier Robert /*
1824c0b746e5SOllivier Robert  * do_restrict - do the dirty stuff of dealing with restrictions
1825c0b746e5SOllivier Robert  */
1826c0b746e5SOllivier Robert static void
1827c0b746e5SOllivier Robert do_restrict(
18289c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1829c0b746e5SOllivier Robert 	struct interface *inter,
1830c0b746e5SOllivier Robert 	struct req_pkt *inpkt,
1831c0b746e5SOllivier Robert 	int op
1832c0b746e5SOllivier Robert 	)
1833c0b746e5SOllivier Robert {
1834c0b746e5SOllivier Robert 	register struct conf_restrict *cr;
1835c0b746e5SOllivier Robert 	register int items;
18369c2daa00SOllivier Robert 	struct sockaddr_storage matchaddr;
18379c2daa00SOllivier Robert 	struct sockaddr_storage matchmask;
1838c0b746e5SOllivier Robert 	int bad;
1839c0b746e5SOllivier Robert 
1840c0b746e5SOllivier Robert 	/*
1841c0b746e5SOllivier Robert 	 * Do a check of the flags to make sure that only
1842c0b746e5SOllivier Robert 	 * the NTPPORT flag is set, if any.  If not, complain
1843c0b746e5SOllivier Robert 	 * about it.  Note we are very picky here.
1844c0b746e5SOllivier Robert 	 */
1845c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1846c0b746e5SOllivier Robert 	cr = (struct conf_restrict *)inpkt->data;
1847c0b746e5SOllivier Robert 
1848c0b746e5SOllivier Robert 	bad = 0;
1849ea906c41SOllivier Robert 	cr->flags = ntohs(cr->flags);
1850ea906c41SOllivier Robert 	cr->mflags = ntohs(cr->mflags);
1851c0b746e5SOllivier Robert 	while (items-- > 0 && !bad) {
1852c0b746e5SOllivier Robert 		if (cr->mflags & ~(RESM_NTPONLY))
1853224ba2bdSOllivier Robert 		    bad |= 1;
1854c0b746e5SOllivier Robert 		if (cr->flags & ~(RES_ALLFLAGS))
1855224ba2bdSOllivier Robert 		    bad |= 2;
18569c2daa00SOllivier Robert 		if (cr->mask != htonl(INADDR_ANY)) {
18579c2daa00SOllivier Robert 			if (client_v6_capable && cr->v6_flag != 0) {
18589c2daa00SOllivier Robert 				if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6))
1859224ba2bdSOllivier Robert 					bad |= 4;
18609c2daa00SOllivier Robert 			} else
18619c2daa00SOllivier Robert 				if (cr->addr == htonl(INADDR_ANY))
18629c2daa00SOllivier Robert 					bad |= 8;
18639c2daa00SOllivier Robert 		}
18649c2daa00SOllivier Robert 		cr = (struct conf_restrict *)((char *)cr +
18659c2daa00SOllivier Robert 		    INFO_ITEMSIZE(inpkt->mbz_itemsize));
1866c0b746e5SOllivier Robert 	}
1867c0b746e5SOllivier Robert 
1868c0b746e5SOllivier Robert 	if (bad) {
1869224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
1870c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1871c0b746e5SOllivier Robert 		return;
1872c0b746e5SOllivier Robert 	}
1873c0b746e5SOllivier Robert 
1874c0b746e5SOllivier Robert 	/*
1875c0b746e5SOllivier Robert 	 * Looks okay, try it out
1876c0b746e5SOllivier Robert 	 */
1877c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
1878c0b746e5SOllivier Robert 	cr = (struct conf_restrict *)inpkt->data;
18799c2daa00SOllivier Robert 	memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage));
18809c2daa00SOllivier Robert 	memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage));
1881c0b746e5SOllivier Robert 
1882c0b746e5SOllivier Robert 	while (items-- > 0) {
18839c2daa00SOllivier Robert 		if (client_v6_capable && cr->v6_flag != 0) {
18849c2daa00SOllivier Robert 			GET_INADDR6(matchaddr) = cr->addr6;
18859c2daa00SOllivier Robert 			GET_INADDR6(matchmask) = cr->mask6;
18869c2daa00SOllivier Robert 			matchaddr.ss_family = AF_INET6;
18879c2daa00SOllivier Robert 			matchmask.ss_family = AF_INET6;
18889c2daa00SOllivier Robert 		} else {
18899c2daa00SOllivier Robert 			GET_INADDR(matchaddr) = cr->addr;
18909c2daa00SOllivier Robert 			GET_INADDR(matchmask) = cr->mask;
18919c2daa00SOllivier Robert 			matchaddr.ss_family = AF_INET;
18929c2daa00SOllivier Robert 			matchmask.ss_family = AF_INET;
18939c2daa00SOllivier Robert 		}
1894c0b746e5SOllivier Robert 		hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
1895c0b746e5SOllivier Robert 			 cr->flags);
1896c0b746e5SOllivier Robert 		cr++;
1897c0b746e5SOllivier Robert 	}
1898c0b746e5SOllivier Robert 
1899c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1900c0b746e5SOllivier Robert }
1901c0b746e5SOllivier Robert 
1902c0b746e5SOllivier Robert 
1903c0b746e5SOllivier Robert /*
1904c0b746e5SOllivier Robert  * mon_getlist - return monitor data
1905c0b746e5SOllivier Robert  */
1906c0b746e5SOllivier Robert static void
1907c0b746e5SOllivier Robert mon_getlist_0(
19089c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1909c0b746e5SOllivier Robert 	struct interface *inter,
1910c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1911c0b746e5SOllivier Robert 	)
1912c0b746e5SOllivier Robert {
1913c0b746e5SOllivier Robert 	register struct info_monitor *im;
1914c0b746e5SOllivier Robert 	register struct mon_data *md;
1915c0b746e5SOllivier Robert 	extern struct mon_data mon_mru_list;
1916c0b746e5SOllivier Robert 	extern int mon_enabled;
1917c0b746e5SOllivier Robert 
1918c0b746e5SOllivier Robert #ifdef DEBUG
1919c0b746e5SOllivier Robert 	if (debug > 2)
1920c0b746e5SOllivier Robert 	    printf("wants monitor 0 list\n");
1921c0b746e5SOllivier Robert #endif
1922c0b746e5SOllivier Robert 	if (!mon_enabled) {
1923c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1924c0b746e5SOllivier Robert 		return;
1925c0b746e5SOllivier Robert 	}
1926c0b746e5SOllivier Robert 	im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
19279c2daa00SOllivier Robert 	    v6sizeof(struct info_monitor));
1928c0b746e5SOllivier Robert 	for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1929c0b746e5SOllivier Robert 	     md = md->mru_next) {
19309c2daa00SOllivier Robert 		im->lasttime = htonl((u_int32)md->avg_interval);
19319c2daa00SOllivier Robert 		im->firsttime = htonl((u_int32)(current_time - md->lasttime));
19329c2daa00SOllivier Robert 		im->lastdrop = htonl((u_int32)md->drop_count);
1933c0b746e5SOllivier Robert 		im->count = htonl((u_int32)(md->count));
19349c2daa00SOllivier Robert 		if (md->rmtadr.ss_family == AF_INET6) {
19359c2daa00SOllivier Robert 			if (!client_v6_capable)
19369c2daa00SOllivier Robert 				continue;
19379c2daa00SOllivier Robert 			im->addr6 = GET_INADDR6(md->rmtadr);
19389c2daa00SOllivier Robert 			im->v6_flag = 1;
19399c2daa00SOllivier Robert 		} else {
19409c2daa00SOllivier Robert 			im->addr = GET_INADDR(md->rmtadr);
19419c2daa00SOllivier Robert 			if (client_v6_capable)
19429c2daa00SOllivier Robert 				im->v6_flag = 0;
19439c2daa00SOllivier Robert 		}
1944c0b746e5SOllivier Robert 		im->port = md->rmtport;
1945c0b746e5SOllivier Robert 		im->mode = md->mode;
1946c0b746e5SOllivier Robert 		im->version = md->version;
1947c0b746e5SOllivier Robert 		im = (struct info_monitor *)more_pkt();
1948c0b746e5SOllivier Robert 	}
1949c0b746e5SOllivier Robert 	flush_pkt();
1950c0b746e5SOllivier Robert }
1951c0b746e5SOllivier Robert 
1952c0b746e5SOllivier Robert /*
1953c0b746e5SOllivier Robert  * mon_getlist - return monitor data
1954c0b746e5SOllivier Robert  */
1955c0b746e5SOllivier Robert static void
1956c0b746e5SOllivier Robert mon_getlist_1(
19579c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
1958c0b746e5SOllivier Robert 	struct interface *inter,
1959c0b746e5SOllivier Robert 	struct req_pkt *inpkt
1960c0b746e5SOllivier Robert 	)
1961c0b746e5SOllivier Robert {
1962c0b746e5SOllivier Robert 	register struct info_monitor_1 *im;
1963c0b746e5SOllivier Robert 	register struct mon_data *md;
1964c0b746e5SOllivier Robert 	extern struct mon_data mon_mru_list;
1965c0b746e5SOllivier Robert 	extern int mon_enabled;
1966c0b746e5SOllivier Robert 
1967c0b746e5SOllivier Robert 	if (!mon_enabled) {
1968c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1969c0b746e5SOllivier Robert 		return;
1970c0b746e5SOllivier Robert 	}
1971c0b746e5SOllivier Robert 	im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
19729c2daa00SOllivier Robert 	    v6sizeof(struct info_monitor_1));
1973c0b746e5SOllivier Robert 	for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1974c0b746e5SOllivier Robert 	     md = md->mru_next) {
19759c2daa00SOllivier Robert 		im->lasttime = htonl((u_int32)md->avg_interval);
19769c2daa00SOllivier Robert 		im->firsttime = htonl((u_int32)(current_time - md->lasttime));
19779c2daa00SOllivier Robert 		im->lastdrop = htonl((u_int32)md->drop_count);
1978c0b746e5SOllivier Robert 		im->count = htonl((u_int32)md->count);
19799c2daa00SOllivier Robert 		if (md->rmtadr.ss_family == AF_INET6) {
19809c2daa00SOllivier Robert 			if (!client_v6_capable)
19819c2daa00SOllivier Robert 				continue;
19829c2daa00SOllivier Robert 			im->addr6 = GET_INADDR6(md->rmtadr);
19839c2daa00SOllivier Robert 			im->v6_flag = 1;
19849c2daa00SOllivier Robert 			im->daddr6 = GET_INADDR6(md->interface->sin);
19859c2daa00SOllivier Robert 		} else {
19869c2daa00SOllivier Robert 			im->addr = GET_INADDR(md->rmtadr);
19879c2daa00SOllivier Robert 			if (client_v6_capable)
19889c2daa00SOllivier Robert 				im->v6_flag = 0;
19899c2daa00SOllivier Robert 			im->daddr = (md->cast_flags == MDF_BCAST)
19909c2daa00SOllivier Robert 				? GET_INADDR(md->interface->bcast)
1991c0b746e5SOllivier Robert 				: (md->cast_flags
19929c2daa00SOllivier Robert 				? (GET_INADDR(md->interface->sin)
19939c2daa00SOllivier Robert 				? GET_INADDR(md->interface->sin)
19949c2daa00SOllivier Robert 				: GET_INADDR(md->interface->bcast))
1995c0b746e5SOllivier Robert 				: 4);
19969c2daa00SOllivier Robert 		}
1997ea906c41SOllivier Robert 		im->flags = htonl(md->cast_flags);
1998c0b746e5SOllivier Robert 		im->port = md->rmtport;
1999c0b746e5SOllivier Robert 		im->mode = md->mode;
2000c0b746e5SOllivier Robert 		im->version = md->version;
2001c0b746e5SOllivier Robert 		im = (struct info_monitor_1 *)more_pkt();
2002c0b746e5SOllivier Robert 	}
2003c0b746e5SOllivier Robert 	flush_pkt();
2004c0b746e5SOllivier Robert }
2005c0b746e5SOllivier Robert 
2006c0b746e5SOllivier Robert /*
2007c0b746e5SOllivier Robert  * Module entry points and the flags they correspond with
2008c0b746e5SOllivier Robert  */
2009c0b746e5SOllivier Robert struct reset_entry {
2010c0b746e5SOllivier Robert 	int flag;		/* flag this corresponds to */
2011c0b746e5SOllivier Robert 	void (*handler) P((void)); /* routine to handle request */
2012c0b746e5SOllivier Robert };
2013c0b746e5SOllivier Robert 
2014c0b746e5SOllivier Robert struct reset_entry reset_entries[] = {
2015c0b746e5SOllivier Robert 	{ RESET_FLAG_ALLPEERS,	peer_all_reset },
2016c0b746e5SOllivier Robert 	{ RESET_FLAG_IO,	io_clr_stats },
2017c0b746e5SOllivier Robert 	{ RESET_FLAG_SYS,	proto_clr_stats },
2018c0b746e5SOllivier Robert 	{ RESET_FLAG_MEM,	peer_clr_stats },
2019c0b746e5SOllivier Robert 	{ RESET_FLAG_TIMER,	timer_clr_stats },
2020c0b746e5SOllivier Robert 	{ RESET_FLAG_AUTH,	reset_auth_stats },
2021c0b746e5SOllivier Robert 	{ RESET_FLAG_CTL,	ctl_clr_stats },
2022c0b746e5SOllivier Robert 	{ 0,			0 }
2023c0b746e5SOllivier Robert };
2024c0b746e5SOllivier Robert 
2025c0b746e5SOllivier Robert /*
2026c0b746e5SOllivier Robert  * reset_stats - reset statistic counters here and there
2027c0b746e5SOllivier Robert  */
2028c0b746e5SOllivier Robert static void
2029c0b746e5SOllivier Robert reset_stats(
20309c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2031c0b746e5SOllivier Robert 	struct interface *inter,
2032c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2033c0b746e5SOllivier Robert 	)
2034c0b746e5SOllivier Robert {
2035c0b746e5SOllivier Robert 	u_long flags;
2036c0b746e5SOllivier Robert 	struct reset_entry *rent;
2037c0b746e5SOllivier Robert 
2038c0b746e5SOllivier Robert 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2039224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
2040c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2041c0b746e5SOllivier Robert 		return;
2042c0b746e5SOllivier Robert 	}
2043c0b746e5SOllivier Robert 
2044c0b746e5SOllivier Robert 	flags = ((struct reset_flags *)inpkt->data)->flags;
2045ea906c41SOllivier Robert 	flags = ntohl(flags);
2046c0b746e5SOllivier Robert 
2047c0b746e5SOllivier Robert 	if (flags & ~RESET_ALLFLAGS) {
2048224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
2049224ba2bdSOllivier Robert 			flags & ~RESET_ALLFLAGS);
2050c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2051c0b746e5SOllivier Robert 		return;
2052c0b746e5SOllivier Robert 	}
2053c0b746e5SOllivier Robert 
2054c0b746e5SOllivier Robert 	for (rent = reset_entries; rent->flag != 0; rent++) {
2055c0b746e5SOllivier Robert 		if (flags & rent->flag)
2056c0b746e5SOllivier Robert 		    (rent->handler)();
2057c0b746e5SOllivier Robert 	}
2058c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2059c0b746e5SOllivier Robert }
2060c0b746e5SOllivier Robert 
2061c0b746e5SOllivier Robert 
2062c0b746e5SOllivier Robert /*
2063c0b746e5SOllivier Robert  * reset_peer - clear a peer's statistics
2064c0b746e5SOllivier Robert  */
2065c0b746e5SOllivier Robert static void
2066c0b746e5SOllivier Robert reset_peer(
20679c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2068c0b746e5SOllivier Robert 	struct interface *inter,
2069c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2070c0b746e5SOllivier Robert 	)
2071c0b746e5SOllivier Robert {
2072c0b746e5SOllivier Robert 	register struct conf_unpeer *cp;
2073c0b746e5SOllivier Robert 	register int items;
2074c0b746e5SOllivier Robert 	register struct peer *peer;
20759c2daa00SOllivier Robert 	struct sockaddr_storage peeraddr;
2076c0b746e5SOllivier Robert 	int bad;
2077c0b746e5SOllivier Robert 
2078c0b746e5SOllivier Robert 	/*
2079c0b746e5SOllivier Robert 	 * We check first to see that every peer exists.  If not,
2080c0b746e5SOllivier Robert 	 * we return an error.
2081c0b746e5SOllivier Robert 	 */
2082c0b746e5SOllivier Robert 
2083c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2084c0b746e5SOllivier Robert 	cp = (struct conf_unpeer *)inpkt->data;
2085c0b746e5SOllivier Robert 
2086c0b746e5SOllivier Robert 	bad = 0;
2087c0b746e5SOllivier Robert 	while (items-- > 0 && !bad) {
20889c2daa00SOllivier Robert 		memset((char *)&peeraddr, 0, sizeof(peeraddr));
20899c2daa00SOllivier Robert 		if (client_v6_capable && cp->v6_flag != 0) {
20909c2daa00SOllivier Robert 			GET_INADDR6(peeraddr) = cp->peeraddr6;
20919c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET6;
20929c2daa00SOllivier Robert 		} else {
20939c2daa00SOllivier Robert 			GET_INADDR(peeraddr) = cp->peeraddr;
20949c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET;
20959c2daa00SOllivier Robert 		}
20969c2daa00SOllivier Robert 		NSRCPORT(&peeraddr) = htons(NTP_PORT);
20979c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
20989c2daa00SOllivier Robert 		peeraddr.ss_len = SOCKLEN(&peeraddr);
20999c2daa00SOllivier Robert #endif
2100c0b746e5SOllivier Robert 		peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
2101c0b746e5SOllivier Robert 		if (peer == (struct peer *)0)
2102c0b746e5SOllivier Robert 		    bad++;
21039c2daa00SOllivier Robert 		cp = (struct conf_unpeer *)((char *)cp +
21049c2daa00SOllivier Robert 		    INFO_ITEMSIZE(inpkt->mbz_itemsize));
2105c0b746e5SOllivier Robert 	}
2106c0b746e5SOllivier Robert 
2107c0b746e5SOllivier Robert 	if (bad) {
2108c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2109c0b746e5SOllivier Robert 		return;
2110c0b746e5SOllivier Robert 	}
2111c0b746e5SOllivier Robert 
2112c0b746e5SOllivier Robert 	/*
2113c0b746e5SOllivier Robert 	 * Now do it in earnest.
2114c0b746e5SOllivier Robert 	 */
2115c0b746e5SOllivier Robert 
2116c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2117c0b746e5SOllivier Robert 	cp = (struct conf_unpeer *)inpkt->data;
2118c0b746e5SOllivier Robert 	while (items-- > 0) {
21199c2daa00SOllivier Robert 		memset((char *)&peeraddr, 0, sizeof(peeraddr));
21209c2daa00SOllivier Robert 		if (client_v6_capable && cp->v6_flag != 0) {
21219c2daa00SOllivier Robert 			GET_INADDR6(peeraddr) = cp->peeraddr6;
21229c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET6;
21239c2daa00SOllivier Robert 		} else {
21249c2daa00SOllivier Robert 			GET_INADDR(peeraddr) = cp->peeraddr;
21259c2daa00SOllivier Robert 			peeraddr.ss_family = AF_INET;
21269c2daa00SOllivier Robert 		}
21279c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
21289c2daa00SOllivier Robert 		peeraddr.ss_len = SOCKLEN(&peeraddr);
21299c2daa00SOllivier Robert #endif
2130c0b746e5SOllivier Robert 		peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
2131c0b746e5SOllivier Robert 		while (peer != 0) {
2132c0b746e5SOllivier Robert 			peer_reset(peer);
2133c0b746e5SOllivier Robert 			peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1);
2134c0b746e5SOllivier Robert 		}
21359c2daa00SOllivier Robert 		cp = (struct conf_unpeer *)((char *)cp +
21369c2daa00SOllivier Robert 		    INFO_ITEMSIZE(inpkt->mbz_itemsize));
2137c0b746e5SOllivier Robert 	}
2138c0b746e5SOllivier Robert 
2139c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2140c0b746e5SOllivier Robert }
2141c0b746e5SOllivier Robert 
2142c0b746e5SOllivier Robert 
2143c0b746e5SOllivier Robert /*
2144c0b746e5SOllivier Robert  * do_key_reread - reread the encryption key file
2145c0b746e5SOllivier Robert  */
2146c0b746e5SOllivier Robert static void
2147c0b746e5SOllivier Robert do_key_reread(
21489c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2149c0b746e5SOllivier Robert 	struct interface *inter,
2150c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2151c0b746e5SOllivier Robert 	)
2152c0b746e5SOllivier Robert {
2153c0b746e5SOllivier Robert 	rereadkeys();
2154c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2155c0b746e5SOllivier Robert }
2156c0b746e5SOllivier Robert 
2157c0b746e5SOllivier Robert 
2158c0b746e5SOllivier Robert /*
2159c0b746e5SOllivier Robert  * trust_key - make one or more keys trusted
2160c0b746e5SOllivier Robert  */
2161c0b746e5SOllivier Robert static void
2162c0b746e5SOllivier Robert trust_key(
21639c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2164c0b746e5SOllivier Robert 	struct interface *inter,
2165c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2166c0b746e5SOllivier Robert 	)
2167c0b746e5SOllivier Robert {
2168c0b746e5SOllivier Robert 	do_trustkey(srcadr, inter, inpkt, 1);
2169c0b746e5SOllivier Robert }
2170c0b746e5SOllivier Robert 
2171c0b746e5SOllivier Robert 
2172c0b746e5SOllivier Robert /*
2173c0b746e5SOllivier Robert  * untrust_key - make one or more keys untrusted
2174c0b746e5SOllivier Robert  */
2175c0b746e5SOllivier Robert static void
2176c0b746e5SOllivier Robert untrust_key(
21779c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2178c0b746e5SOllivier Robert 	struct interface *inter,
2179c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2180c0b746e5SOllivier Robert 	)
2181c0b746e5SOllivier Robert {
2182c0b746e5SOllivier Robert 	do_trustkey(srcadr, inter, inpkt, 0);
2183c0b746e5SOllivier Robert }
2184c0b746e5SOllivier Robert 
2185c0b746e5SOllivier Robert 
2186c0b746e5SOllivier Robert /*
2187c0b746e5SOllivier Robert  * do_trustkey - make keys either trustable or untrustable
2188c0b746e5SOllivier Robert  */
2189c0b746e5SOllivier Robert static void
2190c0b746e5SOllivier Robert do_trustkey(
21919c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2192c0b746e5SOllivier Robert 	struct interface *inter,
2193c0b746e5SOllivier Robert 	struct req_pkt *inpkt,
2194224ba2bdSOllivier Robert 	u_long trust
2195c0b746e5SOllivier Robert 	)
2196c0b746e5SOllivier Robert {
2197c0b746e5SOllivier Robert 	register u_long *kp;
2198c0b746e5SOllivier Robert 	register int items;
2199c0b746e5SOllivier Robert 
2200c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2201c0b746e5SOllivier Robert 	kp = (u_long *)inpkt->data;
2202c0b746e5SOllivier Robert 	while (items-- > 0) {
2203c0b746e5SOllivier Robert 		authtrust(*kp, trust);
2204c0b746e5SOllivier Robert 		kp++;
2205c0b746e5SOllivier Robert 	}
2206c0b746e5SOllivier Robert 
2207c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2208c0b746e5SOllivier Robert }
2209c0b746e5SOllivier Robert 
2210c0b746e5SOllivier Robert 
2211c0b746e5SOllivier Robert /*
2212c0b746e5SOllivier Robert  * get_auth_info - return some stats concerning the authentication module
2213c0b746e5SOllivier Robert  */
2214c0b746e5SOllivier Robert static void
2215c0b746e5SOllivier Robert get_auth_info(
22169c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2217c0b746e5SOllivier Robert 	struct interface *inter,
2218c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2219c0b746e5SOllivier Robert 	)
2220c0b746e5SOllivier Robert {
2221c0b746e5SOllivier Robert 	register struct info_auth *ia;
2222c0b746e5SOllivier Robert 
2223c0b746e5SOllivier Robert 	/*
2224c0b746e5SOllivier Robert 	 * Importations from the authentication module
2225c0b746e5SOllivier Robert 	 */
2226c0b746e5SOllivier Robert 	extern u_long authnumkeys;
2227c0b746e5SOllivier Robert 	extern int authnumfreekeys;
2228c0b746e5SOllivier Robert 	extern u_long authkeylookups;
2229c0b746e5SOllivier Robert 	extern u_long authkeynotfound;
2230c0b746e5SOllivier Robert 	extern u_long authencryptions;
2231c0b746e5SOllivier Robert 	extern u_long authdecryptions;
2232c0b746e5SOllivier Robert 	extern u_long authkeyuncached;
2233c0b746e5SOllivier Robert 	extern u_long authkeyexpired;
2234c0b746e5SOllivier Robert 
2235c0b746e5SOllivier Robert 	ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
2236c0b746e5SOllivier Robert 					     sizeof(struct info_auth));
2237c0b746e5SOllivier Robert 
2238c0b746e5SOllivier Robert 	ia->numkeys = htonl((u_int32)authnumkeys);
2239c0b746e5SOllivier Robert 	ia->numfreekeys = htonl((u_int32)authnumfreekeys);
2240c0b746e5SOllivier Robert 	ia->keylookups = htonl((u_int32)authkeylookups);
2241c0b746e5SOllivier Robert 	ia->keynotfound = htonl((u_int32)authkeynotfound);
2242c0b746e5SOllivier Robert 	ia->encryptions = htonl((u_int32)authencryptions);
2243c0b746e5SOllivier Robert 	ia->decryptions = htonl((u_int32)authdecryptions);
2244c0b746e5SOllivier Robert 	ia->keyuncached = htonl((u_int32)authkeyuncached);
2245c0b746e5SOllivier Robert 	ia->expired = htonl((u_int32)authkeyexpired);
2246c0b746e5SOllivier Robert 	ia->timereset = htonl((u_int32)(current_time - auth_timereset));
2247c0b746e5SOllivier Robert 
2248c0b746e5SOllivier Robert 	(void) more_pkt();
2249c0b746e5SOllivier Robert 	flush_pkt();
2250c0b746e5SOllivier Robert }
2251c0b746e5SOllivier Robert 
2252c0b746e5SOllivier Robert 
2253c0b746e5SOllivier Robert 
2254c0b746e5SOllivier Robert /*
2255c0b746e5SOllivier Robert  * reset_auth_stats - reset the authentication stat counters.  Done here
2256c0b746e5SOllivier Robert  *		      to keep ntp-isms out of the authentication module
2257c0b746e5SOllivier Robert  */
2258c0b746e5SOllivier Robert static void
2259c0b746e5SOllivier Robert reset_auth_stats(void)
2260c0b746e5SOllivier Robert {
2261c0b746e5SOllivier Robert 	/*
2262c0b746e5SOllivier Robert 	 * Importations from the authentication module
2263c0b746e5SOllivier Robert 	 */
2264c0b746e5SOllivier Robert 	extern u_long authkeylookups;
2265c0b746e5SOllivier Robert 	extern u_long authkeynotfound;
2266c0b746e5SOllivier Robert 	extern u_long authencryptions;
2267c0b746e5SOllivier Robert 	extern u_long authdecryptions;
2268c0b746e5SOllivier Robert 	extern u_long authkeyuncached;
2269c0b746e5SOllivier Robert 
2270c0b746e5SOllivier Robert 	authkeylookups = 0;
2271c0b746e5SOllivier Robert 	authkeynotfound = 0;
2272c0b746e5SOllivier Robert 	authencryptions = 0;
2273c0b746e5SOllivier Robert 	authdecryptions = 0;
2274c0b746e5SOllivier Robert 	authkeyuncached = 0;
2275c0b746e5SOllivier Robert 	auth_timereset = current_time;
2276c0b746e5SOllivier Robert }
2277c0b746e5SOllivier Robert 
2278c0b746e5SOllivier Robert 
2279c0b746e5SOllivier Robert /*
2280c0b746e5SOllivier Robert  * req_get_traps - return information about current trap holders
2281c0b746e5SOllivier Robert  */
2282c0b746e5SOllivier Robert static void
2283c0b746e5SOllivier Robert req_get_traps(
22849c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2285c0b746e5SOllivier Robert 	struct interface *inter,
2286c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2287c0b746e5SOllivier Robert 	)
2288c0b746e5SOllivier Robert {
2289c0b746e5SOllivier Robert 	register struct info_trap *it;
2290c0b746e5SOllivier Robert 	register struct ctl_trap *tr;
2291c0b746e5SOllivier Robert 	register int i;
2292c0b746e5SOllivier Robert 
2293c0b746e5SOllivier Robert 	/*
2294c0b746e5SOllivier Robert 	 * Imported from the control module
2295c0b746e5SOllivier Robert 	 */
2296c0b746e5SOllivier Robert 	extern struct ctl_trap ctl_trap[];
2297c0b746e5SOllivier Robert 	extern int num_ctl_traps;
2298c0b746e5SOllivier Robert 
2299c0b746e5SOllivier Robert 	if (num_ctl_traps == 0) {
2300c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2301c0b746e5SOllivier Robert 		return;
2302c0b746e5SOllivier Robert 	}
2303c0b746e5SOllivier Robert 
2304c0b746e5SOllivier Robert 	it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
23059c2daa00SOllivier Robert 	    v6sizeof(struct info_trap));
2306c0b746e5SOllivier Robert 
2307c0b746e5SOllivier Robert 	for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
2308c0b746e5SOllivier Robert 		if (tr->tr_flags & TRAP_INUSE) {
23099c2daa00SOllivier Robert 			if (tr->tr_addr.ss_family == AF_INET) {
2310c0b746e5SOllivier Robert 				if (tr->tr_localaddr == any_interface)
2311c0b746e5SOllivier Robert 					it->local_address = 0;
2312c0b746e5SOllivier Robert 				else
2313c0b746e5SOllivier Robert 					it->local_address
23149c2daa00SOllivier Robert 					    = GET_INADDR(tr->tr_localaddr->sin);
23159c2daa00SOllivier Robert 				it->trap_address = GET_INADDR(tr->tr_addr);
23169c2daa00SOllivier Robert 				if (client_v6_capable)
23179c2daa00SOllivier Robert 					it->v6_flag = 0;
23189c2daa00SOllivier Robert 			} else {
23199c2daa00SOllivier Robert 				if (!client_v6_capable)
23209c2daa00SOllivier Robert 					continue;
23219c2daa00SOllivier Robert 				it->local_address6
23229c2daa00SOllivier Robert 				    = GET_INADDR6(tr->tr_localaddr->sin);
23239c2daa00SOllivier Robert 				it->trap_address6 = GET_INADDR6(tr->tr_addr);
23249c2daa00SOllivier Robert 				it->v6_flag = 1;
23259c2daa00SOllivier Robert 			}
2326c0b746e5SOllivier Robert 			it->trap_port = NSRCPORT(&tr->tr_addr);
2327c0b746e5SOllivier Robert 			it->sequence = htons(tr->tr_sequence);
2328c0b746e5SOllivier Robert 			it->settime = htonl((u_int32)(current_time - tr->tr_settime));
2329c0b746e5SOllivier Robert 			it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
2330c0b746e5SOllivier Robert 			it->resets = htonl((u_int32)tr->tr_resets);
2331c0b746e5SOllivier Robert 			it->flags = htonl((u_int32)tr->tr_flags);
2332c0b746e5SOllivier Robert 			it = (struct info_trap *)more_pkt();
2333c0b746e5SOllivier Robert 		}
2334c0b746e5SOllivier Robert 	}
2335c0b746e5SOllivier Robert 	flush_pkt();
2336c0b746e5SOllivier Robert }
2337c0b746e5SOllivier Robert 
2338c0b746e5SOllivier Robert 
2339c0b746e5SOllivier Robert /*
2340c0b746e5SOllivier Robert  * req_set_trap - configure a trap
2341c0b746e5SOllivier Robert  */
2342c0b746e5SOllivier Robert static void
2343c0b746e5SOllivier Robert req_set_trap(
23449c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2345c0b746e5SOllivier Robert 	struct interface *inter,
2346c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2347c0b746e5SOllivier Robert 	)
2348c0b746e5SOllivier Robert {
2349c0b746e5SOllivier Robert 	do_setclr_trap(srcadr, inter, inpkt, 1);
2350c0b746e5SOllivier Robert }
2351c0b746e5SOllivier Robert 
2352c0b746e5SOllivier Robert 
2353c0b746e5SOllivier Robert 
2354c0b746e5SOllivier Robert /*
2355c0b746e5SOllivier Robert  * req_clr_trap - unconfigure a trap
2356c0b746e5SOllivier Robert  */
2357c0b746e5SOllivier Robert static void
2358c0b746e5SOllivier Robert req_clr_trap(
23599c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2360c0b746e5SOllivier Robert 	struct interface *inter,
2361c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2362c0b746e5SOllivier Robert 	)
2363c0b746e5SOllivier Robert {
2364c0b746e5SOllivier Robert 	do_setclr_trap(srcadr, inter, inpkt, 0);
2365c0b746e5SOllivier Robert }
2366c0b746e5SOllivier Robert 
2367c0b746e5SOllivier Robert 
2368c0b746e5SOllivier Robert 
2369c0b746e5SOllivier Robert /*
2370c0b746e5SOllivier Robert  * do_setclr_trap - do the grunge work of (un)configuring a trap
2371c0b746e5SOllivier Robert  */
2372c0b746e5SOllivier Robert static void
2373c0b746e5SOllivier Robert do_setclr_trap(
23749c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2375c0b746e5SOllivier Robert 	struct interface *inter,
2376c0b746e5SOllivier Robert 	struct req_pkt *inpkt,
2377c0b746e5SOllivier Robert 	int set
2378c0b746e5SOllivier Robert 	)
2379c0b746e5SOllivier Robert {
2380c0b746e5SOllivier Robert 	register struct conf_trap *ct;
2381c0b746e5SOllivier Robert 	register struct interface *linter;
2382c0b746e5SOllivier Robert 	int res;
23839c2daa00SOllivier Robert 	struct sockaddr_storage laddr;
2384c0b746e5SOllivier Robert 
2385c0b746e5SOllivier Robert 	/*
23869c2daa00SOllivier Robert 	 * Prepare sockaddr_storage structure
2387c0b746e5SOllivier Robert 	 */
2388c0b746e5SOllivier Robert 	memset((char *)&laddr, 0, sizeof laddr);
23899c2daa00SOllivier Robert 	laddr.ss_family = srcadr->ss_family;
23909c2daa00SOllivier Robert 	NSRCPORT(&laddr) = ntohs(NTP_PORT);
2391c0b746e5SOllivier Robert 
2392c0b746e5SOllivier Robert 	/*
2393c0b746e5SOllivier Robert 	 * Restrict ourselves to one item only.  This eliminates
2394c0b746e5SOllivier Robert 	 * the error reporting problem.
2395c0b746e5SOllivier Robert 	 */
2396c0b746e5SOllivier Robert 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2397224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
2398c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2399c0b746e5SOllivier Robert 		return;
2400c0b746e5SOllivier Robert 	}
2401c0b746e5SOllivier Robert 	ct = (struct conf_trap *)inpkt->data;
2402c0b746e5SOllivier Robert 
2403c0b746e5SOllivier Robert 	/*
2404c0b746e5SOllivier Robert 	 * Look for the local interface.  If none, use the default.
2405c0b746e5SOllivier Robert 	 */
2406c0b746e5SOllivier Robert 	if (ct->local_address == 0) {
2407c0b746e5SOllivier Robert 		linter = any_interface;
2408c0b746e5SOllivier Robert 	} else {
24099c2daa00SOllivier Robert 		if (laddr.ss_family == AF_INET)
24109c2daa00SOllivier Robert 			GET_INADDR(laddr) = ct->local_address;
24119c2daa00SOllivier Robert 		else
24129c2daa00SOllivier Robert 			GET_INADDR6(laddr) = ct->local_address6;
2413c0b746e5SOllivier Robert 		linter = findinterface(&laddr);
2414c0b746e5SOllivier Robert 		if (linter == NULL) {
2415c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2416c0b746e5SOllivier Robert 			return;
2417c0b746e5SOllivier Robert 		}
2418c0b746e5SOllivier Robert 	}
2419c0b746e5SOllivier Robert 
24209c2daa00SOllivier Robert 	if (laddr.ss_family == AF_INET)
24219c2daa00SOllivier Robert 		GET_INADDR(laddr) = ct->trap_address;
2422c0b746e5SOllivier Robert 	else
24239c2daa00SOllivier Robert 		GET_INADDR6(laddr) = ct->trap_address6;
24249c2daa00SOllivier Robert 	if (ct->trap_port != 0)
24259c2daa00SOllivier Robert 	    NSRCPORT(&laddr) = ct->trap_port;
24269c2daa00SOllivier Robert 	else
24279c2daa00SOllivier Robert 	    NSRCPORT(&laddr) = htons(TRAPPORT);
2428c0b746e5SOllivier Robert 
2429c0b746e5SOllivier Robert 	if (set) {
2430c0b746e5SOllivier Robert 		res = ctlsettrap(&laddr, linter, 0,
2431c0b746e5SOllivier Robert 				 INFO_VERSION(inpkt->rm_vn_mode));
2432c0b746e5SOllivier Robert 	} else {
2433c0b746e5SOllivier Robert 		res = ctlclrtrap(&laddr, linter, 0);
2434c0b746e5SOllivier Robert 	}
2435c0b746e5SOllivier Robert 
2436c0b746e5SOllivier Robert 	if (!res) {
2437c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2438c0b746e5SOllivier Robert 	} else {
2439c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_OKAY);
2440c0b746e5SOllivier Robert 	}
2441c0b746e5SOllivier Robert 	return;
2442c0b746e5SOllivier Robert }
2443c0b746e5SOllivier Robert 
2444c0b746e5SOllivier Robert 
2445c0b746e5SOllivier Robert 
2446c0b746e5SOllivier Robert /*
2447c0b746e5SOllivier Robert  * set_request_keyid - set the keyid used to authenticate requests
2448c0b746e5SOllivier Robert  */
2449c0b746e5SOllivier Robert static void
2450c0b746e5SOllivier Robert set_request_keyid(
24519c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2452c0b746e5SOllivier Robert 	struct interface *inter,
2453c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2454c0b746e5SOllivier Robert 	)
2455c0b746e5SOllivier Robert {
2456224ba2bdSOllivier Robert 	keyid_t keyid;
2457c0b746e5SOllivier Robert 
2458c0b746e5SOllivier Robert 	/*
2459c0b746e5SOllivier Robert 	 * Restrict ourselves to one item only.
2460c0b746e5SOllivier Robert 	 */
2461c0b746e5SOllivier Robert 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2462224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
2463c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2464c0b746e5SOllivier Robert 		return;
2465c0b746e5SOllivier Robert 	}
2466c0b746e5SOllivier Robert 
2467c0b746e5SOllivier Robert 	keyid = ntohl(*((u_int32 *)(inpkt->data)));
2468c0b746e5SOllivier Robert 	info_auth_keyid = keyid;
2469c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2470c0b746e5SOllivier Robert }
2471c0b746e5SOllivier Robert 
2472c0b746e5SOllivier Robert 
2473c0b746e5SOllivier Robert 
2474c0b746e5SOllivier Robert /*
2475c0b746e5SOllivier Robert  * set_control_keyid - set the keyid used to authenticate requests
2476c0b746e5SOllivier Robert  */
2477c0b746e5SOllivier Robert static void
2478c0b746e5SOllivier Robert set_control_keyid(
24799c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2480c0b746e5SOllivier Robert 	struct interface *inter,
2481c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2482c0b746e5SOllivier Robert 	)
2483c0b746e5SOllivier Robert {
2484224ba2bdSOllivier Robert 	keyid_t keyid;
2485224ba2bdSOllivier Robert 	extern keyid_t ctl_auth_keyid;
2486c0b746e5SOllivier Robert 
2487c0b746e5SOllivier Robert 	/*
2488c0b746e5SOllivier Robert 	 * Restrict ourselves to one item only.
2489c0b746e5SOllivier Robert 	 */
2490c0b746e5SOllivier Robert 	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2491224ba2bdSOllivier Robert 		msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
2492c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2493c0b746e5SOllivier Robert 		return;
2494c0b746e5SOllivier Robert 	}
2495c0b746e5SOllivier Robert 
2496c0b746e5SOllivier Robert 	keyid = ntohl(*((u_int32 *)(inpkt->data)));
2497c0b746e5SOllivier Robert 	ctl_auth_keyid = keyid;
2498c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2499c0b746e5SOllivier Robert }
2500c0b746e5SOllivier Robert 
2501c0b746e5SOllivier Robert 
2502c0b746e5SOllivier Robert 
2503c0b746e5SOllivier Robert /*
2504c0b746e5SOllivier Robert  * get_ctl_stats - return some stats concerning the control message module
2505c0b746e5SOllivier Robert  */
2506c0b746e5SOllivier Robert static void
2507c0b746e5SOllivier Robert get_ctl_stats(
25089c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2509c0b746e5SOllivier Robert 	struct interface *inter,
2510c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2511c0b746e5SOllivier Robert 	)
2512c0b746e5SOllivier Robert {
2513c0b746e5SOllivier Robert 	register struct info_control *ic;
2514c0b746e5SOllivier Robert 
2515c0b746e5SOllivier Robert 	/*
2516c0b746e5SOllivier Robert 	 * Importations from the control module
2517c0b746e5SOllivier Robert 	 */
2518c0b746e5SOllivier Robert 	extern u_long ctltimereset;
2519c0b746e5SOllivier Robert 	extern u_long numctlreq;
2520c0b746e5SOllivier Robert 	extern u_long numctlbadpkts;
2521c0b746e5SOllivier Robert 	extern u_long numctlresponses;
2522c0b746e5SOllivier Robert 	extern u_long numctlfrags;
2523c0b746e5SOllivier Robert 	extern u_long numctlerrors;
2524c0b746e5SOllivier Robert 	extern u_long numctltooshort;
2525c0b746e5SOllivier Robert 	extern u_long numctlinputresp;
2526c0b746e5SOllivier Robert 	extern u_long numctlinputfrag;
2527c0b746e5SOllivier Robert 	extern u_long numctlinputerr;
2528c0b746e5SOllivier Robert 	extern u_long numctlbadoffset;
2529c0b746e5SOllivier Robert 	extern u_long numctlbadversion;
2530c0b746e5SOllivier Robert 	extern u_long numctldatatooshort;
2531c0b746e5SOllivier Robert 	extern u_long numctlbadop;
2532c0b746e5SOllivier Robert 	extern u_long numasyncmsgs;
2533c0b746e5SOllivier Robert 
2534c0b746e5SOllivier Robert 	ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
2535c0b746e5SOllivier Robert 						sizeof(struct info_control));
2536c0b746e5SOllivier Robert 
2537c0b746e5SOllivier Robert 	ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
2538c0b746e5SOllivier Robert 	ic->numctlreq = htonl((u_int32)numctlreq);
2539c0b746e5SOllivier Robert 	ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
2540c0b746e5SOllivier Robert 	ic->numctlresponses = htonl((u_int32)numctlresponses);
2541c0b746e5SOllivier Robert 	ic->numctlfrags = htonl((u_int32)numctlfrags);
2542c0b746e5SOllivier Robert 	ic->numctlerrors = htonl((u_int32)numctlerrors);
2543c0b746e5SOllivier Robert 	ic->numctltooshort = htonl((u_int32)numctltooshort);
2544c0b746e5SOllivier Robert 	ic->numctlinputresp = htonl((u_int32)numctlinputresp);
2545c0b746e5SOllivier Robert 	ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
2546c0b746e5SOllivier Robert 	ic->numctlinputerr = htonl((u_int32)numctlinputerr);
2547c0b746e5SOllivier Robert 	ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
2548c0b746e5SOllivier Robert 	ic->numctlbadversion = htonl((u_int32)numctlbadversion);
2549c0b746e5SOllivier Robert 	ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
2550c0b746e5SOllivier Robert 	ic->numctlbadop = htonl((u_int32)numctlbadop);
2551c0b746e5SOllivier Robert 	ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
2552c0b746e5SOllivier Robert 
2553c0b746e5SOllivier Robert 	(void) more_pkt();
2554c0b746e5SOllivier Robert 	flush_pkt();
2555c0b746e5SOllivier Robert }
2556c0b746e5SOllivier Robert 
2557c0b746e5SOllivier Robert 
2558c0b746e5SOllivier Robert #ifdef KERNEL_PLL
2559c0b746e5SOllivier Robert /*
2560c0b746e5SOllivier Robert  * get_kernel_info - get kernel pll/pps information
2561c0b746e5SOllivier Robert  */
2562c0b746e5SOllivier Robert static void
2563c0b746e5SOllivier Robert get_kernel_info(
25649c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2565c0b746e5SOllivier Robert 	struct interface *inter,
2566c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2567c0b746e5SOllivier Robert 	)
2568c0b746e5SOllivier Robert {
2569c0b746e5SOllivier Robert 	register struct info_kernel *ik;
2570c0b746e5SOllivier Robert 	struct timex ntx;
2571c0b746e5SOllivier Robert 
2572c0b746e5SOllivier Robert 	if (!pll_control) {
2573c0b746e5SOllivier Robert 		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2574c0b746e5SOllivier Robert 		return;
2575c0b746e5SOllivier Robert 	}
2576c0b746e5SOllivier Robert 
2577c0b746e5SOllivier Robert 	memset((char *)&ntx, 0, sizeof(ntx));
2578c0b746e5SOllivier Robert 	if (ntp_adjtime(&ntx) < 0)
2579c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
2580c0b746e5SOllivier Robert 	ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
2581c0b746e5SOllivier Robert 	    sizeof(struct info_kernel));
2582c0b746e5SOllivier Robert 
2583c0b746e5SOllivier Robert 	/*
2584c0b746e5SOllivier Robert 	 * pll variables
2585c0b746e5SOllivier Robert 	 */
2586c0b746e5SOllivier Robert 	ik->offset = htonl((u_int32)ntx.offset);
2587c0b746e5SOllivier Robert 	ik->freq = htonl((u_int32)ntx.freq);
2588c0b746e5SOllivier Robert 	ik->maxerror = htonl((u_int32)ntx.maxerror);
2589c0b746e5SOllivier Robert 	ik->esterror = htonl((u_int32)ntx.esterror);
2590c0b746e5SOllivier Robert 	ik->status = htons(ntx.status);
2591c0b746e5SOllivier Robert 	ik->constant = htonl((u_int32)ntx.constant);
2592c0b746e5SOllivier Robert 	ik->precision = htonl((u_int32)ntx.precision);
2593c0b746e5SOllivier Robert 	ik->tolerance = htonl((u_int32)ntx.tolerance);
2594c0b746e5SOllivier Robert 
2595c0b746e5SOllivier Robert 	/*
2596c0b746e5SOllivier Robert 	 * pps variables
2597c0b746e5SOllivier Robert 	 */
2598c0b746e5SOllivier Robert 	ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
2599c0b746e5SOllivier Robert 	ik->jitter = htonl((u_int32)ntx.jitter);
2600c0b746e5SOllivier Robert 	ik->shift = htons(ntx.shift);
2601c0b746e5SOllivier Robert 	ik->stabil = htonl((u_int32)ntx.stabil);
2602c0b746e5SOllivier Robert 	ik->jitcnt = htonl((u_int32)ntx.jitcnt);
2603c0b746e5SOllivier Robert 	ik->calcnt = htonl((u_int32)ntx.calcnt);
2604c0b746e5SOllivier Robert 	ik->errcnt = htonl((u_int32)ntx.errcnt);
2605c0b746e5SOllivier Robert 	ik->stbcnt = htonl((u_int32)ntx.stbcnt);
2606c0b746e5SOllivier Robert 
2607c0b746e5SOllivier Robert 	(void) more_pkt();
2608c0b746e5SOllivier Robert 	flush_pkt();
2609c0b746e5SOllivier Robert }
2610c0b746e5SOllivier Robert #endif /* KERNEL_PLL */
2611c0b746e5SOllivier Robert 
2612c0b746e5SOllivier Robert 
2613c0b746e5SOllivier Robert #ifdef REFCLOCK
2614c0b746e5SOllivier Robert /*
2615c0b746e5SOllivier Robert  * get_clock_info - get info about a clock
2616c0b746e5SOllivier Robert  */
2617c0b746e5SOllivier Robert static void
2618c0b746e5SOllivier Robert get_clock_info(
26199c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2620c0b746e5SOllivier Robert 	struct interface *inter,
2621c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2622c0b746e5SOllivier Robert 	)
2623c0b746e5SOllivier Robert {
2624c0b746e5SOllivier Robert 	register struct info_clock *ic;
2625c0b746e5SOllivier Robert 	register u_int32 *clkaddr;
2626c0b746e5SOllivier Robert 	register int items;
2627c0b746e5SOllivier Robert 	struct refclockstat clock_stat;
26289c2daa00SOllivier Robert 	struct sockaddr_storage addr;
26299c2daa00SOllivier Robert 	struct sockaddr_in tmp_clock;
2630c0b746e5SOllivier Robert 	l_fp ltmp;
2631c0b746e5SOllivier Robert 
2632c0b746e5SOllivier Robert 	memset((char *)&addr, 0, sizeof addr);
26339c2daa00SOllivier Robert 	addr.ss_family = AF_INET;
26349c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
26359c2daa00SOllivier Robert 	addr.ss_len = SOCKLEN(&addr);
26369c2daa00SOllivier Robert #endif
26379c2daa00SOllivier Robert 	NSRCPORT(&addr) = htons(NTP_PORT);
2638c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2639c0b746e5SOllivier Robert 	clkaddr = (u_int32 *) inpkt->data;
2640c0b746e5SOllivier Robert 
2641c0b746e5SOllivier Robert 	ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
2642c0b746e5SOllivier Robert 					      sizeof(struct info_clock));
2643c0b746e5SOllivier Robert 
2644c0b746e5SOllivier Robert 	while (items-- > 0) {
26459c2daa00SOllivier Robert 		tmp_clock.sin_addr.s_addr = *clkaddr++;
26469c2daa00SOllivier Robert 		CAST_V4(addr)->sin_addr = tmp_clock.sin_addr;
26479c2daa00SOllivier Robert 		if (!ISREFCLOCKADR(&tmp_clock) ||
2648c0b746e5SOllivier Robert 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2649c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2650c0b746e5SOllivier Robert 			return;
2651c0b746e5SOllivier Robert 		}
2652c0b746e5SOllivier Robert 
2653c0b746e5SOllivier Robert 		clock_stat.kv_list = (struct ctl_var *)0;
2654c0b746e5SOllivier Robert 
2655c0b746e5SOllivier Robert 		refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
2656c0b746e5SOllivier Robert 
26579c2daa00SOllivier Robert 		ic->clockadr = tmp_clock.sin_addr.s_addr;
2658c0b746e5SOllivier Robert 		ic->type = clock_stat.type;
2659c0b746e5SOllivier Robert 		ic->flags = clock_stat.flags;
2660c0b746e5SOllivier Robert 		ic->lastevent = clock_stat.lastevent;
2661c0b746e5SOllivier Robert 		ic->currentstatus = clock_stat.currentstatus;
2662c0b746e5SOllivier Robert 		ic->polls = htonl((u_int32)clock_stat.polls);
2663c0b746e5SOllivier Robert 		ic->noresponse = htonl((u_int32)clock_stat.noresponse);
2664c0b746e5SOllivier Robert 		ic->badformat = htonl((u_int32)clock_stat.badformat);
2665c0b746e5SOllivier Robert 		ic->baddata = htonl((u_int32)clock_stat.baddata);
2666c0b746e5SOllivier Robert 		ic->timestarted = htonl((u_int32)clock_stat.timereset);
2667c0b746e5SOllivier Robert 		DTOLFP(clock_stat.fudgetime1, &ltmp);
2668c0b746e5SOllivier Robert 		HTONL_FP(&ltmp, &ic->fudgetime1);
26699c2daa00SOllivier Robert 		DTOLFP(clock_stat.fudgetime2, &ltmp);
2670c0b746e5SOllivier Robert 		HTONL_FP(&ltmp, &ic->fudgetime2);
2671c0b746e5SOllivier Robert 		ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
2672c0b746e5SOllivier Robert 		ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2);
2673c0b746e5SOllivier Robert 
2674c0b746e5SOllivier Robert 		free_varlist(clock_stat.kv_list);
2675c0b746e5SOllivier Robert 
2676c0b746e5SOllivier Robert 		ic = (struct info_clock *)more_pkt();
2677c0b746e5SOllivier Robert 	}
2678c0b746e5SOllivier Robert 	flush_pkt();
2679c0b746e5SOllivier Robert }
2680c0b746e5SOllivier Robert 
2681c0b746e5SOllivier Robert 
2682c0b746e5SOllivier Robert 
2683c0b746e5SOllivier Robert /*
2684c0b746e5SOllivier Robert  * set_clock_fudge - get a clock's fudge factors
2685c0b746e5SOllivier Robert  */
2686c0b746e5SOllivier Robert static void
2687c0b746e5SOllivier Robert set_clock_fudge(
26889c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2689c0b746e5SOllivier Robert 	struct interface *inter,
2690c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2691c0b746e5SOllivier Robert 	)
2692c0b746e5SOllivier Robert {
2693c0b746e5SOllivier Robert 	register struct conf_fudge *cf;
2694c0b746e5SOllivier Robert 	register int items;
2695c0b746e5SOllivier Robert 	struct refclockstat clock_stat;
26969c2daa00SOllivier Robert 	struct sockaddr_storage addr;
26979c2daa00SOllivier Robert 	struct sockaddr_in tmp_clock;
2698c0b746e5SOllivier Robert 	l_fp ltmp;
2699c0b746e5SOllivier Robert 
2700c0b746e5SOllivier Robert 	memset((char *)&addr, 0, sizeof addr);
2701c0b746e5SOllivier Robert 	memset((char *)&clock_stat, 0, sizeof clock_stat);
2702c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2703c0b746e5SOllivier Robert 	cf = (struct conf_fudge *) inpkt->data;
2704c0b746e5SOllivier Robert 
2705c0b746e5SOllivier Robert 	while (items-- > 0) {
27069c2daa00SOllivier Robert 		tmp_clock.sin_addr.s_addr = cf->clockadr;
27079c2daa00SOllivier Robert 		*CAST_V4(addr) = tmp_clock;
27089c2daa00SOllivier Robert 		addr.ss_family = AF_INET;
27099c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
27109c2daa00SOllivier Robert 		addr.ss_len = SOCKLEN(&addr);
27119c2daa00SOllivier Robert #endif
27129c2daa00SOllivier Robert 		NSRCPORT(&addr) = htons(NTP_PORT);
27139c2daa00SOllivier Robert 		if (!ISREFCLOCKADR(&tmp_clock) ||
2714c0b746e5SOllivier Robert 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2715c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2716c0b746e5SOllivier Robert 			return;
2717c0b746e5SOllivier Robert 		}
2718c0b746e5SOllivier Robert 
2719c0b746e5SOllivier Robert 		switch(ntohl(cf->which)) {
2720c0b746e5SOllivier Robert 		    case FUDGE_TIME1:
2721c0b746e5SOllivier Robert 			NTOHL_FP(&cf->fudgetime, &ltmp);
2722c0b746e5SOllivier Robert 			LFPTOD(&ltmp, clock_stat.fudgetime1);
2723c0b746e5SOllivier Robert 			clock_stat.haveflags = CLK_HAVETIME1;
2724c0b746e5SOllivier Robert 			break;
2725c0b746e5SOllivier Robert 		    case FUDGE_TIME2:
2726c0b746e5SOllivier Robert 			NTOHL_FP(&cf->fudgetime, &ltmp);
2727c0b746e5SOllivier Robert 			LFPTOD(&ltmp, clock_stat.fudgetime2);
2728c0b746e5SOllivier Robert 			clock_stat.haveflags = CLK_HAVETIME2;
2729c0b746e5SOllivier Robert 			break;
2730c0b746e5SOllivier Robert 		    case FUDGE_VAL1:
2731c0b746e5SOllivier Robert 			clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
2732c0b746e5SOllivier Robert 			clock_stat.haveflags = CLK_HAVEVAL1;
2733c0b746e5SOllivier Robert 			break;
2734c0b746e5SOllivier Robert 		    case FUDGE_VAL2:
2735c0b746e5SOllivier Robert 			clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
2736c0b746e5SOllivier Robert 			clock_stat.haveflags = CLK_HAVEVAL2;
2737c0b746e5SOllivier Robert 			break;
2738c0b746e5SOllivier Robert 		    case FUDGE_FLAGS:
27399c2daa00SOllivier Robert 			clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
2740c0b746e5SOllivier Robert 			clock_stat.haveflags =
2741c0b746e5SOllivier Robert 				(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
2742c0b746e5SOllivier Robert 			break;
2743c0b746e5SOllivier Robert 		    default:
2744224ba2bdSOllivier Robert 			msyslog(LOG_ERR, "set_clock_fudge: default!");
2745c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2746c0b746e5SOllivier Robert 			return;
2747c0b746e5SOllivier Robert 		}
2748c0b746e5SOllivier Robert 
2749c0b746e5SOllivier Robert 		refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
2750c0b746e5SOllivier Robert 	}
2751c0b746e5SOllivier Robert 
2752c0b746e5SOllivier Robert 	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2753c0b746e5SOllivier Robert }
2754c0b746e5SOllivier Robert #endif
2755c0b746e5SOllivier Robert 
2756c0b746e5SOllivier Robert #ifdef REFCLOCK
2757c0b746e5SOllivier Robert /*
2758c0b746e5SOllivier Robert  * get_clkbug_info - get debugging info about a clock
2759c0b746e5SOllivier Robert  */
2760c0b746e5SOllivier Robert static void
2761c0b746e5SOllivier Robert get_clkbug_info(
27629c2daa00SOllivier Robert 	struct sockaddr_storage *srcadr,
2763c0b746e5SOllivier Robert 	struct interface *inter,
2764c0b746e5SOllivier Robert 	struct req_pkt *inpkt
2765c0b746e5SOllivier Robert 	)
2766c0b746e5SOllivier Robert {
2767c0b746e5SOllivier Robert 	register int i;
2768c0b746e5SOllivier Robert 	register struct info_clkbug *ic;
2769c0b746e5SOllivier Robert 	register u_int32 *clkaddr;
2770c0b746e5SOllivier Robert 	register int items;
2771c0b746e5SOllivier Robert 	struct refclockbug bug;
27729c2daa00SOllivier Robert 	struct sockaddr_storage addr;
27739c2daa00SOllivier Robert 	struct sockaddr_in tmp_clock;
2774c0b746e5SOllivier Robert 
2775c0b746e5SOllivier Robert 	memset((char *)&addr, 0, sizeof addr);
27769c2daa00SOllivier Robert 	addr.ss_family = AF_INET;
27779c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
27789c2daa00SOllivier Robert 	addr.ss_len = SOCKLEN(&addr);
27799c2daa00SOllivier Robert #endif
27809c2daa00SOllivier Robert 	NSRCPORT(&addr) = htons(NTP_PORT);
2781c0b746e5SOllivier Robert 	items = INFO_NITEMS(inpkt->err_nitems);
2782c0b746e5SOllivier Robert 	clkaddr = (u_int32 *) inpkt->data;
2783c0b746e5SOllivier Robert 
2784c0b746e5SOllivier Robert 	ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
2785c0b746e5SOllivier Robert 					       sizeof(struct info_clkbug));
2786c0b746e5SOllivier Robert 
2787c0b746e5SOllivier Robert 	while (items-- > 0) {
27889c2daa00SOllivier Robert 		tmp_clock.sin_addr.s_addr = *clkaddr++;
27899c2daa00SOllivier Robert 		GET_INADDR(addr) = tmp_clock.sin_addr.s_addr;
27909c2daa00SOllivier Robert 		if (!ISREFCLOCKADR(&tmp_clock) ||
2791c0b746e5SOllivier Robert 		    findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2792c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2793c0b746e5SOllivier Robert 			return;
2794c0b746e5SOllivier Robert 		}
2795c0b746e5SOllivier Robert 
2796c0b746e5SOllivier Robert 		memset((char *)&bug, 0, sizeof bug);
2797c0b746e5SOllivier Robert 		refclock_buginfo(&addr, &bug);
2798c0b746e5SOllivier Robert 		if (bug.nvalues == 0 && bug.ntimes == 0) {
2799c0b746e5SOllivier Robert 			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2800c0b746e5SOllivier Robert 			return;
2801c0b746e5SOllivier Robert 		}
2802c0b746e5SOllivier Robert 
28039c2daa00SOllivier Robert 		ic->clockadr = tmp_clock.sin_addr.s_addr;
2804c0b746e5SOllivier Robert 		i = bug.nvalues;
2805c0b746e5SOllivier Robert 		if (i > NUMCBUGVALUES)
2806c0b746e5SOllivier Robert 		    i = NUMCBUGVALUES;
2807c0b746e5SOllivier Robert 		ic->nvalues = (u_char)i;
2808c0b746e5SOllivier Robert 		ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
2809c0b746e5SOllivier Robert 		while (--i >= 0)
2810c0b746e5SOllivier Robert 		    ic->values[i] = htonl(bug.values[i]);
2811c0b746e5SOllivier Robert 
2812c0b746e5SOllivier Robert 		i = bug.ntimes;
2813c0b746e5SOllivier Robert 		if (i > NUMCBUGTIMES)
2814c0b746e5SOllivier Robert 		    i = NUMCBUGTIMES;
2815c0b746e5SOllivier Robert 		ic->ntimes = (u_char)i;
2816c0b746e5SOllivier Robert 		ic->stimes = htonl(bug.stimes);
2817c0b746e5SOllivier Robert 		while (--i >= 0) {
2818c0b746e5SOllivier Robert 			HTONL_FP(&bug.times[i], &ic->times[i]);
2819c0b746e5SOllivier Robert 		}
2820c0b746e5SOllivier Robert 
2821c0b746e5SOllivier Robert 		ic = (struct info_clkbug *)more_pkt();
2822c0b746e5SOllivier Robert 	}
2823c0b746e5SOllivier Robert 	flush_pkt();
2824c0b746e5SOllivier Robert }
2825c0b746e5SOllivier Robert #endif
2826ea906c41SOllivier Robert 
2827ea906c41SOllivier Robert /*
2828ea906c41SOllivier Robert  * receiver of interface structures
2829ea906c41SOllivier Robert  */
2830ea906c41SOllivier Robert static void
2831ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info)
2832ea906c41SOllivier Robert {
2833ea906c41SOllivier Robert 	struct info_if_stats **ifsp = (struct info_if_stats **)data;
2834ea906c41SOllivier Robert 	struct info_if_stats *ifs = *ifsp;
2835ea906c41SOllivier Robert 	struct interface *interface = interface_info->interface;
2836ea906c41SOllivier Robert 
2837ea906c41SOllivier Robert 	memset((char*)ifs, 0, sizeof(*ifs));
2838ea906c41SOllivier Robert 
2839ea906c41SOllivier Robert 	if (interface->sin.ss_family == AF_INET6) {
2840ea906c41SOllivier Robert 		if (!client_v6_capable) {
2841ea906c41SOllivier Robert 			return;
2842ea906c41SOllivier Robert 		}
2843ea906c41SOllivier Robert 		ifs->v6_flag = 1;
2844ea906c41SOllivier Robert 		memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr));
2845ea906c41SOllivier Robert 		memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr));
2846ea906c41SOllivier Robert 		memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr));
2847ea906c41SOllivier Robert 	} else {
2848ea906c41SOllivier Robert 		ifs->v6_flag = 0;
2849ea906c41SOllivier Robert 		memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr));
2850ea906c41SOllivier Robert 		memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr));
2851ea906c41SOllivier Robert 		memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr));
2852ea906c41SOllivier Robert 	}
2853ea906c41SOllivier Robert 	ifs->v6_flag = htonl(ifs->v6_flag);
2854ea906c41SOllivier Robert 	strcpy(ifs->name, interface->name);
2855ea906c41SOllivier Robert 	ifs->family = htons(interface->family);
2856ea906c41SOllivier Robert 	ifs->flags = htonl(interface->flags);
2857ea906c41SOllivier Robert 	ifs->last_ttl = htonl(interface->last_ttl);
2858ea906c41SOllivier Robert 	ifs->num_mcast = htonl(interface->num_mcast);
2859ea906c41SOllivier Robert 	ifs->received = htonl(interface->received);
2860ea906c41SOllivier Robert 	ifs->sent = htonl(interface->sent);
2861ea906c41SOllivier Robert 	ifs->notsent = htonl(interface->notsent);
2862ea906c41SOllivier Robert 	ifs->scopeid = htonl(interface->scopeid);
2863ea906c41SOllivier Robert 	ifs->ifindex = htonl(interface->ifindex);
2864ea906c41SOllivier Robert 	ifs->ifnum = htonl(interface->ifnum);
2865ea906c41SOllivier Robert 	ifs->uptime = htonl(current_time - interface->starttime);
2866ea906c41SOllivier Robert 	ifs->ignore_packets = interface->ignore_packets;
2867ea906c41SOllivier Robert 	ifs->peercnt = htonl(interface->peercnt);
2868ea906c41SOllivier Robert 	ifs->action = interface_info->action;
2869ea906c41SOllivier Robert 
2870ea906c41SOllivier Robert 	*ifsp = (struct info_if_stats *)more_pkt();
2871ea906c41SOllivier Robert }
2872ea906c41SOllivier Robert 
2873ea906c41SOllivier Robert /*
2874ea906c41SOllivier Robert  * get_if_stats - get interface statistics
2875ea906c41SOllivier Robert  */
2876ea906c41SOllivier Robert static void
2877ea906c41SOllivier Robert get_if_stats(
2878ea906c41SOllivier Robert 	struct sockaddr_storage *srcadr,
2879ea906c41SOllivier Robert 	struct interface *inter,
2880ea906c41SOllivier Robert 	struct req_pkt *inpkt
2881ea906c41SOllivier Robert 	)
2882ea906c41SOllivier Robert {
2883ea906c41SOllivier Robert 	struct info_if_stats *ifs;
2884ea906c41SOllivier Robert 
2885ea906c41SOllivier Robert 	DPRINTF(3, ("wants interface statistics\n"));
2886ea906c41SOllivier Robert 
2887ea906c41SOllivier Robert 	ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2888ea906c41SOllivier Robert 	    v6sizeof(struct info_if_stats));
2889ea906c41SOllivier Robert 
2890ea906c41SOllivier Robert 	interface_enumerate(fill_info_if_stats, &ifs);
2891ea906c41SOllivier Robert 
2892ea906c41SOllivier Robert 	flush_pkt();
2893ea906c41SOllivier Robert }
2894ea906c41SOllivier Robert 
2895ea906c41SOllivier Robert static void
2896ea906c41SOllivier Robert do_if_reload(
2897ea906c41SOllivier Robert 	struct sockaddr_storage *srcadr,
2898ea906c41SOllivier Robert 	struct interface *inter,
2899ea906c41SOllivier Robert 	struct req_pkt *inpkt
2900ea906c41SOllivier Robert 	)
2901ea906c41SOllivier Robert {
2902ea906c41SOllivier Robert 	struct info_if_stats *ifs;
2903ea906c41SOllivier Robert 
2904ea906c41SOllivier Robert 	DPRINTF(3, ("wants interface reload\n"));
2905ea906c41SOllivier Robert 
2906ea906c41SOllivier Robert 	ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2907ea906c41SOllivier Robert 	    v6sizeof(struct info_if_stats));
2908ea906c41SOllivier Robert 
2909ea906c41SOllivier Robert 	interface_update(fill_info_if_stats, &ifs);
2910ea906c41SOllivier Robert 
2911ea906c41SOllivier Robert 	flush_pkt();
2912ea906c41SOllivier Robert }
2913ea906c41SOllivier Robert 
2914