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