ntp_request.c revision 294905
10SN/A/*
214316Sssadetsky * ntp_request.c - respond to information requests
30SN/A */
40SN/A
50SN/A#ifdef HAVE_CONFIG_H
60SN/A# include <config.h>
72362SN/A#endif
80SN/A
92362SN/A#include "ntpd.h"
100SN/A#include "ntp_io.h"
110SN/A#include "ntp_request.h"
120SN/A#include "ntp_control.h"
130SN/A#include "ntp_refclock.h"
140SN/A#include "ntp_if.h"
150SN/A#include "ntp_stdlib.h"
160SN/A#include "ntp_assert.h"
170SN/A
180SN/A#include <stdio.h>
190SN/A#include <stddef.h>
200SN/A#include <signal.h>
212362SN/A#ifdef HAVE_NETINET_IN_H
222362SN/A#include <netinet/in.h>
232362SN/A#endif
240SN/A#include <arpa/inet.h>
250SN/A
260SN/A#include "recvbuff.h"
2715793Sssadetsky
2815793Sssadetsky#ifdef KERNEL_PLL
290SN/A#include "ntp_syscall.h"
300SN/A#endif /* KERNEL_PLL */
310SN/A
320SN/A/*
330SN/A * Structure to hold request procedure information
340SN/A */
350SN/A#define	NOAUTH	0
360SN/A#define	AUTH	1
370SN/A
380SN/A#define	NO_REQUEST	(-1)
390SN/A/*
400SN/A * Because we now have v6 addresses in the messages, we need to compensate
4115793Sssadetsky * for the larger size.  Therefore, we introduce the alternate size to
420SN/A * keep us friendly with older implementations.  A little ugly.
430SN/A */
440SN/Astatic int client_v6_capable = 0;   /* the client can handle longer messages */
450SN/A
460SN/A#define v6sizeof(type)	(client_v6_capable ? sizeof(type) : v4sizeof(type))
470SN/A
480SN/Astruct req_proc {
490SN/A	short request_code;	/* defined request code */
500SN/A	short needs_auth;	/* true when authentication needed */
510SN/A	short sizeofitem;	/* size of request data item (older size)*/
520SN/A	short v6_sizeofitem;	/* size of request data item (new size)*/
530SN/A	void (*handler) (sockaddr_u *, endpt *,
540SN/A			   struct req_pkt *);	/* routine to handle request */
550SN/A};
560SN/A
570SN/A/*
580SN/A * Universal request codes
590SN/A */
600SN/Astatic const struct req_proc univ_codes[] = {
610SN/A	{ NO_REQUEST,		NOAUTH,	 0,	0, NULL }
620SN/A};
630SN/A
640SN/Astatic	void	req_ack	(sockaddr_u *, endpt *, struct req_pkt *, int);
650SN/Astatic	void *	prepare_pkt	(sockaddr_u *, endpt *,
660SN/A				 struct req_pkt *, size_t);
670SN/Astatic	void *	more_pkt	(void);
680SN/Astatic	void	flush_pkt	(void);
6912839Sprrstatic	void	list_peers	(sockaddr_u *, endpt *, struct req_pkt *);
7012839Sprrstatic	void	list_peers_sum	(sockaddr_u *, endpt *, struct req_pkt *);
710SN/Astatic	void	peer_info	(sockaddr_u *, endpt *, struct req_pkt *);
720SN/Astatic	void	peer_stats	(sockaddr_u *, endpt *, struct req_pkt *);
730SN/Astatic	void	sys_info	(sockaddr_u *, endpt *, struct req_pkt *);
740SN/Astatic	void	sys_stats	(sockaddr_u *, endpt *, struct req_pkt *);
750SN/Astatic	void	mem_stats	(sockaddr_u *, endpt *, struct req_pkt *);
760SN/Astatic	void	io_stats	(sockaddr_u *, endpt *, struct req_pkt *);
770SN/Astatic	void	timer_stats	(sockaddr_u *, endpt *, struct req_pkt *);
780SN/Astatic	void	loop_info	(sockaddr_u *, endpt *, struct req_pkt *);
790SN/Astatic	void	do_conf		(sockaddr_u *, endpt *, struct req_pkt *);
800SN/Astatic	void	do_unconf	(sockaddr_u *, endpt *, struct req_pkt *);
810SN/Astatic	void	set_sys_flag	(sockaddr_u *, endpt *, struct req_pkt *);
820SN/Astatic	void	clr_sys_flag	(sockaddr_u *, endpt *, struct req_pkt *);
830SN/Astatic	void	setclr_flags	(sockaddr_u *, endpt *, struct req_pkt *, u_long);
840SN/Astatic	void	list_restrict4	(const restrict_u *, struct info_restrict **);
850SN/Astatic	void	list_restrict6	(const restrict_u *, struct info_restrict **);
860SN/Astatic	void	list_restrict	(sockaddr_u *, endpt *, struct req_pkt *);
870SN/Astatic	void	do_resaddflags	(sockaddr_u *, endpt *, struct req_pkt *);
880SN/Astatic	void	do_ressubflags	(sockaddr_u *, endpt *, struct req_pkt *);
890SN/Astatic	void	do_unrestrict	(sockaddr_u *, endpt *, struct req_pkt *);
900SN/Astatic	void	do_restrict	(sockaddr_u *, endpt *, struct req_pkt *, int);
910SN/Astatic	void	mon_getlist	(sockaddr_u *, endpt *, struct req_pkt *);
920SN/Astatic	void	reset_stats	(sockaddr_u *, endpt *, struct req_pkt *);
930SN/Astatic	void	reset_peer	(sockaddr_u *, endpt *, struct req_pkt *);
940SN/Astatic	void	do_key_reread	(sockaddr_u *, endpt *, struct req_pkt *);
950SN/Astatic	void	trust_key	(sockaddr_u *, endpt *, struct req_pkt *);
960SN/Astatic	void	untrust_key	(sockaddr_u *, endpt *, struct req_pkt *);
970SN/Astatic	void	do_trustkey	(sockaddr_u *, endpt *, struct req_pkt *, u_long);
980SN/Astatic	void	get_auth_info	(sockaddr_u *, endpt *, struct req_pkt *);
990SN/Astatic	void	req_get_traps	(sockaddr_u *, endpt *, struct req_pkt *);
1000SN/Astatic	void	req_set_trap	(sockaddr_u *, endpt *, struct req_pkt *);
1010SN/Astatic	void	req_clr_trap	(sockaddr_u *, endpt *, struct req_pkt *);
1020SN/Astatic	void	do_setclr_trap	(sockaddr_u *, endpt *, struct req_pkt *, int);
1030SN/Astatic	void	set_request_keyid (sockaddr_u *, endpt *, struct req_pkt *);
1040SN/Astatic	void	set_control_keyid (sockaddr_u *, endpt *, struct req_pkt *);
1050SN/Astatic	void	get_ctl_stats   (sockaddr_u *, endpt *, struct req_pkt *);
1060SN/Astatic	void	get_if_stats    (sockaddr_u *, endpt *, struct req_pkt *);
1070SN/Astatic	void	do_if_reload    (sockaddr_u *, endpt *, struct req_pkt *);
1080SN/A#ifdef KERNEL_PLL
1090SN/Astatic	void	get_kernel_info (sockaddr_u *, endpt *, struct req_pkt *);
1100SN/A#endif /* KERNEL_PLL */
1110SN/A#ifdef REFCLOCK
1120SN/Astatic	void	get_clock_info (sockaddr_u *, endpt *, struct req_pkt *);
1130SN/Astatic	void	set_clock_fudge (sockaddr_u *, endpt *, struct req_pkt *);
1140SN/A#endif	/* REFCLOCK */
1150SN/A#ifdef REFCLOCK
1160SN/Astatic	void	get_clkbug_info (sockaddr_u *, endpt *, struct req_pkt *);
1170SN/A#endif	/* REFCLOCK */
1180SN/A
1190SN/A/*
1200SN/A * ntpd request codes
1210SN/A */
1220SN/Astatic const struct req_proc ntp_codes[] = {
1230SN/A	{ REQ_PEER_LIST,	NOAUTH,	0, 0,	list_peers },
1240SN/A	{ REQ_PEER_LIST_SUM,	NOAUTH,	0, 0,	list_peers_sum },
1250SN/A	{ REQ_PEER_INFO,    NOAUTH, v4sizeof(struct info_peer_list),
1260SN/A				sizeof(struct info_peer_list), peer_info},
1270SN/A	{ REQ_PEER_STATS,   NOAUTH, v4sizeof(struct info_peer_list),
1280SN/A				sizeof(struct info_peer_list), peer_stats},
1290SN/A	{ REQ_SYS_INFO,		NOAUTH,	0, 0,	sys_info },
1300SN/A	{ REQ_SYS_STATS,	NOAUTH,	0, 0,	sys_stats },
1310SN/A	{ REQ_IO_STATS,		NOAUTH,	0, 0,	io_stats },
1320SN/A	{ REQ_MEM_STATS,	NOAUTH,	0, 0,	mem_stats },
1330SN/A	{ REQ_LOOP_INFO,	NOAUTH,	0, 0,	loop_info },
1340SN/A	{ REQ_TIMER_STATS,	NOAUTH,	0, 0,	timer_stats },
1350SN/A	{ REQ_CONFIG,	    AUTH, v4sizeof(struct conf_peer),
1360SN/A				sizeof(struct conf_peer), do_conf },
1370SN/A	{ REQ_UNCONFIG,	    AUTH, v4sizeof(struct conf_unpeer),
1380SN/A				sizeof(struct conf_unpeer), do_unconf },
1390SN/A	{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
1400SN/A				sizeof(struct conf_sys_flags), set_sys_flag },
1410SN/A	{ REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
1420SN/A				sizeof(struct conf_sys_flags),  clr_sys_flag },
1430SN/A	{ REQ_GET_RESTRICT,	NOAUTH,	0, 0,	list_restrict },
1440SN/A	{ REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),
1450SN/A				sizeof(struct conf_restrict), do_resaddflags },
1460SN/A	{ REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),
1470SN/A				sizeof(struct conf_restrict), do_ressubflags },
1480SN/A	{ REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),
1490SN/A				sizeof(struct conf_restrict), do_unrestrict },
1500SN/A	{ REQ_MON_GETLIST,	NOAUTH,	0, 0,	mon_getlist },
1510SN/A	{ REQ_MON_GETLIST_1,	NOAUTH,	0, 0,	mon_getlist },
1520SN/A	{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },
1530SN/A	{ REQ_RESET_PEER,  AUTH, v4sizeof(struct conf_unpeer),
1540SN/A				sizeof(struct conf_unpeer), reset_peer },
1550SN/A	{ REQ_REREAD_KEYS,	AUTH,	0, 0,	do_key_reread },
1560SN/A	{ REQ_TRUSTKEY,   AUTH, sizeof(u_long), sizeof(u_long), trust_key },
1570SN/A	{ REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },
1580SN/A	{ REQ_AUTHINFO,		NOAUTH,	0, 0,	get_auth_info },
1590SN/A	{ REQ_TRAPS,		NOAUTH, 0, 0,	req_get_traps },
1600SN/A	{ REQ_ADD_TRAP,	AUTH, v4sizeof(struct conf_trap),
1610SN/A				sizeof(struct conf_trap), req_set_trap },
1620SN/A	{ REQ_CLR_TRAP,	AUTH, v4sizeof(struct conf_trap),
1630SN/A				sizeof(struct conf_trap), req_clr_trap },
1640SN/A	{ REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long),
1650SN/A				set_request_keyid },
1660SN/A	{ REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long),
1670SN/A				set_control_keyid },
1680SN/A	{ REQ_GET_CTLSTATS,	NOAUTH,	0, 0,	get_ctl_stats },
1690SN/A#ifdef KERNEL_PLL
1700SN/A	{ REQ_GET_KERNEL,	NOAUTH,	0, 0,	get_kernel_info },
1710SN/A#endif
1720SN/A#ifdef REFCLOCK
1730SN/A	{ REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
1740SN/A				get_clock_info },
1750SN/A	{ REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge),
1760SN/A				sizeof(struct conf_fudge), set_clock_fudge },
1770SN/A	{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
1780SN/A				get_clkbug_info },
1790SN/A#endif
1800SN/A	{ REQ_IF_STATS,		AUTH, 0, 0,	get_if_stats },
1810SN/A	{ REQ_IF_RELOAD,	AUTH, 0, 0,	do_if_reload },
1820SN/A
1830SN/A	{ NO_REQUEST,		NOAUTH,	0, 0,	0 }
1840SN/A};
1850SN/A
1860SN/A
1870SN/A/*
1880SN/A * Authentication keyid used to authenticate requests.  Zero means we
1890SN/A * don't allow writing anything.
1900SN/A */
1910SN/Akeyid_t info_auth_keyid;
1920SN/A
1930SN/A/*
1940SN/A * Statistic counters to keep track of requests and responses.
1950SN/A */
1960SN/Au_long numrequests;		/* number of requests we've received */
1970SN/Au_long numresppkts;		/* number of resp packets sent with data */
1980SN/A
1990SN/A/*
2000SN/A * lazy way to count errors, indexed by the error code
2010SN/A */
2020SN/Au_long errorcounter[MAX_INFO_ERR + 1];
2030SN/A
2040SN/A/*
2050SN/A * A hack.  To keep the authentication module clear of ntp-ism's, we
2060SN/A * include a time reset variable for its stats here.
2070SN/A */
2080SN/Au_long auth_timereset;
2090SN/A
2100SN/A/*
2110SN/A * Response packet used by these routines.  Also some state information
2120SN/A * so that we can handle packet formatting within a common set of
2130SN/A * subroutines.  Note we try to enter data in place whenever possible,
2140SN/A * but the need to set the more bit correctly means we occasionally
2150SN/A * use the extra buffer and copy.
2160SN/A */
2170SN/Astatic struct resp_pkt rpkt;
2180SN/Astatic int reqver;
2190SN/Astatic int seqno;
2200SN/Astatic int nitems;
2210SN/Astatic int itemsize;
2220SN/Astatic int databytes;
2230SN/Astatic char exbuf[RESP_DATA_SIZE];
2240SN/Astatic int usingexbuf;
2250SN/Astatic sockaddr_u *toaddr;
2260SN/Astatic endpt *frominter;
2270SN/A
2280SN/A/*
2290SN/A * init_request - initialize request data
2300SN/A */
2310SN/Avoid
2320SN/Ainit_request (void)
2330SN/A{
2340SN/A	size_t i;
2350SN/A
2360SN/A	numrequests = 0;
2370SN/A	numresppkts = 0;
2380SN/A	auth_timereset = 0;
2390SN/A	info_auth_keyid = 0;	/* by default, can't do this */
2400SN/A
2410SN/A	for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
2420SN/A	    errorcounter[i] = 0;
2430SN/A}
2440SN/A
2450SN/A
2460SN/A/*
2470SN/A * req_ack - acknowledge request with no data
2480SN/A */
2490SN/Astatic void
2500SN/Areq_ack(
2510SN/A	sockaddr_u *srcadr,
2520SN/A	endpt *inter,
2530SN/A	struct req_pkt *inpkt,
2540SN/A	int errcode
2550SN/A	)
2560SN/A{
2570SN/A	/*
2580SN/A	 * fill in the fields
2590SN/A	 */
2600SN/A	rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
2610SN/A	rpkt.auth_seq = AUTH_SEQ(0, 0);
2620SN/A	rpkt.implementation = inpkt->implementation;
2630SN/A	rpkt.request = inpkt->request;
2640SN/A	rpkt.err_nitems = ERR_NITEMS(errcode, 0);
2650SN/A	rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
2660SN/A
2670SN/A	/*
2680SN/A	 * send packet and bump counters
2690SN/A	 */
2700SN/A	sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
2710SN/A	errorcounter[errcode]++;
2720SN/A}
2730SN/A
2740SN/A
2750SN/A/*
2760SN/A * prepare_pkt - prepare response packet for transmission, return pointer
2770SN/A *		 to storage for data item.
2780SN/A */
2790SN/Astatic void *
2800SN/Aprepare_pkt(
2810SN/A	sockaddr_u *srcadr,
2820SN/A	endpt *inter,
2830SN/A	struct req_pkt *pkt,
2840SN/A	size_t structsize
2850SN/A	)
2860SN/A{
2870SN/A	DPRINTF(4, ("request: preparing pkt\n"));
2880SN/A
2890SN/A	/*
2900SN/A	 * Fill in the implementation, request and itemsize fields
2910SN/A	 * since these won't change.
2920SN/A	 */
2930SN/A	rpkt.implementation = pkt->implementation;
2940SN/A	rpkt.request = pkt->request;
2950SN/A	rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
2960SN/A
2970SN/A	/*
2980SN/A	 * Compute the static data needed to carry on.
2990SN/A	 */
3000SN/A	toaddr = srcadr;
3010SN/A	frominter = inter;
3020SN/A	seqno = 0;
3030SN/A	nitems = 0;
304820SN/A	itemsize = structsize;
3050SN/A	databytes = 0;
3060SN/A	usingexbuf = 0;
3070SN/A
3080SN/A	/*
3090SN/A	 * return the beginning of the packet buffer.
3100SN/A	 */
3110SN/A	return &rpkt.u;
3120SN/A}
3130SN/A
3140SN/A
3150SN/A/*
3160SN/A * more_pkt - return a data pointer for a new item.
3170SN/A */
3180SN/Astatic void *
3190SN/Amore_pkt(void)
3200SN/A{
3210SN/A	/*
3220SN/A	 * If we were using the extra buffer, send the packet.
3230SN/A	 */
3240SN/A	if (usingexbuf) {
3250SN/A		DPRINTF(3, ("request: sending pkt\n"));
3260SN/A		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
3270SN/A		rpkt.auth_seq = AUTH_SEQ(0, seqno);
3280SN/A		rpkt.err_nitems = htons((u_short)nitems);
3290SN/A		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
3300SN/A			RESP_HEADER_SIZE + databytes);
3310SN/A		numresppkts++;
3320SN/A
3330SN/A		/*
3340SN/A		 * Copy data out of exbuf into the packet.
3350SN/A		 */
3360SN/A		memcpy(&rpkt.u.data[0], exbuf, (unsigned)itemsize);
3370SN/A		seqno++;
3380SN/A		databytes = 0;
3390SN/A		nitems = 0;
3400SN/A		usingexbuf = 0;
3410SN/A	}
3420SN/A
3430SN/A	databytes += itemsize;
3440SN/A	nitems++;
3450SN/A	if (databytes + itemsize <= RESP_DATA_SIZE) {
3460SN/A		DPRINTF(4, ("request: giving him more data\n"));
3470SN/A		/*
3480SN/A		 * More room in packet.  Give him the
3490SN/A		 * next address.
3500SN/A		 */
3510SN/A		return &rpkt.u.data[databytes];
3520SN/A	} else {
3530SN/A		/*
3540SN/A		 * No room in packet.  Give him the extra
3550SN/A		 * buffer unless this was the last in the sequence.
3560SN/A		 */
3570SN/A		DPRINTF(4, ("request: into extra buffer\n"));
3580SN/A		if (seqno == MAXSEQ)
3590SN/A			return NULL;
3600SN/A		else {
3610SN/A			usingexbuf = 1;
3620SN/A			return exbuf;
3630SN/A		}
3640SN/A	}
3650SN/A}
3660SN/A
3670SN/A
3680SN/A/*
3690SN/A * flush_pkt - we're done, return remaining information.
3700SN/A */
3710SN/Astatic void
3720SN/Aflush_pkt(void)
3730SN/A{
3740SN/A	DPRINTF(3, ("request: flushing packet, %d items\n", nitems));
3750SN/A	/*
3760SN/A	 * Must send the last packet.  If nothing in here and nothing
3770SN/A	 * has been sent, send an error saying no data to be found.
3780SN/A	 */
3790SN/A	if (seqno == 0 && nitems == 0)
3800SN/A		req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
3810SN/A			INFO_ERR_NODATA);
3820SN/A	else {
3830SN/A		rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
3840SN/A		rpkt.auth_seq = AUTH_SEQ(0, seqno);
3850SN/A		rpkt.err_nitems = htons((u_short)nitems);
3860SN/A		sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
3870SN/A			RESP_HEADER_SIZE+databytes);
3880SN/A		numresppkts++;
3890SN/A	}
3900SN/A}
3910SN/A
3920SN/A
3930SN/A
3940SN/A/*
3950SN/A * Given a buffer, return the packet mode
3960SN/A */
3970SN/Aint
3980SN/Aget_packet_mode(struct recvbuf *rbufp)
3990SN/A{
4000SN/A	struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt;
4010SN/A	return (INFO_MODE(inpkt->rm_vn_mode));
4020SN/A}
4030SN/A
4040SN/A
4052711SN/A/*
4060SN/A * process_private - process private mode (7) packets
4070SN/A */
4080SN/Avoid
4090SN/Aprocess_private(
4100SN/A	struct recvbuf *rbufp,
4110SN/A	int mod_okay
4120SN/A	)
4130SN/A{
4140SN/A	static u_long quiet_until;
4152711SN/A	struct req_pkt *inpkt;
4160SN/A	struct req_pkt_tail *tailinpkt;
4170SN/A	sockaddr_u *srcadr;
4180SN/A	endpt *inter;
4190SN/A	const struct req_proc *proc;
4200SN/A	int ec;
4210SN/A	short temp_size;
4220SN/A	l_fp ftmp;
4230SN/A	double dtemp;
4240SN/A	size_t recv_len;
4250SN/A	size_t noslop_len;
4260SN/A	size_t mac_len;
4270SN/A
4280SN/A	/*
4290SN/A	 * Initialize pointers, for convenience
4300SN/A	 */
4310SN/A	recv_len = rbufp->recv_length;
4320SN/A	inpkt = (struct req_pkt *)&rbufp->recv_pkt;
4330SN/A	srcadr = &rbufp->recv_srcadr;
4340SN/A	inter = rbufp->dstadr;
4350SN/A
4360SN/A	DPRINTF(3, ("process_private: impl %d req %d\n",
4370SN/A		    inpkt->implementation, inpkt->request));
4380SN/A
4390SN/A	/*
4400SN/A	 * Do some sanity checks on the packet.  Return a format
4410SN/A	 * error if it fails.
4422711SN/A	 */
4430SN/A	ec = 0;
4440SN/A	if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))
4450SN/A	    || (++ec, ISMORE(inpkt->rm_vn_mode))
4460SN/A	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
4470SN/A	    || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
4480SN/A	    || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
4490SN/A	    || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
4500SN/A	    || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
4510SN/A	    || (++ec, rbufp->recv_length < (int)REQ_LEN_HDR)
4520SN/A		) {
4530SN/A		NLOG(NLOG_SYSEVENT)
4540SN/A			if (current_time >= quiet_until) {
4550SN/A				msyslog(LOG_ERR,
4560SN/A					"process_private: drop test %d"
4570SN/A					" failed, pkt from %s",
4580SN/A					ec, stoa(srcadr));
4590SN/A				quiet_until = current_time + 60;
4600SN/A			}
4610SN/A		return;
4620SN/A	}
4632711SN/A
4640SN/A	reqver = INFO_VERSION(inpkt->rm_vn_mode);
4650SN/A
4660SN/A	/*
4670SN/A	 * Get the appropriate procedure list to search.
4680SN/A	 */
4690SN/A	if (inpkt->implementation == IMPL_UNIV)
4700SN/A		proc = univ_codes;
4710SN/A	else if ((inpkt->implementation == IMPL_XNTPD) ||
4720SN/A		 (inpkt->implementation == IMPL_XNTPD_OLD))
4730SN/A		proc = ntp_codes;
4740SN/A	else {
4750SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
4760SN/A		return;
4770SN/A	}
4780SN/A
4790SN/A	/*
4800SN/A	 * Search the list for the request codes.  If it isn't one
4810SN/A	 * we know, return an error.
4820SN/A	 */
4830SN/A	while (proc->request_code != NO_REQUEST) {
4840SN/A		if (proc->request_code == (short) inpkt->request)
4850SN/A			break;
4860SN/A		proc++;
4870SN/A	}
4880SN/A	if (proc->request_code == NO_REQUEST) {
4890SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
4900SN/A		return;
4910SN/A	}
4920SN/A
4930SN/A	DPRINTF(4, ("found request in tables\n"));
4940SN/A
4950SN/A	/*
4960SN/A	 * If we need data, check to see if we have some.  If we
4970SN/A	 * don't, check to see that there is none (picky, picky).
4980SN/A	 */
4990SN/A
5000SN/A	/* This part is a bit tricky, we want to be sure that the size
5010SN/A	 * returned is either the old or the new size.  We also can find
5020SN/A	 * out if the client can accept both types of messages this way.
5030SN/A	 *
5040SN/A	 * Handle the exception of REQ_CONFIG. It can have two data sizes.
5050SN/A	 */
5060SN/A	temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);
5070SN/A	if ((temp_size != proc->sizeofitem &&
5080SN/A	     temp_size != proc->v6_sizeofitem) &&
5090SN/A	    !(inpkt->implementation == IMPL_XNTPD &&
5100SN/A	      inpkt->request == REQ_CONFIG &&
5110SN/A	      temp_size == sizeof(struct old_conf_peer))) {
5120SN/A		DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n",
5130SN/A			    temp_size, proc->sizeofitem, proc->v6_sizeofitem));
5140SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5150SN/A		return;
5160SN/A	}
5170SN/A	if ((proc->sizeofitem != 0) &&
5180SN/A	    ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) >
5190SN/A	     (recv_len - REQ_LEN_HDR))) {
5200SN/A		DPRINTF(3, ("process_private: not enough data\n"));
5210SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5220SN/A		return;
5230SN/A	}
5240SN/A
5250SN/A	switch (inpkt->implementation) {
5260SN/A	case IMPL_XNTPD:
5270SN/A		client_v6_capable = 1;
5280SN/A		break;
5290SN/A	case IMPL_XNTPD_OLD:
5300SN/A		client_v6_capable = 0;
5310SN/A		break;
5320SN/A	default:
5330SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5340SN/A		return;
5350SN/A	}
5360SN/A
5370SN/A	/*
5380SN/A	 * If we need to authenticate, do so.  Note that an
5390SN/A	 * authenticatable packet must include a mac field, must
5400SN/A	 * have used key info_auth_keyid and must have included
5410SN/A	 * a time stamp in the appropriate field.  The time stamp
5420SN/A	 * must be within INFO_TS_MAXSKEW of the receive
5430SN/A	 * time stamp.
5440SN/A	 */
5450SN/A	if (proc->needs_auth && sys_authenticate) {
5460SN/A
5470SN/A		if (recv_len < (REQ_LEN_HDR +
5480SN/A		    (INFO_ITEMSIZE(inpkt->mbz_itemsize) *
5490SN/A		    INFO_NITEMS(inpkt->err_nitems)) +
5500SN/A		    REQ_TAIL_MIN)) {
5510SN/A			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
5520SN/A			return;
5530SN/A		}
5540SN/A
5550SN/A		/*
5560SN/A		 * For 16-octet digests, regardless of itemsize and
5570SN/A		 * nitems, authenticated requests are a fixed size
5580SN/A		 * with the timestamp, key ID, and digest located
5590SN/A		 * at the end of the packet.  Because the key ID
5600SN/A		 * determining the digest size precedes the digest,
5610SN/A		 * for larger digests the fixed size request scheme
5620SN/A		 * is abandoned and the timestamp, key ID, and digest
5630SN/A		 * are located relative to the start of the packet,
5640SN/A		 * with the digest size determined by the packet size.
5650SN/A		 */
5660SN/A		noslop_len = REQ_LEN_HDR
5670SN/A			     + INFO_ITEMSIZE(inpkt->mbz_itemsize) *
5680SN/A			       INFO_NITEMS(inpkt->err_nitems)
5690SN/A			     + sizeof(inpkt->tstamp);
5700SN/A		/* 32-bit alignment */
5710SN/A		noslop_len = (noslop_len + 3) & ~3;
5720SN/A		if (recv_len > (noslop_len + MAX_MAC_LEN))
57315793Sssadetsky			mac_len = 20;
57415793Sssadetsky		else
5750SN/A			mac_len = recv_len - noslop_len;
57615793Sssadetsky
5770SN/A		tailinpkt = (void *)((char *)inpkt + recv_len -
5780SN/A			    (mac_len + sizeof(inpkt->tstamp)));
5790SN/A
5800SN/A		/*
5810SN/A		 * If this guy is restricted from doing this, don't let
5820SN/A		 * him.  If the wrong key was used, or packet doesn't
5830SN/A		 * have mac, return.
58414316Sssadetsky		 */
5850SN/A		if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid
58614316Sssadetsky		    || ntohl(tailinpkt->keyid) != info_auth_keyid) {
58714316Sssadetsky			DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
58814316Sssadetsky				    INFO_IS_AUTH(inpkt->auth_seq),
58915793Sssadetsky				    info_auth_keyid,
59015793Sssadetsky				    ntohl(tailinpkt->keyid), (u_long)mac_len));
59115793Sssadetsky#ifdef DEBUG
59215793Sssadetsky			msyslog(LOG_DEBUG,
59315793Sssadetsky				"process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
59415793Sssadetsky				INFO_IS_AUTH(inpkt->auth_seq),
59515793Sssadetsky				info_auth_keyid,
59615793Sssadetsky				ntohl(tailinpkt->keyid), (u_long)mac_len);
59715793Sssadetsky#endif
59815793Sssadetsky			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
59915793Sssadetsky			return;
60015793Sssadetsky		}
60115793Sssadetsky		if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) {
60215793Sssadetsky			DPRINTF(5, ("bad pkt length %zu\n", recv_len));
60315793Sssadetsky			msyslog(LOG_ERR,
60415793Sssadetsky				"process_private: bad pkt length %zu",
60515793Sssadetsky				recv_len);
60615793Sssadetsky			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
60715793Sssadetsky			return;
6080SN/A		}
6090SN/A		if (!mod_okay || !authhavekey(info_auth_keyid)) {
6100SN/A			DPRINTF(5, ("failed auth mod_okay %d\n",
6110SN/A				    mod_okay));
6120SN/A#ifdef DEBUG
6130SN/A			msyslog(LOG_DEBUG,
6140SN/A				"process_private: failed auth mod_okay %d\n",
6150SN/A				mod_okay);
6160SN/A#endif
6170SN/A			if (!mod_okay) {
6180SN/A				sys_restricted++;
6190SN/A			}
6200SN/A			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
6210SN/A			return;
6220SN/A		}
6230SN/A
6240SN/A		/*
6250SN/A		 * calculate absolute time difference between xmit time stamp
6260SN/A		 * and receive time stamp.  If too large, too bad.
6270SN/A		 */
6280SN/A		NTOHL_FP(&tailinpkt->tstamp, &ftmp);
6290SN/A		L_SUB(&ftmp, &rbufp->recv_time);
6300SN/A		LFPTOD(&ftmp, dtemp);
6310SN/A		if (fabs(dtemp) > INFO_TS_MAXSKEW) {
6320SN/A			/*
6330SN/A			 * He's a loser.  Tell him.
6340SN/A			 */
6350SN/A			DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n",
6360SN/A				    dtemp, INFO_TS_MAXSKEW));
6370SN/A			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
6380SN/A			return;
6390SN/A		}
6400SN/A
6410SN/A		/*
6420SN/A		 * So far so good.  See if decryption works out okay.
6430SN/A		 */
6440SN/A		if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
6450SN/A				 recv_len - mac_len, mac_len)) {
6460SN/A			DPRINTF(5, ("authdecrypt failed\n"));
6470SN/A			req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
6480SN/A			return;
6490SN/A		}
6500SN/A	}
6510SN/A
6520SN/A	DPRINTF(3, ("process_private: all okay, into handler\n"));
6530SN/A	/*
6540SN/A	 * Packet is okay.  Call the handler to send him data.
6550SN/A	 */
6560SN/A	(proc->handler)(srcadr, inter, inpkt);
6570SN/A}
6580SN/A
6590SN/A
6600SN/A/*
6610SN/A * list_peers - send a list of the peers
6620SN/A */
6630SN/Astatic void
6640SN/Alist_peers(
66514316Sssadetsky	sockaddr_u *srcadr,
66614316Sssadetsky	endpt *inter,
66714316Sssadetsky	struct req_pkt *inpkt
66814316Sssadetsky	)
66914316Sssadetsky{
67014316Sssadetsky	struct info_peer_list *	ip;
67114316Sssadetsky	const struct peer *	pp;
67214316Sssadetsky
67314316Sssadetsky	ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
67414316Sssadetsky	    v6sizeof(struct info_peer_list));
67514316Sssadetsky	for (pp = peer_list; pp != NULL && ip != NULL; pp = pp->p_link) {
67614316Sssadetsky		if (IS_IPV6(&pp->srcadr)) {
67715272Sssadetsky			if (!client_v6_capable)
67815272Sssadetsky				continue;
67915272Sssadetsky			ip->addr6 = SOCK_ADDR6(&pp->srcadr);
68015272Sssadetsky			ip->v6_flag = 1;
68115272Sssadetsky		} else {
68215272Sssadetsky			ip->addr = NSRCADR(&pp->srcadr);
68315272Sssadetsky			if (client_v6_capable)
68415272Sssadetsky				ip->v6_flag = 0;
68515272Sssadetsky		}
68615272Sssadetsky
68715272Sssadetsky		ip->port = NSRCPORT(&pp->srcadr);
68814316Sssadetsky		ip->hmode = pp->hmode;
68914316Sssadetsky		ip->flags = 0;
69014316Sssadetsky		if (pp->flags & FLAG_CONFIG)
69114316Sssadetsky			ip->flags |= INFO_FLAG_CONFIG;
69214316Sssadetsky		if (pp == sys_peer)
69314316Sssadetsky			ip->flags |= INFO_FLAG_SYSPEER;
69414316Sssadetsky		if (pp->status == CTL_PST_SEL_SYNCCAND)
69514316Sssadetsky			ip->flags |= INFO_FLAG_SEL_CANDIDATE;
69614316Sssadetsky		if (pp->status >= CTL_PST_SEL_SYSPEER)
69714316Sssadetsky			ip->flags |= INFO_FLAG_SHORTLIST;
69814316Sssadetsky		ip = (struct info_peer_list *)more_pkt();
69914316Sssadetsky	}	/* for pp */
70014316Sssadetsky
70114316Sssadetsky	flush_pkt();
7020SN/A}
7030SN/A
7040SN/A
7050SN/A/*
7060SN/A * list_peers_sum - return extended peer list
7070SN/A */
7080SN/Astatic void
7090SN/Alist_peers_sum(
7100SN/A	sockaddr_u *srcadr,
7110SN/A	endpt *inter,
7120SN/A	struct req_pkt *inpkt
7130SN/A	)
7140SN/A{
7150SN/A	struct info_peer_summary *	ips;
7160SN/A	const struct peer *		pp;
7170SN/A	l_fp 				ltmp;
7180SN/A
7190SN/A	DPRINTF(3, ("wants peer list summary\n"));
7200SN/A
7210SN/A	ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
7220SN/A	    v6sizeof(struct info_peer_summary));
7230SN/A	for (pp = peer_list; pp != NULL && ips != NULL; pp = pp->p_link) {
7240SN/A		DPRINTF(4, ("sum: got one\n"));
7250SN/A		/*
7260SN/A		 * Be careful here not to return v6 peers when we
7270SN/A		 * want only v4.
7280SN/A		 */
7290SN/A		if (IS_IPV6(&pp->srcadr)) {
7300SN/A			if (!client_v6_capable)
7310SN/A				continue;
7320SN/A			ips->srcadr6 = SOCK_ADDR6(&pp->srcadr);
7330SN/A			ips->v6_flag = 1;
7340SN/A			if (pp->dstadr)
7350SN/A				ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin);
7360SN/A			else
7370SN/A				ZERO(ips->dstadr6);
7380SN/A		} else {
7390SN/A			ips->srcadr = NSRCADR(&pp->srcadr);
7400SN/A			if (client_v6_capable)
7410SN/A				ips->v6_flag = 0;
7420SN/A
7430SN/A			if (pp->dstadr) {
7440SN/A				if (!pp->processed)
7450SN/A					ips->dstadr = NSRCADR(&pp->dstadr->sin);
7460SN/A				else {
7470SN/A					if (MDF_BCAST == pp->cast_flags)
7480SN/A						ips->dstadr = NSRCADR(&pp->dstadr->bcast);
7490SN/A					else if (pp->cast_flags) {
7500SN/A						ips->dstadr = NSRCADR(&pp->dstadr->sin);
7510SN/A						if (!ips->dstadr)
7520SN/A							ips->dstadr = NSRCADR(&pp->dstadr->bcast);
7530SN/A					}
7540SN/A				}
7550SN/A			} else {
7560SN/A				ips->dstadr = 0;
7570SN/A			}
7580SN/A		}
7590SN/A
7600SN/A		ips->srcport = NSRCPORT(&pp->srcadr);
7610SN/A		ips->stratum = pp->stratum;
7620SN/A		ips->hpoll = pp->hpoll;
7630SN/A		ips->ppoll = pp->ppoll;
7640SN/A		ips->reach = pp->reach;
7650SN/A		ips->flags = 0;
7660SN/A		if (pp == sys_peer)
7670SN/A			ips->flags |= INFO_FLAG_SYSPEER;
7680SN/A		if (pp->flags & FLAG_CONFIG)
7690SN/A			ips->flags |= INFO_FLAG_CONFIG;
7700SN/A		if (pp->flags & FLAG_REFCLOCK)
7710SN/A			ips->flags |= INFO_FLAG_REFCLOCK;
7720SN/A		if (pp->flags & FLAG_PREFER)
7730SN/A			ips->flags |= INFO_FLAG_PREFER;
7740SN/A		if (pp->flags & FLAG_BURST)
7750SN/A			ips->flags |= INFO_FLAG_BURST;
7760SN/A		if (pp->status == CTL_PST_SEL_SYNCCAND)
7770SN/A			ips->flags |= INFO_FLAG_SEL_CANDIDATE;
7780SN/A		if (pp->status >= CTL_PST_SEL_SYSPEER)
7790SN/A			ips->flags |= INFO_FLAG_SHORTLIST;
7800SN/A		ips->hmode = pp->hmode;
7810SN/A		ips->delay = HTONS_FP(DTOFP(pp->delay));
7820SN/A		DTOLFP(pp->offset, &ltmp);
7830SN/A		HTONL_FP(&ltmp, &ips->offset);
7840SN/A		ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
7850SN/A
7860SN/A		ips = (struct info_peer_summary *)more_pkt();
7870SN/A	}	/* for pp */
7880SN/A
7890SN/A	flush_pkt();
7900SN/A}
7910SN/A
7920SN/A
7930SN/A/*
7940SN/A * peer_info - send information for one or more peers
7950SN/A */
7960SN/Astatic void
7970SN/Apeer_info (
7980SN/A	sockaddr_u *srcadr,
7990SN/A	endpt *inter,
8000SN/A	struct req_pkt *inpkt
8010SN/A	)
8020SN/A{
80314339Sssadetsky	u_short			items;
80414339Sssadetsky	size_t			item_sz;
80514339Sssadetsky	char *			datap;
80614339Sssadetsky	struct info_peer_list	ipl;
80714339Sssadetsky	struct peer *		pp;
80814339Sssadetsky	struct info_peer *	ip;
80914339Sssadetsky	int			i;
81014339Sssadetsky	int			j;
81114339Sssadetsky	sockaddr_u		addr;
8120SN/A	l_fp			ltmp;
8130SN/A
8140SN/A	items = INFO_NITEMS(inpkt->err_nitems);
8150SN/A	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
8160SN/A	datap = inpkt->u.data;
8170SN/A	if (item_sz != sizeof(ipl)) {
8180SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
8190SN/A		return;
8200SN/A	}
8210SN/A	ip = prepare_pkt(srcadr, inter, inpkt,
8220SN/A			 v6sizeof(struct info_peer));
8230SN/A	while (items-- > 0 && ip != NULL) {
8240SN/A		ZERO(ipl);
8250SN/A		memcpy(&ipl, datap, item_sz);
8260SN/A		ZERO_SOCK(&addr);
8270SN/A		NSRCPORT(&addr) = ipl.port;
8280SN/A		if (client_v6_capable && ipl.v6_flag) {
8290SN/A			AF(&addr) = AF_INET6;
8300SN/A			SOCK_ADDR6(&addr) = ipl.addr6;
8310SN/A		} else {
8320SN/A			AF(&addr) = AF_INET;
8330SN/A			NSRCADR(&addr) = ipl.addr;
8340SN/A		}
8350SN/A#ifdef ISC_PLATFORM_HAVESALEN
8360SN/A		addr.sa.sa_len = SOCKLEN(&addr);
8370SN/A#endif
8380SN/A		datap += item_sz;
8390SN/A
8400SN/A		pp = findexistingpeer(&addr, NULL, NULL, -1, 0);
8410SN/A		if (NULL == pp)
8420SN/A			continue;
8430SN/A		if (IS_IPV6(srcadr)) {
8440SN/A			if (pp->dstadr)
84514339Sssadetsky				ip->dstadr6 =
84614339Sssadetsky				    (MDF_BCAST == pp->cast_flags)
8470SN/A					? SOCK_ADDR6(&pp->dstadr->bcast)
84814339Sssadetsky					: SOCK_ADDR6(&pp->dstadr->sin);
84914339Sssadetsky			else
8500SN/A				ZERO(ip->dstadr6);
8510SN/A
8520SN/A			ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
8530SN/A			ip->v6_flag = 1;
8540SN/A		} else {
8550SN/A			if (pp->dstadr) {
85614339Sssadetsky				if (!pp->processed)
85714339Sssadetsky					ip->dstadr = NSRCADR(&pp->dstadr->sin);
8580SN/A				else {
8590SN/A					if (MDF_BCAST == pp->cast_flags)
8600SN/A						ip->dstadr = NSRCADR(&pp->dstadr->bcast);
8610SN/A					else if (pp->cast_flags) {
8620SN/A						ip->dstadr = NSRCADR(&pp->dstadr->sin);
8630SN/A						if (!ip->dstadr)
8640SN/A							ip->dstadr = NSRCADR(&pp->dstadr->bcast);
8650SN/A					}
8660SN/A				}
8670SN/A			} else
8680SN/A				ip->dstadr = 0;
8690SN/A
8700SN/A			ip->srcadr = NSRCADR(&pp->srcadr);
8710SN/A			if (client_v6_capable)
8720SN/A				ip->v6_flag = 0;
8730SN/A		}
8740SN/A		ip->srcport = NSRCPORT(&pp->srcadr);
8750SN/A		ip->flags = 0;
8760SN/A		if (pp == sys_peer)
8770SN/A			ip->flags |= INFO_FLAG_SYSPEER;
8780SN/A		if (pp->flags & FLAG_CONFIG)
8790SN/A			ip->flags |= INFO_FLAG_CONFIG;
8800SN/A		if (pp->flags & FLAG_REFCLOCK)
8810SN/A			ip->flags |= INFO_FLAG_REFCLOCK;
8820SN/A		if (pp->flags & FLAG_PREFER)
8830SN/A			ip->flags |= INFO_FLAG_PREFER;
8840SN/A		if (pp->flags & FLAG_BURST)
8850SN/A			ip->flags |= INFO_FLAG_BURST;
8860SN/A		if (pp->status == CTL_PST_SEL_SYNCCAND)
8870SN/A			ip->flags |= INFO_FLAG_SEL_CANDIDATE;
8880SN/A		if (pp->status >= CTL_PST_SEL_SYSPEER)
8890SN/A			ip->flags |= INFO_FLAG_SHORTLIST;
8900SN/A		ip->leap = pp->leap;
8910SN/A		ip->hmode = pp->hmode;
8920SN/A		ip->keyid = pp->keyid;
8930SN/A		ip->stratum = pp->stratum;
8940SN/A		ip->ppoll = pp->ppoll;
8950SN/A		ip->hpoll = pp->hpoll;
8960SN/A		ip->precision = pp->precision;
8970SN/A		ip->version = pp->version;
8980SN/A		ip->reach = pp->reach;
8990SN/A		ip->unreach = (u_char)pp->unreach;
9000SN/A		ip->flash = (u_char)pp->flash;
9010SN/A		ip->flash2 = (u_short)pp->flash;
9020SN/A		ip->estbdelay = HTONS_FP(DTOFP(pp->delay));
9030SN/A		ip->ttl = (u_char)pp->ttl;
9040SN/A		ip->associd = htons(pp->associd);
9050SN/A		ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
9060SN/A		ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp));
9070SN/A		ip->refid = pp->refid;
9080SN/A		HTONL_FP(&pp->reftime, &ip->reftime);
9090SN/A		HTONL_FP(&pp->aorg, &ip->org);
9100SN/A		HTONL_FP(&pp->rec, &ip->rec);
9110SN/A		HTONL_FP(&pp->xmt, &ip->xmt);
9120SN/A		j = pp->filter_nextpt - 1;
9130SN/A		for (i = 0; i < NTP_SHIFT; i++, j--) {
9140SN/A			if (j < 0)
9150SN/A				j = NTP_SHIFT-1;
9160SN/A			ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
9170SN/A			DTOLFP(pp->filter_offset[j], &ltmp);
9180SN/A			HTONL_FP(&ltmp, &ip->filtoffset[i]);
9190SN/A			ip->order[i] = (u_char)((pp->filter_nextpt +
9200SN/A						 NTP_SHIFT - 1) -
9210SN/A						pp->filter_order[i]);
9220SN/A			if (ip->order[i] >= NTP_SHIFT)
9230SN/A				ip->order[i] -= NTP_SHIFT;
9240SN/A		}
9250SN/A		DTOLFP(pp->offset, &ltmp);
9260SN/A		HTONL_FP(&ltmp, &ip->offset);
9270SN/A		ip->delay = HTONS_FP(DTOFP(pp->delay));
9280SN/A		ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
9290SN/A		ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
9300SN/A		ip = more_pkt();
9310SN/A	}
9320SN/A	flush_pkt();
9330SN/A}
9340SN/A
9350SN/A
9360SN/A/*
9370SN/A * peer_stats - send statistics for one or more peers
9380SN/A */
9390SN/Astatic void
9400SN/Apeer_stats (
9410SN/A	sockaddr_u *srcadr,
9420SN/A	endpt *inter,
9430SN/A	struct req_pkt *inpkt
9440SN/A	)
9450SN/A{
9460SN/A	u_short			items;
9470SN/A	size_t			item_sz;
9480SN/A	char *			datap;
9490SN/A	struct info_peer_list	ipl;
9500SN/A	struct peer *		pp;
9510SN/A	struct info_peer_stats *ip;
9520SN/A	sockaddr_u addr;
9530SN/A
9540SN/A	DPRINTF(1, ("peer_stats: called\n"));
9550SN/A	items = INFO_NITEMS(inpkt->err_nitems);
9560SN/A	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
9570SN/A	datap = inpkt->u.data;
9580SN/A	if (item_sz > sizeof(ipl)) {
9590SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
9600SN/A		return;
9610SN/A	}
9620SN/A	ip = prepare_pkt(srcadr, inter, inpkt,
9630SN/A			 v6sizeof(struct info_peer_stats));
9640SN/A	while (items-- > 0 && ip != NULL) {
9650SN/A		ZERO(ipl);
9660SN/A		memcpy(&ipl, datap, item_sz);
9670SN/A		ZERO(addr);
9680SN/A		NSRCPORT(&addr) = ipl.port;
9690SN/A		if (client_v6_capable && ipl.v6_flag) {
9700SN/A			AF(&addr) = AF_INET6;
9710SN/A			SOCK_ADDR6(&addr) = ipl.addr6;
9720SN/A		} else {
9730SN/A			AF(&addr) = AF_INET;
9740SN/A			NSRCADR(&addr) = ipl.addr;
9750SN/A		}
9760SN/A#ifdef ISC_PLATFORM_HAVESALEN
9770SN/A		addr.sa.sa_len = SOCKLEN(&addr);
9780SN/A#endif
9790SN/A		DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n",
9800SN/A			    stoa(&addr), ipl.port, NSRCPORT(&addr)));
9810SN/A
9820SN/A		datap += item_sz;
9830SN/A
9840SN/A		pp = findexistingpeer(&addr, NULL, NULL, -1, 0);
9850SN/A		if (NULL == pp)
9860SN/A			continue;
9870SN/A
9880SN/A		DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr)));
9890SN/A
9900SN/A		if (IS_IPV4(&pp->srcadr)) {
9910SN/A			if (pp->dstadr) {
9920SN/A				if (!pp->processed)
9930SN/A					ip->dstadr = NSRCADR(&pp->dstadr->sin);
9940SN/A				else {
9950SN/A					if (MDF_BCAST == pp->cast_flags)
9960SN/A						ip->dstadr = NSRCADR(&pp->dstadr->bcast);
9970SN/A					else if (pp->cast_flags) {
9980SN/A						ip->dstadr = NSRCADR(&pp->dstadr->sin);
9995520SN/A						if (!ip->dstadr)
10005520SN/A							ip->dstadr = NSRCADR(&pp->dstadr->bcast);
10010SN/A					}
10020SN/A				}
10030SN/A			} else
10045520SN/A				ip->dstadr = 0;
10055520SN/A
10065520SN/A			ip->srcadr = NSRCADR(&pp->srcadr);
10075520SN/A			if (client_v6_capable)
10085520SN/A				ip->v6_flag = 0;
10095520SN/A		} else {
10105520SN/A			if (pp->dstadr)
10115520SN/A				ip->dstadr6 =
10125520SN/A				    (MDF_BCAST == pp->cast_flags)
10130SN/A					? SOCK_ADDR6(&pp->dstadr->bcast)
10140SN/A					: SOCK_ADDR6(&pp->dstadr->sin);
10150SN/A			else
10160SN/A				ZERO(ip->dstadr6);
10170SN/A
10180SN/A			ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
10190SN/A			ip->v6_flag = 1;
10200SN/A		}
10210SN/A		ip->srcport = NSRCPORT(&pp->srcadr);
10225520SN/A		ip->flags = 0;
10235520SN/A		if (pp == sys_peer)
10245520SN/A		    ip->flags |= INFO_FLAG_SYSPEER;
10250SN/A		if (pp->flags & FLAG_CONFIG)
10260SN/A		    ip->flags |= INFO_FLAG_CONFIG;
10270SN/A		if (pp->flags & FLAG_REFCLOCK)
10280SN/A		    ip->flags |= INFO_FLAG_REFCLOCK;
10290SN/A		if (pp->flags & FLAG_PREFER)
10300SN/A		    ip->flags |= INFO_FLAG_PREFER;
10310SN/A		if (pp->flags & FLAG_BURST)
10320SN/A		    ip->flags |= INFO_FLAG_BURST;
10330SN/A		if (pp->flags & FLAG_IBURST)
10340SN/A		    ip->flags |= INFO_FLAG_IBURST;
10350SN/A		if (pp->status == CTL_PST_SEL_SYNCCAND)
103614339Sssadetsky		    ip->flags |= INFO_FLAG_SEL_CANDIDATE;
103714339Sssadetsky		if (pp->status >= CTL_PST_SEL_SYSPEER)
103814339Sssadetsky		    ip->flags |= INFO_FLAG_SHORTLIST;
103914339Sssadetsky		ip->flags = htons(ip->flags);
10400SN/A		ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
10410SN/A		ip->timetosend = htonl(pp->nextdate - current_time);
104214339Sssadetsky		ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
104314339Sssadetsky		ip->sent = htonl((u_int32)(pp->sent));
104414339Sssadetsky		ip->processed = htonl((u_int32)(pp->processed));
104514339Sssadetsky		ip->badauth = htonl((u_int32)(pp->badauth));
104614339Sssadetsky		ip->bogusorg = htonl((u_int32)(pp->bogusorg));
104714339Sssadetsky		ip->oldpkt = htonl((u_int32)(pp->oldpkt));
104814339Sssadetsky		ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
104914339Sssadetsky		ip->selbroken = htonl((u_int32)(pp->selbroken));
105014339Sssadetsky		ip->candidate = pp->status;
10510SN/A		ip = (struct info_peer_stats *)more_pkt();
10525520SN/A	}
10535520SN/A	flush_pkt();
10545520SN/A}
10555520SN/A
10565520SN/A
10575520SN/A/*
10585520SN/A * sys_info - return system info
10595520SN/A */
10605520SN/Astatic void
106114339Sssadetskysys_info(
106214339Sssadetsky	sockaddr_u *srcadr,
106314339Sssadetsky	endpt *inter,
10645520SN/A	struct req_pkt *inpkt
106514339Sssadetsky	)
106614339Sssadetsky{
106714339Sssadetsky	register struct info_sys *is;
106814339Sssadetsky
10695520SN/A	is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
10705520SN/A	    v6sizeof(struct info_sys));
10710SN/A
10720SN/A	if (sys_peer) {
10730SN/A		if (IS_IPV4(&sys_peer->srcadr)) {
10740SN/A			is->peer = NSRCADR(&sys_peer->srcadr);
10750SN/A			if (client_v6_capable)
10760SN/A				is->v6_flag = 0;
10770SN/A		} else if (client_v6_capable) {
10780SN/A			is->peer6 = SOCK_ADDR6(&sys_peer->srcadr);
10790SN/A			is->v6_flag = 1;
10800SN/A		}
10810SN/A		is->peer_mode = sys_peer->hmode;
10820SN/A	} else {
10830SN/A		is->peer = 0;
10840SN/A		if (client_v6_capable) {
10850SN/A			is->v6_flag = 0;
10860SN/A		}
10870SN/A		is->peer_mode = 0;
10880SN/A	}
10890SN/A
10900SN/A	is->leap = sys_leap;
10910SN/A	is->stratum = sys_stratum;
10920SN/A	is->precision = sys_precision;
10930SN/A	is->rootdelay = htonl(DTOFP(sys_rootdelay));
10940SN/A	is->rootdispersion = htonl(DTOUFP(sys_rootdisp));
10950SN/A	is->frequency = htonl(DTOFP(sys_jitter));
10960SN/A	is->stability = htonl(DTOUFP(clock_stability * 1e6));
10970SN/A	is->refid = sys_refid;
10980SN/A	HTONL_FP(&sys_reftime, &is->reftime);
10990SN/A
11000SN/A	is->poll = sys_poll;
11010SN/A
11020SN/A	is->flags = 0;
11030SN/A	if (sys_authenticate)
11040SN/A		is->flags |= INFO_FLAG_AUTHENTICATE;
11050SN/A	if (sys_bclient)
11060SN/A		is->flags |= INFO_FLAG_BCLIENT;
11070SN/A#ifdef REFCLOCK
11080SN/A	if (cal_enable)
11090SN/A		is->flags |= INFO_FLAG_CAL;
11100SN/A#endif /* REFCLOCK */
11110SN/A	if (kern_enable)
11120SN/A		is->flags |= INFO_FLAG_KERNEL;
11130SN/A	if (mon_enabled != MON_OFF)
11140SN/A		is->flags |= INFO_FLAG_MONITOR;
11150SN/A	if (ntp_enable)
11160SN/A		is->flags |= INFO_FLAG_NTP;
11170SN/A	if (hardpps_enable)
11180SN/A		is->flags |= INFO_FLAG_PPS_SYNC;
11190SN/A	if (stats_control)
11200SN/A		is->flags |= INFO_FLAG_FILEGEN;
11210SN/A	is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
11220SN/A	HTONL_UF(sys_authdelay.l_uf, &is->authdelay);
11230SN/A	(void) more_pkt();
11240SN/A	flush_pkt();
11250SN/A}
11260SN/A
11270SN/A
11280SN/A/*
11290SN/A * sys_stats - return system statistics
11300SN/A */
11310SN/Astatic void
11320SN/Asys_stats(
11330SN/A	sockaddr_u *srcadr,
11340SN/A	endpt *inter,
11350SN/A	struct req_pkt *inpkt
11360SN/A	)
11370SN/A{
11380SN/A	register struct info_sys_stats *ss;
11390SN/A
11400SN/A	ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
11410SN/A		sizeof(struct info_sys_stats));
11420SN/A	ss->timeup = htonl((u_int32)current_time);
11430SN/A	ss->timereset = htonl((u_int32)(current_time - sys_stattime));
11440SN/A	ss->denied = htonl((u_int32)sys_restricted);
11450SN/A	ss->oldversionpkt = htonl((u_int32)sys_oldversion);
11460SN/A	ss->newversionpkt = htonl((u_int32)sys_newversion);
11470SN/A	ss->unknownversion = htonl((u_int32)sys_declined);
11480SN/A	ss->badlength = htonl((u_int32)sys_badlength);
11490SN/A	ss->processed = htonl((u_int32)sys_processed);
11500SN/A	ss->badauth = htonl((u_int32)sys_badauth);
11510SN/A	ss->limitrejected = htonl((u_int32)sys_limitrejected);
11520SN/A	ss->received = htonl((u_int32)sys_received);
11530SN/A	(void) more_pkt();
11540SN/A	flush_pkt();
11550SN/A}
11560SN/A
11570SN/A
11580SN/A/*
11590SN/A * mem_stats - return memory statistics
11600SN/A */
11610SN/Astatic void
11620SN/Amem_stats(
11630SN/A	sockaddr_u *srcadr,
11640SN/A	endpt *inter,
11650SN/A	struct req_pkt *inpkt
11660SN/A	)
11670SN/A{
11680SN/A	register struct info_mem_stats *ms;
11690SN/A	register int i;
11700SN/A
11710SN/A	ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
11720SN/A						  sizeof(struct info_mem_stats));
11730SN/A
11740SN/A	ms->timereset = htonl((u_int32)(current_time - peer_timereset));
11750SN/A	ms->totalpeermem = htons((u_short)total_peer_structs);
11760SN/A	ms->freepeermem = htons((u_short)peer_free_count);
11770SN/A	ms->findpeer_calls = htonl((u_int32)findpeer_calls);
11780SN/A	ms->allocations = htonl((u_int32)peer_allocations);
11790SN/A	ms->demobilizations = htonl((u_int32)peer_demobilizations);
11800SN/A
11810SN/A	for (i = 0; i < NTP_HASH_SIZE; i++)
11820SN/A		ms->hashcount[i] = (u_char)
11830SN/A		    max((u_int)peer_hash_count[i], UCHAR_MAX);
11840SN/A
11850SN/A	(void) more_pkt();
11860SN/A	flush_pkt();
11870SN/A}
11880SN/A
11890SN/A
11900SN/A/*
11910SN/A * io_stats - return io statistics
11920SN/A */
11930SN/Astatic void
11940SN/Aio_stats(
11950SN/A	sockaddr_u *srcadr,
11960SN/A	endpt *inter,
11970SN/A	struct req_pkt *inpkt
11980SN/A	)
11990SN/A{
12000SN/A	struct info_io_stats *io;
12010SN/A
12020SN/A	io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
12030SN/A						 sizeof(struct info_io_stats));
12040SN/A
12050SN/A	io->timereset = htonl((u_int32)(current_time - io_timereset));
12060SN/A	io->totalrecvbufs = htons((u_short) total_recvbuffs());
12070SN/A	io->freerecvbufs = htons((u_short) free_recvbuffs());
12080SN/A	io->fullrecvbufs = htons((u_short) full_recvbuffs());
12090SN/A	io->lowwater = htons((u_short) lowater_additions());
12100SN/A	io->dropped = htonl((u_int32)packets_dropped);
12110SN/A	io->ignored = htonl((u_int32)packets_ignored);
12120SN/A	io->received = htonl((u_int32)packets_received);
12130SN/A	io->sent = htonl((u_int32)packets_sent);
12140SN/A	io->notsent = htonl((u_int32)packets_notsent);
12150SN/A	io->interrupts = htonl((u_int32)handler_calls);
12160SN/A	io->int_received = htonl((u_int32)handler_pkts);
121714339Sssadetsky
121814339Sssadetsky	(void) more_pkt();
12190SN/A	flush_pkt();
12200SN/A}
12210SN/A
12220SN/A
12230SN/A/*
12240SN/A * timer_stats - return timer statistics
12250SN/A */
12260SN/Astatic void
12270SN/Atimer_stats(
12280SN/A	sockaddr_u *		srcadr,
12290SN/A	endpt *			inter,
12300SN/A	struct req_pkt *	inpkt
12310SN/A	)
12320SN/A{
12330SN/A	struct info_timer_stats *	ts;
12340SN/A	u_long				sincereset;
12350SN/A
12360SN/A	ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter,
12370SN/A						    inpkt, sizeof(*ts));
12380SN/A
12390SN/A	sincereset = current_time - timer_timereset;
12400SN/A	ts->timereset = htonl((u_int32)sincereset);
12410SN/A	ts->alarms = ts->timereset;
12420SN/A	ts->overflows = htonl((u_int32)alarm_overflow);
12430SN/A	ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
12440SN/A
12450SN/A	(void) more_pkt();
12460SN/A	flush_pkt();
12470SN/A}
12480SN/A
12490SN/A
12500SN/A/*
12510SN/A * loop_info - return the current state of the loop filter
12520SN/A */
12530SN/Astatic void
12540SN/Aloop_info(
12550SN/A	sockaddr_u *srcadr,
12560SN/A	endpt *inter,
12570SN/A	struct req_pkt *inpkt
12580SN/A	)
12590SN/A{
12600SN/A	struct info_loop *li;
12610SN/A	l_fp ltmp;
12620SN/A
12630SN/A	li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
12640SN/A	    sizeof(struct info_loop));
12650SN/A
12660SN/A	DTOLFP(last_offset, &ltmp);
12670SN/A	HTONL_FP(&ltmp, &li->last_offset);
12680SN/A	DTOLFP(drift_comp * 1e6, &ltmp);
12690SN/A	HTONL_FP(&ltmp, &li->drift_comp);
12700SN/A	li->compliance = htonl((u_int32)(tc_counter));
12710SN/A	li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch));
12720SN/A
12730SN/A	(void) more_pkt();
12740SN/A	flush_pkt();
12750SN/A}
12760SN/A
12770SN/A
12780SN/A/*
12790SN/A * do_conf - add a peer to the configuration list
12800SN/A */
12810SN/Astatic void
12820SN/Ado_conf(
12830SN/A	sockaddr_u *srcadr,
12840SN/A	endpt *inter,
12850SN/A	struct req_pkt *inpkt
12860SN/A	)
12870SN/A{
12880SN/A	u_short			items;
12890SN/A	size_t			item_sz;
12900SN/A	u_int			fl;
12910SN/A	char *			datap;
12920SN/A	struct conf_peer	temp_cp;
12930SN/A	sockaddr_u		peeraddr;
12940SN/A
12950SN/A	/*
12960SN/A	 * Do a check of everything to see that it looks
12970SN/A	 * okay.  If not, complain about it.  Note we are
12980SN/A	 * very picky here.
12990SN/A	 */
13000SN/A	items = INFO_NITEMS(inpkt->err_nitems);
13010SN/A	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
13020SN/A	datap = inpkt->u.data;
13030SN/A	if (item_sz > sizeof(temp_cp)) {
13040SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
13050SN/A		return;
13060SN/A	}
13070SN/A
13080SN/A	while (items-- > 0) {
13090SN/A		ZERO(temp_cp);
13100SN/A		memcpy(&temp_cp, datap, item_sz);
13110SN/A		ZERO_SOCK(&peeraddr);
13120SN/A
13130SN/A		fl = 0;
13140SN/A		if (temp_cp.flags & CONF_FLAG_PREFER)
13150SN/A			fl |= FLAG_PREFER;
13160SN/A		if (temp_cp.flags & CONF_FLAG_BURST)
13170SN/A			fl |= FLAG_BURST;
13180SN/A		if (temp_cp.flags & CONF_FLAG_IBURST)
13190SN/A			fl |= FLAG_IBURST;
13200SN/A#ifdef AUTOKEY
13210SN/A		if (temp_cp.flags & CONF_FLAG_SKEY)
13220SN/A			fl |= FLAG_SKEY;
13230SN/A#endif	/* AUTOKEY */
13240SN/A		if (client_v6_capable && temp_cp.v6_flag) {
13250SN/A			AF(&peeraddr) = AF_INET6;
13260SN/A			SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
13270SN/A		} else {
13280SN/A			AF(&peeraddr) = AF_INET;
13290SN/A			NSRCADR(&peeraddr) = temp_cp.peeraddr;
13300SN/A			/*
13310SN/A			 * Make sure the address is valid
13320SN/A			 */
13330SN/A			if (!ISREFCLOCKADR(&peeraddr) &&
13340SN/A			    ISBADADR(&peeraddr)) {
13350SN/A				req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
13360SN/A				return;
13370SN/A			}
13380SN/A
13390SN/A		}
13400SN/A		NSRCPORT(&peeraddr) = htons(NTP_PORT);
13410SN/A#ifdef ISC_PLATFORM_HAVESALEN
13420SN/A		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
13430SN/A#endif
13440SN/A
13450SN/A		/* XXX W2DO? minpoll/maxpoll arguments ??? */
13460SN/A		if (peer_config(&peeraddr, NULL, NULL,
13470SN/A		    temp_cp.hmode, temp_cp.version, temp_cp.minpoll,
13480SN/A		    temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
13490SN/A		    NULL) == 0) {
13500SN/A			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
13510SN/A			return;
13520SN/A		}
13530SN/A
13540SN/A		datap += item_sz;
13550SN/A	}
13560SN/A	req_ack(srcadr, inter, inpkt, INFO_OKAY);
13570SN/A}
13580SN/A
13590SN/A
13600SN/A/*
13610SN/A * do_unconf - remove a peer from the configuration list
13620SN/A */
13630SN/Astatic void
13640SN/Ado_unconf(
13650SN/A	sockaddr_u *	srcadr,
13660SN/A	endpt *		inter,
13670SN/A	struct req_pkt *inpkt
13680SN/A	)
13690SN/A{
13700SN/A	u_short			items;
13710SN/A	size_t			item_sz;
13720SN/A	char *			datap;
13730SN/A	struct conf_unpeer	temp_cp;
137415167Sssadetsky	struct peer *		p;
13750SN/A	sockaddr_u		peeraddr;
13760SN/A	int			bad;
13770SN/A	int			found;
13780SN/A
13790SN/A	/*
13800SN/A	 * This is a bit unstructured, but I like to be careful.
138115167Sssadetsky	 * We check to see that every peer exists and is actually
13820SN/A	 * configured.  If so, we remove them.  If not, we return
13830SN/A	 * an error.
13840SN/A	 */
13850SN/A	items = INFO_NITEMS(inpkt->err_nitems);
13860SN/A	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
13870SN/A	datap = inpkt->u.data;
13880SN/A	if (item_sz > sizeof(temp_cp)) {
13890SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
13900SN/A		return;
13910SN/A	}
13920SN/A
13930SN/A	bad = FALSE;
13940SN/A	while (items-- > 0 && !bad) {
13950SN/A		ZERO(temp_cp);
13960SN/A		memcpy(&temp_cp, datap, item_sz);
13970SN/A		ZERO_SOCK(&peeraddr);
13980SN/A		if (client_v6_capable && temp_cp.v6_flag) {
13990SN/A			AF(&peeraddr) = AF_INET6;
14000SN/A			SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
14010SN/A		} else {
14020SN/A			AF(&peeraddr) = AF_INET;
14030SN/A			NSRCADR(&peeraddr) = temp_cp.peeraddr;
14040SN/A		}
14050SN/A		SET_PORT(&peeraddr, NTP_PORT);
14060SN/A#ifdef ISC_PLATFORM_HAVESALEN
14070SN/A		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
14080SN/A#endif
14090SN/A		found = FALSE;
14100SN/A		p = NULL;
14110SN/A
14120SN/A		DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
14130SN/A
14140SN/A		while (!found) {
14150SN/A			p = findexistingpeer(&peeraddr, NULL, p, -1, 0);
141615272Sssadetsky			if (NULL == p)
141715272Sssadetsky				break;
141815272Sssadetsky			if (FLAG_CONFIG & p->flags)
141915272Sssadetsky				found = TRUE;
142015272Sssadetsky		}
14210SN/A		if (!found)
142215272Sssadetsky			bad = TRUE;
14230SN/A
14240SN/A		datap += item_sz;
14250SN/A	}
14260SN/A
14270SN/A	if (bad) {
14280SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
14290SN/A		return;
14300SN/A	}
14310SN/A
14320SN/A	/*
14330SN/A	 * Now do it in earnest.
14340SN/A	 */
14350SN/A
14360SN/A	items = INFO_NITEMS(inpkt->err_nitems);
14370SN/A	datap = inpkt->u.data;
14380SN/A
14390SN/A	while (items-- > 0) {
14400SN/A		ZERO(temp_cp);
14410SN/A		memcpy(&temp_cp, datap, item_sz);
14420SN/A		ZERO(peeraddr);
14430SN/A		if (client_v6_capable && temp_cp.v6_flag) {
14440SN/A			AF(&peeraddr) = AF_INET6;
14450SN/A			SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
14460SN/A		} else {
14470SN/A			AF(&peeraddr) = AF_INET;
14480SN/A			NSRCADR(&peeraddr) = temp_cp.peeraddr;
14490SN/A		}
14500SN/A		SET_PORT(&peeraddr, NTP_PORT);
14510SN/A#ifdef ISC_PLATFORM_HAVESALEN
14520SN/A		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
14530SN/A#endif
14540SN/A		found = FALSE;
14550SN/A		p = NULL;
14560SN/A
14570SN/A		while (!found) {
14580SN/A			p = findexistingpeer(&peeraddr, NULL, p, -1, 0);
14590SN/A			if (NULL == p)
14600SN/A				break;
14610SN/A			if (FLAG_CONFIG & p->flags)
14620SN/A				found = TRUE;
14630SN/A		}
14640SN/A		INSIST(found);
14650SN/A		INSIST(NULL != p);
14660SN/A
14670SN/A		peer_clear(p, "GONE");
14680SN/A		unpeer(p);
14690SN/A
14700SN/A		datap += item_sz;
14710SN/A	}
14720SN/A
14730SN/A	req_ack(srcadr, inter, inpkt, INFO_OKAY);
14740SN/A}
14750SN/A
14760SN/A
14770SN/A/*
14780SN/A * set_sys_flag - set system flags
14790SN/A */
14800SN/Astatic void
14810SN/Aset_sys_flag(
14820SN/A	sockaddr_u *srcadr,
14830SN/A	endpt *inter,
14840SN/A	struct req_pkt *inpkt
14850SN/A	)
14860SN/A{
14870SN/A	setclr_flags(srcadr, inter, inpkt, 1);
14880SN/A}
14890SN/A
14900SN/A
14910SN/A/*
14920SN/A * clr_sys_flag - clear system flags
14930SN/A */
14940SN/Astatic void
14950SN/Aclr_sys_flag(
14960SN/A	sockaddr_u *srcadr,
14970SN/A	endpt *inter,
14989595SN/A	struct req_pkt *inpkt
14990SN/A	)
15000SN/A{
15010SN/A	setclr_flags(srcadr, inter, inpkt, 0);
15020SN/A}
15030SN/A
15040SN/A
15050SN/A/*
15060SN/A * setclr_flags - do the grunge work of flag setting/clearing
15070SN/A */
15080SN/Astatic void
15090SN/Asetclr_flags(
15100SN/A	sockaddr_u *srcadr,
15110SN/A	endpt *inter,
15120SN/A	struct req_pkt *inpkt,
15130SN/A	u_long set
15140SN/A	)
15150SN/A{
15160SN/A	struct conf_sys_flags *sf;
15170SN/A	u_int32 flags;
15180SN/A
15190SN/A	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
15200SN/A		msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
15210SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
15220SN/A		return;
15230SN/A	}
15240SN/A
15250SN/A	sf = (struct conf_sys_flags *)&inpkt->u;
15260SN/A	flags = ntohl(sf->flags);
15270SN/A
15280SN/A	if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
15290SN/A		      SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
15300SN/A		      SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
15310SN/A		msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
15320SN/A			flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
15330SN/A				  SYS_FLAG_NTP | SYS_FLAG_KERNEL |
15340SN/A				  SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
15350SN/A				  SYS_FLAG_AUTH | SYS_FLAG_CAL));
15360SN/A		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
15370SN/A		return;
15380SN/A	}
15390SN/A
15400SN/A	if (flags & SYS_FLAG_BCLIENT)
15410SN/A		proto_config(PROTO_BROADCLIENT, set, 0., NULL);
15420SN/A	if (flags & SYS_FLAG_PPS)
15430SN/A		proto_config(PROTO_PPS, set, 0., NULL);
15440SN/A	if (flags & SYS_FLAG_NTP)
15450SN/A		proto_config(PROTO_NTP, set, 0., NULL);
15460SN/A	if (flags & SYS_FLAG_KERNEL)
15470SN/A		proto_config(PROTO_KERNEL, set, 0., NULL);
15480SN/A	if (flags & SYS_FLAG_MONITOR)
15490SN/A		proto_config(PROTO_MONITOR, set, 0., NULL);
15500SN/A	if (flags & SYS_FLAG_FILEGEN)
15510SN/A		proto_config(PROTO_FILEGEN, set, 0., NULL);
15520SN/A	if (flags & SYS_FLAG_AUTH)
15530SN/A		proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
15540SN/A	if (flags & SYS_FLAG_CAL)
15550SN/A		proto_config(PROTO_CAL, set, 0., NULL);
15560SN/A	req_ack(srcadr, inter, inpkt, INFO_OKAY);
15570SN/A}
15580SN/A
15590SN/A/* There have been some issues with the restrict list processing,
15600SN/A * ranging from problems with deep recursion (resulting in stack
15610SN/A * overflows) and overfull reply buffers.
15620SN/A *
15630SN/A * To avoid this trouble the list reversal is done iteratively using a
15640SN/A * scratch pad.
15650SN/A */
15660SN/Atypedef struct RestrictStack RestrictStackT;
15679595SN/Astruct RestrictStack {
15680SN/A	RestrictStackT   *link;
15690SN/A	size_t            fcnt;
15700SN/A	const restrict_u *pres[63];
15710SN/A};
15720SN/A
15730SN/Astatic size_t
15740SN/AgetStackSheetSize(
15750SN/A	RestrictStackT *sp
15760SN/A	)
15770SN/A{
15780SN/A	if (sp)
15790SN/A		return sizeof(sp->pres)/sizeof(sp->pres[0]);
15800SN/A	return 0u;
15810SN/A}
15820SN/A
15830SN/Astatic int/*BOOL*/
15840SN/ApushRestriction(
15850SN/A	RestrictStackT  **spp,
15860SN/A	const restrict_u *ptr
15870SN/A	)
15880SN/A{
15890SN/A	RestrictStackT *sp;
15900SN/A
15910SN/A	if (NULL == (sp = *spp) || 0 == sp->fcnt) {
15920SN/A		/* need another sheet in the scratch pad */
15930SN/A		sp = emalloc(sizeof(*sp));
15940SN/A		sp->link = *spp;
15950SN/A		sp->fcnt = getStackSheetSize(sp);
15960SN/A		*spp = sp;
15970SN/A	}
15980SN/A	sp->pres[--sp->fcnt] = ptr;
15990SN/A	return TRUE;
16000SN/A}
16010SN/A
16020SN/Astatic int/*BOOL*/
16030SN/ApopRestriction(
16040SN/A	RestrictStackT   **spp,
16050SN/A	const restrict_u **opp
16060SN/A	)
1607{
1608	RestrictStackT *sp;
1609
1610	if (NULL == (sp = *spp) || sp->fcnt >= getStackSheetSize(sp))
1611		return FALSE;
1612
1613	*opp = sp->pres[sp->fcnt++];
1614	if (sp->fcnt >= getStackSheetSize(sp)) {
1615		/* discard sheet from scratch pad */
1616		*spp = sp->link;
1617		free(sp);
1618	}
1619	return TRUE;
1620}
1621
1622static void
1623flushRestrictionStack(
1624	RestrictStackT **spp
1625	)
1626{
1627	RestrictStackT *sp;
1628
1629	while (NULL != (sp = *spp)) {
1630		*spp = sp->link;
1631		free(sp);
1632	}
1633}
1634
1635/*
1636 * list_restrict4 - iterative helper for list_restrict dumps IPv4
1637 *		    restriction list in reverse order.
1638 */
1639static void
1640list_restrict4(
1641	const restrict_u *	res,
1642	struct info_restrict **	ppir
1643	)
1644{
1645	RestrictStackT *	rpad;
1646	struct info_restrict *	pir;
1647
1648	pir = *ppir;
1649	for (rpad = NULL; res; res = res->link)
1650		if (!pushRestriction(&rpad, res))
1651			break;
1652
1653	while (pir && popRestriction(&rpad, &res)) {
1654		pir->addr = htonl(res->u.v4.addr);
1655		if (client_v6_capable)
1656			pir->v6_flag = 0;
1657		pir->mask = htonl(res->u.v4.mask);
1658		pir->count = htonl(res->count);
1659		pir->flags = htons(res->flags);
1660		pir->mflags = htons(res->mflags);
1661		pir = (struct info_restrict *)more_pkt();
1662	}
1663	flushRestrictionStack(&rpad);
1664	*ppir = pir;
1665}
1666
1667/*
1668 * list_restrict6 - iterative helper for list_restrict dumps IPv6
1669 *		    restriction list in reverse order.
1670 */
1671static void
1672list_restrict6(
1673	const restrict_u *	res,
1674	struct info_restrict **	ppir
1675	)
1676{
1677	RestrictStackT *	rpad;
1678	struct info_restrict *	pir;
1679
1680	pir = *ppir;
1681	for (rpad = NULL; res; res = res->link)
1682		if (!pushRestriction(&rpad, res))
1683			break;
1684
1685	while (pir && popRestriction(&rpad, &res)) {
1686		pir->addr6 = res->u.v6.addr;
1687		pir->mask6 = res->u.v6.mask;
1688		pir->v6_flag = 1;
1689		pir->count = htonl(res->count);
1690		pir->flags = htons(res->flags);
1691		pir->mflags = htons(res->mflags);
1692		pir = (struct info_restrict *)more_pkt();
1693	}
1694	flushRestrictionStack(&rpad);
1695	*ppir = pir;
1696}
1697
1698
1699/*
1700 * list_restrict - return the restrict list
1701 */
1702static void
1703list_restrict(
1704	sockaddr_u *srcadr,
1705	endpt *inter,
1706	struct req_pkt *inpkt
1707	)
1708{
1709	struct info_restrict *ir;
1710
1711	DPRINTF(3, ("wants restrict list summary\n"));
1712
1713	ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
1714	    v6sizeof(struct info_restrict));
1715
1716	/*
1717	 * The restriction lists are kept sorted in the reverse order
1718	 * than they were originally.  To preserve the output semantics,
1719	 * dump each list in reverse order. The workers take care of that.
1720	 */
1721	list_restrict4(restrictlist4, &ir);
1722	if (client_v6_capable)
1723		list_restrict6(restrictlist6, &ir);
1724	flush_pkt();
1725}
1726
1727
1728/*
1729 * do_resaddflags - add flags to a restrict entry (or create one)
1730 */
1731static void
1732do_resaddflags(
1733	sockaddr_u *srcadr,
1734	endpt *inter,
1735	struct req_pkt *inpkt
1736	)
1737{
1738	do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
1739}
1740
1741
1742
1743/*
1744 * do_ressubflags - remove flags from a restrict entry
1745 */
1746static void
1747do_ressubflags(
1748	sockaddr_u *srcadr,
1749	endpt *inter,
1750	struct req_pkt *inpkt
1751	)
1752{
1753	do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
1754}
1755
1756
1757/*
1758 * do_unrestrict - remove a restrict entry from the list
1759 */
1760static void
1761do_unrestrict(
1762	sockaddr_u *srcadr,
1763	endpt *inter,
1764	struct req_pkt *inpkt
1765	)
1766{
1767	do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
1768}
1769
1770
1771/*
1772 * do_restrict - do the dirty stuff of dealing with restrictions
1773 */
1774static void
1775do_restrict(
1776	sockaddr_u *srcadr,
1777	endpt *inter,
1778	struct req_pkt *inpkt,
1779	int op
1780	)
1781{
1782	char *			datap;
1783	struct conf_restrict	cr;
1784	u_short			items;
1785	size_t			item_sz;
1786	sockaddr_u		matchaddr;
1787	sockaddr_u		matchmask;
1788	int			bad;
1789
1790	/*
1791	 * Do a check of the flags to make sure that only
1792	 * the NTPPORT flag is set, if any.  If not, complain
1793	 * about it.  Note we are very picky here.
1794	 */
1795	items = INFO_NITEMS(inpkt->err_nitems);
1796	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
1797	datap = inpkt->u.data;
1798	if (item_sz > sizeof(cr)) {
1799		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1800		return;
1801	}
1802
1803	bad = FALSE;
1804	while (items-- > 0 && !bad) {
1805		memcpy(&cr, datap, item_sz);
1806		cr.flags = ntohs(cr.flags);
1807		cr.mflags = ntohs(cr.mflags);
1808		if (~RESM_NTPONLY & cr.mflags)
1809			bad |= 1;
1810		if (~RES_ALLFLAGS & cr.flags)
1811			bad |= 2;
1812		if (INADDR_ANY != cr.mask) {
1813			if (client_v6_capable && cr.v6_flag) {
1814				if (IN6_IS_ADDR_UNSPECIFIED(&cr.addr6))
1815					bad |= 4;
1816			} else {
1817				if (INADDR_ANY == cr.addr)
1818					bad |= 8;
1819			}
1820		}
1821		datap += item_sz;
1822	}
1823
1824	if (bad) {
1825		msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
1826		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1827		return;
1828	}
1829
1830	/*
1831	 * Looks okay, try it out.  Needs to reload data pointer and
1832	 * item counter. (Talos-CAN-0052)
1833	 */
1834	ZERO_SOCK(&matchaddr);
1835	ZERO_SOCK(&matchmask);
1836	items = INFO_NITEMS(inpkt->err_nitems);
1837	datap = inpkt->u.data;
1838
1839	while (items-- > 0) {
1840		memcpy(&cr, datap, item_sz);
1841		cr.flags = ntohs(cr.flags);
1842		cr.mflags = ntohs(cr.mflags);
1843		if (client_v6_capable && cr.v6_flag) {
1844			AF(&matchaddr) = AF_INET6;
1845			AF(&matchmask) = AF_INET6;
1846			SOCK_ADDR6(&matchaddr) = cr.addr6;
1847			SOCK_ADDR6(&matchmask) = cr.mask6;
1848		} else {
1849			AF(&matchaddr) = AF_INET;
1850			AF(&matchmask) = AF_INET;
1851			NSRCADR(&matchaddr) = cr.addr;
1852			NSRCADR(&matchmask) = cr.mask;
1853		}
1854		hack_restrict(op, &matchaddr, &matchmask, cr.mflags,
1855			      cr.flags, 0);
1856		datap += item_sz;
1857	}
1858
1859	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1860}
1861
1862
1863/*
1864 * mon_getlist - return monitor data
1865 */
1866static void
1867mon_getlist(
1868	sockaddr_u *srcadr,
1869	endpt *inter,
1870	struct req_pkt *inpkt
1871	)
1872{
1873	req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1874}
1875
1876
1877/*
1878 * Module entry points and the flags they correspond with
1879 */
1880struct reset_entry {
1881	int flag;		/* flag this corresponds to */
1882	void (*handler)(void);	/* routine to handle request */
1883};
1884
1885struct reset_entry reset_entries[] = {
1886	{ RESET_FLAG_ALLPEERS,	peer_all_reset },
1887	{ RESET_FLAG_IO,	io_clr_stats },
1888	{ RESET_FLAG_SYS,	proto_clr_stats },
1889	{ RESET_FLAG_MEM,	peer_clr_stats },
1890	{ RESET_FLAG_TIMER,	timer_clr_stats },
1891	{ RESET_FLAG_AUTH,	reset_auth_stats },
1892	{ RESET_FLAG_CTL,	ctl_clr_stats },
1893	{ 0,			0 }
1894};
1895
1896/*
1897 * reset_stats - reset statistic counters here and there
1898 */
1899static void
1900reset_stats(
1901	sockaddr_u *srcadr,
1902	endpt *inter,
1903	struct req_pkt *inpkt
1904	)
1905{
1906	struct reset_flags *rflags;
1907	u_long flags;
1908	struct reset_entry *rent;
1909
1910	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1911		msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
1912		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1913		return;
1914	}
1915
1916	rflags = (struct reset_flags *)&inpkt->u;
1917	flags = ntohl(rflags->flags);
1918
1919	if (flags & ~RESET_ALLFLAGS) {
1920		msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
1921			flags & ~RESET_ALLFLAGS);
1922		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1923		return;
1924	}
1925
1926	for (rent = reset_entries; rent->flag != 0; rent++) {
1927		if (flags & rent->flag)
1928			(*rent->handler)();
1929	}
1930	req_ack(srcadr, inter, inpkt, INFO_OKAY);
1931}
1932
1933
1934/*
1935 * reset_peer - clear a peer's statistics
1936 */
1937static void
1938reset_peer(
1939	sockaddr_u *srcadr,
1940	endpt *inter,
1941	struct req_pkt *inpkt
1942	)
1943{
1944	u_short			items;
1945	size_t			item_sz;
1946	char *			datap;
1947	struct conf_unpeer	cp;
1948	struct peer *		p;
1949	sockaddr_u		peeraddr;
1950	int			bad;
1951
1952	/*
1953	 * We check first to see that every peer exists.  If not,
1954	 * we return an error.
1955	 */
1956
1957	items = INFO_NITEMS(inpkt->err_nitems);
1958	item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize);
1959	datap = inpkt->u.data;
1960	if (item_sz > sizeof(cp)) {
1961		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1962		return;
1963	}
1964
1965	bad = FALSE;
1966	while (items-- > 0 && !bad) {
1967		ZERO(cp);
1968		memcpy(&cp, datap, item_sz);
1969		ZERO_SOCK(&peeraddr);
1970		if (client_v6_capable && cp.v6_flag) {
1971			AF(&peeraddr) = AF_INET6;
1972			SOCK_ADDR6(&peeraddr) = cp.peeraddr6;
1973		} else {
1974			AF(&peeraddr) = AF_INET;
1975			NSRCADR(&peeraddr) = cp.peeraddr;
1976		}
1977
1978#ifdef ISC_PLATFORM_HAVESALEN
1979		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
1980#endif
1981		p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
1982		if (NULL == p)
1983			bad++;
1984		datap += item_sz;
1985	}
1986
1987	if (bad) {
1988		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1989		return;
1990	}
1991
1992	/*
1993	 * Now do it in earnest. Needs to reload data pointer and item
1994	 * counter. (Talos-CAN-0052)
1995	 */
1996
1997	items = INFO_NITEMS(inpkt->err_nitems);
1998	datap = inpkt->u.data;
1999	while (items-- > 0) {
2000		ZERO(cp);
2001		memcpy(&cp, datap, item_sz);
2002		ZERO_SOCK(&peeraddr);
2003		if (client_v6_capable && cp.v6_flag) {
2004			AF(&peeraddr) = AF_INET6;
2005			SOCK_ADDR6(&peeraddr) = cp.peeraddr6;
2006		} else {
2007			AF(&peeraddr) = AF_INET;
2008			NSRCADR(&peeraddr) = cp.peeraddr;
2009		}
2010		SET_PORT(&peeraddr, 123);
2011#ifdef ISC_PLATFORM_HAVESALEN
2012		peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
2013#endif
2014		p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0);
2015		while (p != NULL) {
2016			peer_reset(p);
2017			p = findexistingpeer(&peeraddr, NULL, p, -1, 0);
2018		}
2019		datap += item_sz;
2020	}
2021
2022	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2023}
2024
2025
2026/*
2027 * do_key_reread - reread the encryption key file
2028 */
2029static void
2030do_key_reread(
2031	sockaddr_u *srcadr,
2032	endpt *inter,
2033	struct req_pkt *inpkt
2034	)
2035{
2036	rereadkeys();
2037	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2038}
2039
2040
2041/*
2042 * trust_key - make one or more keys trusted
2043 */
2044static void
2045trust_key(
2046	sockaddr_u *srcadr,
2047	endpt *inter,
2048	struct req_pkt *inpkt
2049	)
2050{
2051	do_trustkey(srcadr, inter, inpkt, 1);
2052}
2053
2054
2055/*
2056 * untrust_key - make one or more keys untrusted
2057 */
2058static void
2059untrust_key(
2060	sockaddr_u *srcadr,
2061	endpt *inter,
2062	struct req_pkt *inpkt
2063	)
2064{
2065	do_trustkey(srcadr, inter, inpkt, 0);
2066}
2067
2068
2069/*
2070 * do_trustkey - make keys either trustable or untrustable
2071 */
2072static void
2073do_trustkey(
2074	sockaddr_u *srcadr,
2075	endpt *inter,
2076	struct req_pkt *inpkt,
2077	u_long trust
2078	)
2079{
2080	register uint32_t *kp;
2081	register int items;
2082
2083	items = INFO_NITEMS(inpkt->err_nitems);
2084	kp = (uint32_t *)&inpkt->u;
2085	while (items-- > 0) {
2086		authtrust(*kp, trust);
2087		kp++;
2088	}
2089
2090	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2091}
2092
2093
2094/*
2095 * get_auth_info - return some stats concerning the authentication module
2096 */
2097static void
2098get_auth_info(
2099	sockaddr_u *srcadr,
2100	endpt *inter,
2101	struct req_pkt *inpkt
2102	)
2103{
2104	register struct info_auth *ia;
2105
2106	ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
2107					     sizeof(struct info_auth));
2108
2109	ia->numkeys = htonl((u_int32)authnumkeys);
2110	ia->numfreekeys = htonl((u_int32)authnumfreekeys);
2111	ia->keylookups = htonl((u_int32)authkeylookups);
2112	ia->keynotfound = htonl((u_int32)authkeynotfound);
2113	ia->encryptions = htonl((u_int32)authencryptions);
2114	ia->decryptions = htonl((u_int32)authdecryptions);
2115	ia->keyuncached = htonl((u_int32)authkeyuncached);
2116	ia->expired = htonl((u_int32)authkeyexpired);
2117	ia->timereset = htonl((u_int32)(current_time - auth_timereset));
2118
2119	(void) more_pkt();
2120	flush_pkt();
2121}
2122
2123
2124
2125/*
2126 * reset_auth_stats - reset the authentication stat counters.  Done here
2127 *		      to keep ntp-isms out of the authentication module
2128 */
2129void
2130reset_auth_stats(void)
2131{
2132	authkeylookups = 0;
2133	authkeynotfound = 0;
2134	authencryptions = 0;
2135	authdecryptions = 0;
2136	authkeyuncached = 0;
2137	auth_timereset = current_time;
2138}
2139
2140
2141/*
2142 * req_get_traps - return information about current trap holders
2143 */
2144static void
2145req_get_traps(
2146	sockaddr_u *srcadr,
2147	endpt *inter,
2148	struct req_pkt *inpkt
2149	)
2150{
2151	struct info_trap *it;
2152	struct ctl_trap *tr;
2153	size_t i;
2154
2155	if (num_ctl_traps == 0) {
2156		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2157		return;
2158	}
2159
2160	it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
2161	    v6sizeof(struct info_trap));
2162
2163	for (i = 0, tr = ctl_traps; it && i < COUNTOF(ctl_traps); i++, tr++) {
2164		if (tr->tr_flags & TRAP_INUSE) {
2165			if (IS_IPV4(&tr->tr_addr)) {
2166				if (tr->tr_localaddr == any_interface)
2167					it->local_address = 0;
2168				else
2169					it->local_address
2170					    = NSRCADR(&tr->tr_localaddr->sin);
2171				it->trap_address = NSRCADR(&tr->tr_addr);
2172				if (client_v6_capable)
2173					it->v6_flag = 0;
2174			} else {
2175				if (!client_v6_capable)
2176					continue;
2177				it->local_address6
2178				    = SOCK_ADDR6(&tr->tr_localaddr->sin);
2179				it->trap_address6 = SOCK_ADDR6(&tr->tr_addr);
2180				it->v6_flag = 1;
2181			}
2182			it->trap_port = NSRCPORT(&tr->tr_addr);
2183			it->sequence = htons(tr->tr_sequence);
2184			it->settime = htonl((u_int32)(current_time - tr->tr_settime));
2185			it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
2186			it->resets = htonl((u_int32)tr->tr_resets);
2187			it->flags = htonl((u_int32)tr->tr_flags);
2188			it = (struct info_trap *)more_pkt();
2189		}
2190	}
2191	flush_pkt();
2192}
2193
2194
2195/*
2196 * req_set_trap - configure a trap
2197 */
2198static void
2199req_set_trap(
2200	sockaddr_u *srcadr,
2201	endpt *inter,
2202	struct req_pkt *inpkt
2203	)
2204{
2205	do_setclr_trap(srcadr, inter, inpkt, 1);
2206}
2207
2208
2209
2210/*
2211 * req_clr_trap - unconfigure a trap
2212 */
2213static void
2214req_clr_trap(
2215	sockaddr_u *srcadr,
2216	endpt *inter,
2217	struct req_pkt *inpkt
2218	)
2219{
2220	do_setclr_trap(srcadr, inter, inpkt, 0);
2221}
2222
2223
2224
2225/*
2226 * do_setclr_trap - do the grunge work of (un)configuring a trap
2227 */
2228static void
2229do_setclr_trap(
2230	sockaddr_u *srcadr,
2231	endpt *inter,
2232	struct req_pkt *inpkt,
2233	int set
2234	)
2235{
2236	register struct conf_trap *ct;
2237	register endpt *linter;
2238	int res;
2239	sockaddr_u laddr;
2240
2241	/*
2242	 * Prepare sockaddr
2243	 */
2244	ZERO_SOCK(&laddr);
2245	AF(&laddr) = AF(srcadr);
2246	SET_PORT(&laddr, NTP_PORT);
2247
2248	/*
2249	 * Restrict ourselves to one item only.  This eliminates
2250	 * the error reporting problem.
2251	 */
2252	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2253		msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
2254		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2255		return;
2256	}
2257	ct = (struct conf_trap *)&inpkt->u;
2258
2259	/*
2260	 * Look for the local interface.  If none, use the default.
2261	 */
2262	if (ct->local_address == 0) {
2263		linter = any_interface;
2264	} else {
2265		if (IS_IPV4(&laddr))
2266			NSRCADR(&laddr) = ct->local_address;
2267		else
2268			SOCK_ADDR6(&laddr) = ct->local_address6;
2269		linter = findinterface(&laddr);
2270		if (NULL == linter) {
2271			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2272			return;
2273		}
2274	}
2275
2276	if (IS_IPV4(&laddr))
2277		NSRCADR(&laddr) = ct->trap_address;
2278	else
2279		SOCK_ADDR6(&laddr) = ct->trap_address6;
2280	if (ct->trap_port)
2281		NSRCPORT(&laddr) = ct->trap_port;
2282	else
2283		SET_PORT(&laddr, TRAPPORT);
2284
2285	if (set) {
2286		res = ctlsettrap(&laddr, linter, 0,
2287				 INFO_VERSION(inpkt->rm_vn_mode));
2288	} else {
2289		res = ctlclrtrap(&laddr, linter, 0);
2290	}
2291
2292	if (!res) {
2293		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2294	} else {
2295		req_ack(srcadr, inter, inpkt, INFO_OKAY);
2296	}
2297	return;
2298}
2299
2300
2301
2302/*
2303 * set_request_keyid - set the keyid used to authenticate requests
2304 */
2305static void
2306set_request_keyid(
2307	sockaddr_u *srcadr,
2308	endpt *inter,
2309	struct req_pkt *inpkt
2310	)
2311{
2312	keyid_t *pkeyid;
2313
2314	/*
2315	 * Restrict ourselves to one item only.
2316	 */
2317	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2318		msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
2319		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2320		return;
2321	}
2322
2323	pkeyid = (keyid_t *)&inpkt->u;
2324	info_auth_keyid = ntohl(*pkeyid);
2325	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2326}
2327
2328
2329
2330/*
2331 * set_control_keyid - set the keyid used to authenticate requests
2332 */
2333static void
2334set_control_keyid(
2335	sockaddr_u *srcadr,
2336	endpt *inter,
2337	struct req_pkt *inpkt
2338	)
2339{
2340	keyid_t *pkeyid;
2341
2342	/*
2343	 * Restrict ourselves to one item only.
2344	 */
2345	if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2346		msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
2347		req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2348		return;
2349	}
2350
2351	pkeyid = (keyid_t *)&inpkt->u;
2352	ctl_auth_keyid = ntohl(*pkeyid);
2353	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2354}
2355
2356
2357
2358/*
2359 * get_ctl_stats - return some stats concerning the control message module
2360 */
2361static void
2362get_ctl_stats(
2363	sockaddr_u *srcadr,
2364	endpt *inter,
2365	struct req_pkt *inpkt
2366	)
2367{
2368	register struct info_control *ic;
2369
2370	ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
2371						sizeof(struct info_control));
2372
2373	ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
2374	ic->numctlreq = htonl((u_int32)numctlreq);
2375	ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
2376	ic->numctlresponses = htonl((u_int32)numctlresponses);
2377	ic->numctlfrags = htonl((u_int32)numctlfrags);
2378	ic->numctlerrors = htonl((u_int32)numctlerrors);
2379	ic->numctltooshort = htonl((u_int32)numctltooshort);
2380	ic->numctlinputresp = htonl((u_int32)numctlinputresp);
2381	ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
2382	ic->numctlinputerr = htonl((u_int32)numctlinputerr);
2383	ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
2384	ic->numctlbadversion = htonl((u_int32)numctlbadversion);
2385	ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
2386	ic->numctlbadop = htonl((u_int32)numctlbadop);
2387	ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
2388
2389	(void) more_pkt();
2390	flush_pkt();
2391}
2392
2393
2394#ifdef KERNEL_PLL
2395/*
2396 * get_kernel_info - get kernel pll/pps information
2397 */
2398static void
2399get_kernel_info(
2400	sockaddr_u *srcadr,
2401	endpt *inter,
2402	struct req_pkt *inpkt
2403	)
2404{
2405	register struct info_kernel *ik;
2406	struct timex ntx;
2407
2408	if (!pll_control) {
2409		req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2410		return;
2411	}
2412
2413	ZERO(ntx);
2414	if (ntp_adjtime(&ntx) < 0)
2415		msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
2416	ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
2417	    sizeof(struct info_kernel));
2418
2419	/*
2420	 * pll variables
2421	 */
2422	ik->offset = htonl((u_int32)ntx.offset);
2423	ik->freq = htonl((u_int32)ntx.freq);
2424	ik->maxerror = htonl((u_int32)ntx.maxerror);
2425	ik->esterror = htonl((u_int32)ntx.esterror);
2426	ik->status = htons(ntx.status);
2427	ik->constant = htonl((u_int32)ntx.constant);
2428	ik->precision = htonl((u_int32)ntx.precision);
2429	ik->tolerance = htonl((u_int32)ntx.tolerance);
2430
2431	/*
2432	 * pps variables
2433	 */
2434	ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
2435	ik->jitter = htonl((u_int32)ntx.jitter);
2436	ik->shift = htons(ntx.shift);
2437	ik->stabil = htonl((u_int32)ntx.stabil);
2438	ik->jitcnt = htonl((u_int32)ntx.jitcnt);
2439	ik->calcnt = htonl((u_int32)ntx.calcnt);
2440	ik->errcnt = htonl((u_int32)ntx.errcnt);
2441	ik->stbcnt = htonl((u_int32)ntx.stbcnt);
2442
2443	(void) more_pkt();
2444	flush_pkt();
2445}
2446#endif /* KERNEL_PLL */
2447
2448
2449#ifdef REFCLOCK
2450/*
2451 * get_clock_info - get info about a clock
2452 */
2453static void
2454get_clock_info(
2455	sockaddr_u *srcadr,
2456	endpt *inter,
2457	struct req_pkt *inpkt
2458	)
2459{
2460	register struct info_clock *ic;
2461	register u_int32 *clkaddr;
2462	register int items;
2463	struct refclockstat clock_stat;
2464	sockaddr_u addr;
2465	l_fp ltmp;
2466
2467	ZERO_SOCK(&addr);
2468	AF(&addr) = AF_INET;
2469#ifdef ISC_PLATFORM_HAVESALEN
2470	addr.sa.sa_len = SOCKLEN(&addr);
2471#endif
2472	SET_PORT(&addr, NTP_PORT);
2473	items = INFO_NITEMS(inpkt->err_nitems);
2474	clkaddr = &inpkt->u.u32[0];
2475
2476	ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
2477					      sizeof(struct info_clock));
2478
2479	while (items-- > 0 && ic) {
2480		NSRCADR(&addr) = *clkaddr++;
2481		if (!ISREFCLOCKADR(&addr) || NULL ==
2482		    findexistingpeer(&addr, NULL, NULL, -1, 0)) {
2483			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2484			return;
2485		}
2486
2487		clock_stat.kv_list = (struct ctl_var *)0;
2488
2489		refclock_control(&addr, NULL, &clock_stat);
2490
2491		ic->clockadr = NSRCADR(&addr);
2492		ic->type = clock_stat.type;
2493		ic->flags = clock_stat.flags;
2494		ic->lastevent = clock_stat.lastevent;
2495		ic->currentstatus = clock_stat.currentstatus;
2496		ic->polls = htonl((u_int32)clock_stat.polls);
2497		ic->noresponse = htonl((u_int32)clock_stat.noresponse);
2498		ic->badformat = htonl((u_int32)clock_stat.badformat);
2499		ic->baddata = htonl((u_int32)clock_stat.baddata);
2500		ic->timestarted = htonl((u_int32)clock_stat.timereset);
2501		DTOLFP(clock_stat.fudgetime1, &ltmp);
2502		HTONL_FP(&ltmp, &ic->fudgetime1);
2503		DTOLFP(clock_stat.fudgetime2, &ltmp);
2504		HTONL_FP(&ltmp, &ic->fudgetime2);
2505		ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
2506		ic->fudgeval2 = htonl(clock_stat.fudgeval2);
2507
2508		free_varlist(clock_stat.kv_list);
2509
2510		ic = (struct info_clock *)more_pkt();
2511	}
2512	flush_pkt();
2513}
2514
2515
2516
2517/*
2518 * set_clock_fudge - get a clock's fudge factors
2519 */
2520static void
2521set_clock_fudge(
2522	sockaddr_u *srcadr,
2523	endpt *inter,
2524	struct req_pkt *inpkt
2525	)
2526{
2527	register struct conf_fudge *cf;
2528	register int items;
2529	struct refclockstat clock_stat;
2530	sockaddr_u addr;
2531	l_fp ltmp;
2532
2533	ZERO(addr);
2534	ZERO(clock_stat);
2535	items = INFO_NITEMS(inpkt->err_nitems);
2536	cf = (struct conf_fudge *)&inpkt->u;
2537
2538	while (items-- > 0) {
2539		AF(&addr) = AF_INET;
2540		NSRCADR(&addr) = cf->clockadr;
2541#ifdef ISC_PLATFORM_HAVESALEN
2542		addr.sa.sa_len = SOCKLEN(&addr);
2543#endif
2544		SET_PORT(&addr, NTP_PORT);
2545		if (!ISREFCLOCKADR(&addr) || NULL ==
2546		    findexistingpeer(&addr, NULL, NULL, -1, 0)) {
2547			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2548			return;
2549		}
2550
2551		switch(ntohl(cf->which)) {
2552		    case FUDGE_TIME1:
2553			NTOHL_FP(&cf->fudgetime, &ltmp);
2554			LFPTOD(&ltmp, clock_stat.fudgetime1);
2555			clock_stat.haveflags = CLK_HAVETIME1;
2556			break;
2557		    case FUDGE_TIME2:
2558			NTOHL_FP(&cf->fudgetime, &ltmp);
2559			LFPTOD(&ltmp, clock_stat.fudgetime2);
2560			clock_stat.haveflags = CLK_HAVETIME2;
2561			break;
2562		    case FUDGE_VAL1:
2563			clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
2564			clock_stat.haveflags = CLK_HAVEVAL1;
2565			break;
2566		    case FUDGE_VAL2:
2567			clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
2568			clock_stat.haveflags = CLK_HAVEVAL2;
2569			break;
2570		    case FUDGE_FLAGS:
2571			clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
2572			clock_stat.haveflags =
2573				(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
2574			break;
2575		    default:
2576			msyslog(LOG_ERR, "set_clock_fudge: default!");
2577			req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2578			return;
2579		}
2580
2581		refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
2582	}
2583
2584	req_ack(srcadr, inter, inpkt, INFO_OKAY);
2585}
2586#endif
2587
2588#ifdef REFCLOCK
2589/*
2590 * get_clkbug_info - get debugging info about a clock
2591 */
2592static void
2593get_clkbug_info(
2594	sockaddr_u *srcadr,
2595	endpt *inter,
2596	struct req_pkt *inpkt
2597	)
2598{
2599	register int i;
2600	register struct info_clkbug *ic;
2601	register u_int32 *clkaddr;
2602	register int items;
2603	struct refclockbug bug;
2604	sockaddr_u addr;
2605
2606	ZERO_SOCK(&addr);
2607	AF(&addr) = AF_INET;
2608#ifdef ISC_PLATFORM_HAVESALEN
2609	addr.sa.sa_len = SOCKLEN(&addr);
2610#endif
2611	SET_PORT(&addr, NTP_PORT);
2612	items = INFO_NITEMS(inpkt->err_nitems);
2613	clkaddr = (u_int32 *)&inpkt->u;
2614
2615	ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
2616					       sizeof(struct info_clkbug));
2617
2618	while (items-- > 0 && ic) {
2619		NSRCADR(&addr) = *clkaddr++;
2620		if (!ISREFCLOCKADR(&addr) || NULL ==
2621		    findexistingpeer(&addr, NULL, NULL, -1, 0)) {
2622			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2623			return;
2624		}
2625
2626		ZERO(bug);
2627		refclock_buginfo(&addr, &bug);
2628		if (bug.nvalues == 0 && bug.ntimes == 0) {
2629			req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2630			return;
2631		}
2632
2633		ic->clockadr = NSRCADR(&addr);
2634		i = bug.nvalues;
2635		if (i > NUMCBUGVALUES)
2636		    i = NUMCBUGVALUES;
2637		ic->nvalues = (u_char)i;
2638		ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
2639		while (--i >= 0)
2640		    ic->values[i] = htonl(bug.values[i]);
2641
2642		i = bug.ntimes;
2643		if (i > NUMCBUGTIMES)
2644		    i = NUMCBUGTIMES;
2645		ic->ntimes = (u_char)i;
2646		ic->stimes = htonl(bug.stimes);
2647		while (--i >= 0) {
2648			HTONL_FP(&bug.times[i], &ic->times[i]);
2649		}
2650
2651		ic = (struct info_clkbug *)more_pkt();
2652	}
2653	flush_pkt();
2654}
2655#endif
2656
2657/*
2658 * receiver of interface structures
2659 */
2660static void
2661fill_info_if_stats(void *data, interface_info_t *interface_info)
2662{
2663	struct info_if_stats **ifsp = (struct info_if_stats **)data;
2664	struct info_if_stats *ifs = *ifsp;
2665	endpt *ep = interface_info->ep;
2666
2667	if (NULL == ifs)
2668		return;
2669
2670	ZERO(*ifs);
2671
2672	if (IS_IPV6(&ep->sin)) {
2673		if (!client_v6_capable)
2674			return;
2675		ifs->v6_flag = 1;
2676		ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin);
2677		ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast);
2678		ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask);
2679	} else {
2680		ifs->v6_flag = 0;
2681		ifs->unaddr.addr = SOCK_ADDR4(&ep->sin);
2682		ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast);
2683		ifs->unmask.addr = SOCK_ADDR4(&ep->mask);
2684	}
2685	ifs->v6_flag = htonl(ifs->v6_flag);
2686	strlcpy(ifs->name, ep->name, sizeof(ifs->name));
2687	ifs->family = htons(ep->family);
2688	ifs->flags = htonl(ep->flags);
2689	ifs->last_ttl = htonl(ep->last_ttl);
2690	ifs->num_mcast = htonl(ep->num_mcast);
2691	ifs->received = htonl(ep->received);
2692	ifs->sent = htonl(ep->sent);
2693	ifs->notsent = htonl(ep->notsent);
2694	ifs->ifindex = htonl(ep->ifindex);
2695	/* scope no longer in endpt, in in6_addr typically */
2696	ifs->scopeid = ifs->ifindex;
2697	ifs->ifnum = htonl(ep->ifnum);
2698	ifs->uptime = htonl(current_time - ep->starttime);
2699	ifs->ignore_packets = ep->ignore_packets;
2700	ifs->peercnt = htonl(ep->peercnt);
2701	ifs->action = interface_info->action;
2702
2703	*ifsp = (struct info_if_stats *)more_pkt();
2704}
2705
2706/*
2707 * get_if_stats - get interface statistics
2708 */
2709static void
2710get_if_stats(
2711	sockaddr_u *srcadr,
2712	endpt *inter,
2713	struct req_pkt *inpkt
2714	)
2715{
2716	struct info_if_stats *ifs;
2717
2718	DPRINTF(3, ("wants interface statistics\n"));
2719
2720	ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2721	    v6sizeof(struct info_if_stats));
2722
2723	interface_enumerate(fill_info_if_stats, &ifs);
2724
2725	flush_pkt();
2726}
2727
2728static void
2729do_if_reload(
2730	sockaddr_u *srcadr,
2731	endpt *inter,
2732	struct req_pkt *inpkt
2733	)
2734{
2735	struct info_if_stats *ifs;
2736
2737	DPRINTF(3, ("wants interface reload\n"));
2738
2739	ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2740	    v6sizeof(struct info_if_stats));
2741
2742	interface_update(fill_info_if_stats, &ifs);
2743
2744	flush_pkt();
2745}
2746
2747