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