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