ntp_control.c revision 106166
1/*
2 * ntp_control.c - respond to control messages and send async traps
3 */
4
5/*
6 * $FreeBSD: head/contrib/ntp/ntpd/ntp_control.c 106166 2002-10-29 20:04:27Z roberto $
7 */
8
9#ifdef HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include "ntpd.h"
14#include "ntp_io.h"
15#include "ntp_refclock.h"
16#include "ntp_control.h"
17#include "ntp_stdlib.h"
18
19#include <stdio.h>
20#include <ctype.h>
21#include <signal.h>
22
23#include <netinet/in.h>
24#include <arpa/inet.h>
25
26#ifdef PUBKEY
27#include "ntp_crypto.h"
28#endif /* PUBKEY */
29
30/*
31 * Structure to hold request procedure information
32 */
33#define NOAUTH	0
34#define AUTH	1
35
36#define NO_REQUEST	(-1)
37
38struct ctl_proc {
39	short control_code;		/* defined request code */
40	u_short flags;			/* flags word */
41	void (*handler) P((struct recvbuf *, int)); /* handle request */
42};
43
44/*
45 * Only one flag.  Authentication required or not.
46 */
47#define NOAUTH	0
48#define AUTH	1
49
50/*
51 * Request processing routines
52 */
53static	void	ctl_error	P((int));
54static	u_short ctlclkstatus	P((struct refclockstat *));
55static	void	ctl_flushpkt	P((int));
56static	void	ctl_putdata	P((const char *, unsigned int, int));
57static	void	ctl_putstr	P((const char *, const char *,
58				    unsigned int));
59static	void	ctl_putdbl	P((const char *, double));
60static	void	ctl_putuint	P((const char *, u_long));
61static	void	ctl_puthex	P((const char *, u_long));
62static	void	ctl_putint	P((const char *, long));
63static	void	ctl_putts	P((const char *, l_fp *));
64static	void	ctl_putadr	P((const char *, u_int32));
65static	void	ctl_putid	P((const char *, char *));
66static	void	ctl_putarray	P((const char *, double *, int));
67static	void	ctl_putsys	P((int));
68static	void	ctl_putpeer	P((int, struct peer *));
69#ifdef REFCLOCK
70static	void	ctl_putclock	P((int, struct refclockstat *, int));
71#endif	/* REFCLOCK */
72static	struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
73static	u_long count_var	P((struct ctl_var *));
74static	void	control_unspec	P((struct recvbuf *, int));
75static	void	read_status	P((struct recvbuf *, int));
76static	void	read_variables	P((struct recvbuf *, int));
77static	void	write_variables P((struct recvbuf *, int));
78static	void	read_clock_status P((struct recvbuf *, int));
79static	void	write_clock_status P((struct recvbuf *, int));
80static	void	set_trap	P((struct recvbuf *, int));
81static	void	unset_trap	P((struct recvbuf *, int));
82static	struct ctl_trap *ctlfindtrap P((struct sockaddr_in *,
83				    struct interface *));
84
85static	struct ctl_proc control_codes[] = {
86	{ CTL_OP_UNSPEC,	NOAUTH, control_unspec },
87	{ CTL_OP_READSTAT,	NOAUTH, read_status },
88	{ CTL_OP_READVAR,	NOAUTH, read_variables },
89	{ CTL_OP_WRITEVAR,	AUTH,	write_variables },
90	{ CTL_OP_READCLOCK,	NOAUTH, read_clock_status },
91	{ CTL_OP_WRITECLOCK,	NOAUTH, write_clock_status },
92	{ CTL_OP_SETTRAP,	NOAUTH, set_trap },
93	{ CTL_OP_UNSETTRAP,	NOAUTH, unset_trap },
94	{ NO_REQUEST,		0 }
95};
96
97/*
98 * System variable values. The array can be indexed by the variable
99 * index to find the textual name.
100 */
101static struct ctl_var sys_var[] = {
102	{ 0,		PADDING, "" },		/* 0 */
103	{ CS_LEAP,	RW, "leap" },		/* 1 */
104	{ CS_STRATUM,	RO, "stratum" },	/* 2 */
105	{ CS_PRECISION, RO, "precision" },	/* 3 */
106	{ CS_ROOTDELAY, RO, "rootdelay" },	/* 4 */
107	{ CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
108	{ CS_REFID,	RO, "refid" },		/* 6 */
109	{ CS_REFTIME,	RO, "reftime" },	/* 7 */
110	{ CS_POLL,	RO, "poll" },		/* 8 */
111	{ CS_PEERID,	RO, "peer" },		/* 9 */
112	{ CS_STATE,	RO, "state" },		/* 10 */
113	{ CS_OFFSET,	RO, "offset" },		/* 11 */
114	{ CS_DRIFT,	RO, "frequency" },	/* 12 */
115	{ CS_JITTER,	RO, "jitter" },		/* 13 */
116	{ CS_CLOCK,	RO, "clock" },		/* 14 */
117	{ CS_PROCESSOR, RO, "processor" },	/* 15 */
118	{ CS_SYSTEM,	RO, "system" },		/* 16 */
119	{ CS_VERSION,	RO, "version" },	/* 17 */
120	{ CS_STABIL,	RO, "stability" },	/* 18 */
121	{ CS_VARLIST,	RO, "sys_var_list" },	/* 19 */
122#ifdef PUBKEY
123	{ CS_FLAGS,	RO, "flags" },		/* 20 */
124	{ CS_HOST,	RO, "hostname" },	/* 21 */
125	{ CS_PUBLIC,	RO, "publickey" },	/* 22 */
126	{ CS_CERTIF,	RO, "certificate" },	/* 23 */
127	{ CS_DHPARAMS,	RO, "params" },		/* 24 */
128	{ CS_REVTIME,	RO, "refresh" },	/* 25 */
129	{ CS_LEAPTAB,	RO, "leapseconds" },	/* 26 */
130	{ CS_TAI,	RO, "tai"},		/* 27 */
131#endif /* PUBKEY */
132	{ 0,		EOV, "" }		/* 28 */
133};
134
135static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
136
137/*
138 * System variables we print by default (in fuzzball order,
139 * more-or-less)
140 */
141static	u_char def_sys_var[] = {
142	CS_VERSION,
143	CS_PROCESSOR,
144	CS_SYSTEM,
145	CS_LEAP,
146	CS_STRATUM,
147	CS_PRECISION,
148	CS_ROOTDELAY,
149	CS_ROOTDISPERSION,
150	CS_PEERID,
151	CS_REFID,
152	CS_REFTIME,
153	CS_POLL,
154	CS_CLOCK,
155	CS_STATE,
156	CS_OFFSET,
157	CS_DRIFT,
158	CS_JITTER,
159	CS_STABIL,
160#ifdef PUBKEY
161	CS_FLAGS,
162	CS_HOST,
163	CS_CERTIF,
164	CS_DHPARAMS,
165	CS_REVTIME,
166	CS_LEAPTAB,
167#endif /* PUBKEY */
168	0
169};
170
171
172/*
173 * Peer variable list
174 */
175static struct ctl_var peer_var[] = {
176	{ 0,		PADDING, "" },		/* 0 */
177	{ CP_CONFIG,	RO, "config" },		/* 1 */
178	{ CP_AUTHENABLE, RO,	"authenable" },	/* 2 */
179	{ CP_AUTHENTIC, RO, "authentic" }, 	/* 3 */
180	{ CP_SRCADR,	RO, "srcadr" },		/* 4 */
181	{ CP_SRCPORT,	RO, "srcport" },	/* 5 */
182	{ CP_DSTADR,	RO, "dstadr" },		/* 6 */
183	{ CP_DSTPORT,	RO, "dstport" },	/* 7 */
184	{ CP_LEAP,	RO, "leap" },		/* 8 */
185	{ CP_HMODE,	RO, "hmode" },		/* 9 */
186	{ CP_STRATUM,	RO, "stratum" },	/* 10 */
187	{ CP_PPOLL,	RO, "ppoll" },		/* 11 */
188	{ CP_HPOLL,	RO, "hpoll" },		/* 12 */
189	{ CP_PRECISION,	RO, "precision" },	/* 13 */
190	{ CP_ROOTDELAY,	RO, "rootdelay" },	/* 14 */
191	{ CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
192	{ CP_REFID,	RO, "refid" },		/* 16 */
193	{ CP_REFTIME,	RO, "reftime" },	/* 17 */
194	{ CP_ORG,	RO, "org" },		/* 18 */
195	{ CP_REC,	RO, "rec" },		/* 19 */
196	{ CP_XMT,	RO, "xmt" },		/* 20 */
197	{ CP_REACH,	RO, "reach" },		/* 21 */
198	{ CP_VALID,	RO, "unreach" },	/* 22 */
199	{ CP_TIMER,	RO, "timer" },		/* 23 */
200	{ CP_DELAY,	RO, "delay" },		/* 24 */
201	{ CP_OFFSET,	RO, "offset" },		/* 25 */
202	{ CP_JITTER,	RO, "jitter" },		/* 26 */
203	{ CP_DISPERSION, RO, "dispersion" },	/* 27 */
204	{ CP_KEYID,	RO, "keyid" },		/* 28 */
205	{ CP_FILTDELAY,	RO, "filtdelay=" },	/* 29 */
206	{ CP_FILTOFFSET, RO, "filtoffset=" },	/* 30 */
207	{ CP_PMODE,	RO, "pmode" },		/* 31 */
208	{ CP_RECEIVED,	RO, "received"},	/* 32 */
209	{ CP_SENT,	RO, "sent" },		/* 33 */
210	{ CP_FILTERROR,	RO, "filtdisp=" },	/* 34 */
211	{ CP_FLASH,	RO, "flash" },		/* 35 */
212	{ CP_TTL,	RO, "ttl" },		/* 36 */
213	{ CP_TTLMAX,	RO, "ttlmax" },		/* 37 */
214	{ CP_VARLIST,	RO, "peer_var_list" },	/* 38 */
215#ifdef PUBKEY
216	{ CP_FLAGS,	RO, "flags" },		/* 38 */
217	{ CP_HOST,	RO, "hostname" },	/* 39 */
218	{ CP_PUBLIC,	RO, "publickey" },	/* 40 */
219	{ CP_CERTIF,	RO, "certificate" },	/* 41 */
220	{ CP_SESKEY,	RO, "pcookie" },	/* 42 */
221	{ CP_SASKEY,	RO, "hcookie" },	/* 43 */
222	{ CP_INITSEQ,	RO, "initsequence" },   /* 44 */
223	{ CP_INITKEY,	RO, "initkey" },	/* 45 */
224	{ CP_INITTSP,	RO, "timestamp" },	/* 46 */
225#endif /* PUBKEY */
226	{ 0,		EOV, ""  }		/* 47 */
227};
228
229
230/*
231 * Peer variables we print by default
232 */
233static u_char def_peer_var[] = {
234	CP_SRCADR,
235	CP_SRCPORT,
236	CP_DSTADR,
237	CP_DSTPORT,
238	CP_LEAP,
239	CP_STRATUM,
240	CP_PRECISION,
241	CP_ROOTDELAY,
242	CP_ROOTDISPERSION,
243	CP_REFID,
244	CP_REACH,
245	CP_VALID,
246	CP_HMODE,
247	CP_PMODE,
248	CP_HPOLL,
249	CP_PPOLL,
250	CP_FLASH,
251	CP_KEYID,
252	CP_TTL,
253	CP_TTLMAX,
254	CP_OFFSET,
255	CP_DELAY,
256	CP_DISPERSION,
257	CP_JITTER,
258	CP_REFTIME,
259	CP_ORG,
260	CP_REC,
261	CP_XMT,
262	CP_FILTDELAY,
263	CP_FILTOFFSET,
264	CP_FILTERROR,
265#ifdef PUBKEY
266	CP_FLAGS,
267	CP_HOST,
268	CP_CERTIF,
269	CP_SESKEY,
270	CP_INITSEQ,
271#endif /* PUBKEY */
272	0
273};
274
275
276#ifdef REFCLOCK
277/*
278 * Clock variable list
279 */
280static struct ctl_var clock_var[] = {
281	{ 0,		PADDING, "" },		/* 0 */
282	{ CC_TYPE,	RO, "type" },		/* 1 */
283	{ CC_TIMECODE,	RO, "timecode" },	/* 2 */
284	{ CC_POLL,	RO, "poll" },		/* 3 */
285	{ CC_NOREPLY,	RO, "noreply" },	/* 4 */
286	{ CC_BADFORMAT, RO, "badformat" },	/* 5 */
287	{ CC_BADDATA,	RO, "baddata" },	/* 6 */
288	{ CC_FUDGETIME1, RO, "fudgetime1" },	/* 7 */
289	{ CC_FUDGETIME2, RO, "fudgetime2" },	/* 8 */
290	{ CC_FUDGEVAL1, RO, "stratum" },	/* 9 */
291	{ CC_FUDGEVAL2, RO, "refid" },		/* 10 */
292	{ CC_FLAGS,	RO, "flags" },		/* 11 */
293	{ CC_DEVICE,	RO, "device" },		/* 12 */
294	{ CC_VARLIST,	RO, "clock_var_list" },	/* 13 */
295	{ 0,		EOV, ""  }		/* 14 */
296};
297
298
299/*
300 * Clock variables printed by default
301 */
302static u_char def_clock_var[] = {
303	CC_DEVICE,
304	CC_TYPE,	/* won't be output if device = known */
305	CC_TIMECODE,
306	CC_POLL,
307	CC_NOREPLY,
308	CC_BADFORMAT,
309	CC_BADDATA,
310	CC_FUDGETIME1,
311	CC_FUDGETIME2,
312	CC_FUDGEVAL1,
313	CC_FUDGEVAL2,
314	CC_FLAGS,
315	0
316};
317#endif
318
319
320/*
321 * System and processor definitions.
322 */
323#ifndef HAVE_UNAME
324# ifndef STR_SYSTEM
325#  define		STR_SYSTEM	"UNIX"
326# endif
327# ifndef STR_PROCESSOR
328#	define		STR_PROCESSOR	"unknown"
329# endif
330
331static char str_system[] = STR_SYSTEM;
332static char str_processor[] = STR_PROCESSOR;
333#else
334# include <sys/utsname.h>
335static struct utsname utsnamebuf;
336#endif /* HAVE_UNAME */
337
338/*
339 * Trap structures. We only allow a few of these, and send a copy of
340 * each async message to each live one. Traps time out after an hour, it
341 * is up to the trap receipient to keep resetting it to avoid being
342 * timed out.
343 */
344/* ntp_request.c */
345struct ctl_trap ctl_trap[CTL_MAXTRAPS];
346int num_ctl_traps;
347
348/*
349 * Type bits, for ctlsettrap() call.
350 */
351#define TRAP_TYPE_CONFIG	0	/* used by configuration code */
352#define TRAP_TYPE_PRIO		1	/* priority trap */
353#define TRAP_TYPE_NONPRIO	2	/* nonpriority trap */
354
355
356/*
357 * List relating reference clock types to control message time sources.
358 * Index by the reference clock type. This list will only be used iff
359 * the reference clock driver doesn't set peer->sstclktype to something
360 * different than CTL_SST_TS_UNSPEC.
361 */
362static u_char clocktypes[] = {
363	CTL_SST_TS_NTP, 	/* REFCLK_NONE (0) */
364	CTL_SST_TS_LOCAL,	/* REFCLK_LOCALCLOCK (1) */
365	CTL_SST_TS_UHF, 	/* REFCLK_GPS_TRAK (2) */
366	CTL_SST_TS_HF,		/* REFCLK_WWV_PST (3) */
367	CTL_SST_TS_LF,		/* REFCLK_WWVB_SPECTRACOM (4) */
368	CTL_SST_TS_UHF, 	/* REFCLK_TRUETIME (5) */
369	CTL_SST_TS_UHF, 	/* REFCLK_GOES_TRAK (6) */
370	CTL_SST_TS_HF,		/* REFCLK_CHU (7) */
371	CTL_SST_TS_LF,		/* REFCLOCK_PARSE (default) (8) */
372	CTL_SST_TS_LF,		/* REFCLK_GPS_MX4200 (9) */
373	CTL_SST_TS_UHF, 	/* REFCLK_GPS_AS2201 (10) */
374	CTL_SST_TS_UHF, 	/* REFCLK_GPS_ARBITER (11) */
375	CTL_SST_TS_UHF, 	/* REFCLK_IRIG_TPRO (12) */
376	CTL_SST_TS_ATOM,	/* REFCLK_ATOM_LEITCH (13) */
377	CTL_SST_TS_LF,		/* REFCLK_MSF_EES (14) */
378	CTL_SST_TS_UHF, 	/* REFCLK_TRUETIME (15) */
379	CTL_SST_TS_UHF, 	/* REFCLK_IRIG_BANCOMM (16) */
380	CTL_SST_TS_UHF, 	/* REFCLK_GPS_DATU (17) */
381	CTL_SST_TS_TELEPHONE,	/* REFCLK_NIST_ACTS (18) */
382	CTL_SST_TS_HF,		/* REFCLK_WWV_HEATH (19) */
383	CTL_SST_TS_UHF, 	/* REFCLK_GPS_NMEA (20) */
384	CTL_SST_TS_UHF, 	/* REFCLK_GPS_VME (21) */
385	CTL_SST_TS_ATOM,	/* REFCLK_ATOM_PPS (22) */
386	CTL_SST_TS_TELEPHONE,	/* REFCLK_PTB_ACTS (23) */
387	CTL_SST_TS_TELEPHONE,	/* REFCLK_USNO (24) */
388	CTL_SST_TS_UHF, 	/* REFCLK_TRUETIME (25) */
389	CTL_SST_TS_UHF, 	/* REFCLK_GPS_HP (26) */
390	CTL_SST_TS_TELEPHONE,	/* REFCLK_ARCRON_MSF (27) */
391	CTL_SST_TS_TELEPHONE,	/* REFCLK_SHM (28) */
392	CTL_SST_TS_UHF, 	/* REFCLK_PALISADE (29) */
393	CTL_SST_TS_UHF, 	/* REFCLK_ONCORE (30) */
394	CTL_SST_TS_UHF,		/* REFCLK_JUPITER (31) */
395	CTL_SST_TS_LF,		/* REFCLK_CHRONOLOG (32) */
396	CTL_SST_TS_LF,		/* REFCLK_DUMBCLOCK (32) */
397	CTL_SST_TS_LF,		/* REFCLK_ULINK (33) */
398	CTL_SST_TS_LF,		/* REFCLK_PCF (35) */
399	CTL_SST_TS_LF,		/* REFCLK_WWV (36) */
400	CTL_SST_TS_LF,		/* REFCLK_FG (37) */
401	CTL_SST_TS_UHF, 	/* REFCLK_HOPF_SERIAL (38) */
402	CTL_SST_TS_UHF,		/* REFCLK_HOPF_PCI (39) */
403	CTL_SST_TS_LF,		/* REFCLK_JJY (40) */
404	CTL_SST_TS_UHF,		/* REFCLK_TT560 (41) */
405	CTL_SST_TS_UHF,		/* REFCLK_ZYFER (42) */
406};
407
408
409/*
410 * Keyid used for authenticating write requests.
411 */
412keyid_t ctl_auth_keyid;
413
414/*
415 * We keep track of the last error reported by the system internally
416 */
417static	u_char ctl_sys_last_event;
418static	u_char ctl_sys_num_events;
419
420
421/*
422 * Statistic counters to keep track of requests and responses.
423 */
424u_long ctltimereset;		/* time stats reset */
425u_long numctlreq;		/* number of requests we've received */
426u_long numctlbadpkts;		/* number of bad control packets */
427u_long numctlresponses; 	/* number of resp packets sent with data */
428u_long numctlfrags; 		/* number of fragments sent */
429u_long numctlerrors;		/* number of error responses sent */
430u_long numctltooshort;		/* number of too short input packets */
431u_long numctlinputresp; 	/* number of responses on input */
432u_long numctlinputfrag; 	/* number of fragments on input */
433u_long numctlinputerr;		/* number of input pkts with err bit set */
434u_long numctlbadoffset; 	/* number of input pkts with nonzero offset */
435u_long numctlbadversion;	/* number of input pkts with unknown version */
436u_long numctldatatooshort;	/* data too short for count */
437u_long numctlbadop; 		/* bad op code found in packet */
438u_long numasyncmsgs;		/* number of async messages we've sent */
439
440/*
441 * Response packet used by these routines. Also some state information
442 * so that we can handle packet formatting within a common set of
443 * subroutines.  Note we try to enter data in place whenever possible,
444 * but the need to set the more bit correctly means we occasionally
445 * use the extra buffer and copy.
446 */
447static struct ntp_control rpkt;
448static u_char	res_version;
449static u_char	res_opcode;
450static associd_t res_associd;
451static int	res_offset;
452static u_char * datapt;
453static u_char * dataend;
454static int	datalinelen;
455static int	datanotbinflag;
456static struct sockaddr_in *rmt_addr;
457static struct interface *lcl_inter;
458
459static u_char	res_authenticate;
460static u_char	res_authokay;
461static keyid_t	res_keyid;
462
463#define MAXDATALINELEN	(72)
464
465static u_char	res_async;	/* set to 1 if this is async trap response */
466
467/*
468 * Pointers for saving state when decoding request packets
469 */
470static	char *reqpt;
471static	char *reqend;
472
473/*
474 * init_control - initialize request data
475 */
476void
477init_control(void)
478{
479	int i;
480
481#ifdef HAVE_UNAME
482	uname(&utsnamebuf);
483#endif /* HAVE_UNAME */
484
485	ctl_clr_stats();
486
487	ctl_auth_keyid = 0;
488	ctl_sys_last_event = EVNT_UNSPEC;
489	ctl_sys_num_events = 0;
490
491	num_ctl_traps = 0;
492	for (i = 0; i < CTL_MAXTRAPS; i++)
493		ctl_trap[i].tr_flags = 0;
494}
495
496
497/*
498 * ctl_error - send an error response for the current request
499 */
500static void
501ctl_error(
502	int errcode
503	)
504{
505#ifdef DEBUG
506	if (debug >= 4)
507		printf("sending control error %d\n", errcode);
508#endif
509	/*
510	 * Fill in the fields. We assume rpkt.sequence and rpkt.associd
511	 * have already been filled in.
512	 */
513	rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
514	    CTL_OP_MASK));
515	rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
516	rpkt.count = 0;
517
518	/*
519	 * send packet and bump counters
520	 */
521	if (res_authenticate && sys_authenticate) {
522		int maclen;
523
524		*(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
525		    htonl(res_keyid);
526		maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
527		    CTL_HEADER_LEN);
528		sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
529		    CTL_HEADER_LEN + maclen);
530	} else {
531		sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
532		    CTL_HEADER_LEN);
533	}
534	numctlerrors++;
535}
536
537
538/*
539 * process_control - process an incoming control message
540 */
541void
542process_control(
543	struct recvbuf *rbufp,
544	int restrict_mask
545	)
546{
547	register struct ntp_control *pkt;
548	register int req_count;
549	register int req_data;
550	register struct ctl_proc *cc;
551	int properlen;
552	int maclen;
553
554#ifdef DEBUG
555	if (debug > 2)
556		printf("in process_control()\n");
557#endif
558
559	/*
560	 * Save the addresses for error responses
561	 */
562	numctlreq++;
563	rmt_addr = &rbufp->recv_srcadr;
564	lcl_inter = rbufp->dstadr;
565	pkt = (struct ntp_control *)&rbufp->recv_pkt;
566
567	/*
568	 * If the length is less than required for the header, or
569	 * it is a response or a fragment, ignore this.
570	 */
571	if (rbufp->recv_length < CTL_HEADER_LEN
572	    || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
573	    || pkt->offset != 0) {
574#ifdef DEBUG
575		if (debug)
576			printf("invalid format in control packet\n");
577#endif
578		if (rbufp->recv_length < CTL_HEADER_LEN)
579			numctltooshort++;
580		if (pkt->r_m_e_op & CTL_RESPONSE)
581			numctlinputresp++;
582		if (pkt->r_m_e_op & CTL_MORE)
583			numctlinputfrag++;
584		if (pkt->r_m_e_op & CTL_ERROR)
585			numctlinputerr++;
586		if (pkt->offset != 0)
587			numctlbadoffset++;
588		return;
589	}
590	res_version = PKT_VERSION(pkt->li_vn_mode);
591	if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
592#ifdef DEBUG
593		if (debug)
594			printf("unknown version %d in control packet\n",
595			   res_version);
596#endif
597		numctlbadversion++;
598		return;
599	}
600
601	/*
602	 * Pull enough data from the packet to make intelligent
603	 * responses
604	 */
605	rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
606	    MODE_CONTROL);
607	res_opcode = pkt->r_m_e_op;
608	rpkt.sequence = pkt->sequence;
609	rpkt.associd = pkt->associd;
610	rpkt.status = 0;
611	res_offset = 0;
612	res_associd = htons(pkt->associd);
613	res_async = 0;
614	res_authenticate = 0;
615	res_keyid = 0;
616	res_authokay = 0;
617	req_count = (int)htons(pkt->count);
618	datanotbinflag = 0;
619	datalinelen = 0;
620	datapt = rpkt.data;
621	dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
622
623	/*
624	 * We're set up now. Make sure we've got at least enough
625	 * incoming data space to match the count.
626	 */
627	req_data = rbufp->recv_length - CTL_HEADER_LEN;
628	if (req_data < req_count || rbufp->recv_length & 0x3) {
629		ctl_error(CERR_BADFMT);
630		numctldatatooshort++;
631		return;
632	}
633
634	properlen = req_count + CTL_HEADER_LEN;
635#ifdef DEBUG
636	if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
637		printf("Packet length %d unrounded\n",
638		    rbufp->recv_length);
639#endif
640	/* round up proper len to a 8 octet boundary */
641
642	properlen = (properlen + 7) & ~7;
643	maclen = rbufp->recv_length - properlen;
644	if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
645	    maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
646	    sys_authenticate) {
647		res_authenticate = 1;
648		res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
649		    properlen));
650
651#ifdef DEBUG
652		if (debug > 2)
653			printf(
654			    "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
655			    rbufp->recv_length, properlen, res_keyid, maclen);
656#endif
657		if (!authistrusted(res_keyid)) {
658#ifdef DEBUG
659			if (debug > 2)
660				printf("invalid keyid %08x\n",
661				    res_keyid);
662#endif
663		} else if (authdecrypt(res_keyid, (u_int32 *)pkt,
664		    rbufp->recv_length - maclen, maclen)) {
665#ifdef DEBUG
666			if (debug > 2)
667				printf("authenticated okay\n");
668#endif
669			res_authokay = 1;
670		} else {
671#ifdef DEBUG
672			if (debug > 2)
673				printf("authentication failed\n");
674#endif
675			res_keyid = 0;
676		}
677	}
678
679	/*
680	 * Set up translate pointers
681	 */
682	reqpt = (char *)pkt->data;
683	reqend = reqpt + req_count;
684
685	/*
686	 * Look for the opcode processor
687	 */
688	for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
689		if (cc->control_code == res_opcode) {
690#ifdef DEBUG
691			if (debug > 2)
692				printf("opcode %d, found command handler\n",
693				    res_opcode);
694#endif
695			if (cc->flags == AUTH && (!res_authokay ||
696			    res_keyid != ctl_auth_keyid)) {
697				ctl_error(CERR_PERMISSION);
698				return;
699			}
700			(cc->handler)(rbufp, restrict_mask);
701			return;
702		}
703	}
704
705	/*
706	 * Can't find this one, return an error.
707	 */
708	numctlbadop++;
709	ctl_error(CERR_BADOP);
710	return;
711}
712
713
714/*
715 * ctlpeerstatus - return a status word for this peer
716 */
717u_short
718ctlpeerstatus(
719	register struct peer *peer
720	)
721{
722	register u_short status;
723
724	status = peer->status;
725	if (peer->flags & FLAG_CONFIG)
726		status |= CTL_PST_CONFIG;
727	if (peer->flags & FLAG_AUTHENABLE)
728		status |= CTL_PST_AUTHENABLE;
729	if (peer->flags & FLAG_AUTHENTIC)
730		status |= CTL_PST_AUTHENTIC;
731	if (peer->reach != 0)
732		status |= CTL_PST_REACH;
733	return (u_short)CTL_PEER_STATUS(status, peer->num_events,
734	    peer->last_event);
735}
736
737
738/*
739 * ctlclkstatus - return a status word for this clock
740 */
741static u_short
742ctlclkstatus(
743	struct refclockstat *this_clock
744	)
745{
746	return ((u_short)(this_clock->currentstatus) << 8) |
747	    (u_short)(this_clock->lastevent);
748}
749
750
751/*
752 * ctlsysstatus - return the system status word
753 */
754u_short
755ctlsysstatus(void)
756{
757	register u_char this_clock;
758
759	this_clock = CTL_SST_TS_UNSPEC;
760	if (sys_peer != 0) {
761		if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
762			this_clock = sys_peer->sstclktype;
763			if (pps_control)
764				this_clock |= CTL_SST_TS_PPS;
765		} else {
766			if (sys_peer->refclktype < sizeof(clocktypes))
767				this_clock =
768				    clocktypes[sys_peer->refclktype];
769			if (pps_control)
770				this_clock |= CTL_SST_TS_PPS;
771		}
772	}
773	return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
774	    ctl_sys_num_events, ctl_sys_last_event);
775}
776
777
778/*
779 * ctl_flushpkt - write out the current packet and prepare
780 *		  another if necessary.
781 */
782static void
783ctl_flushpkt(
784	int more
785	)
786{
787	int dlen;
788	int sendlen;
789
790	if (!more && datanotbinflag) {
791		/*
792		 * Big hack, output a trailing \r\n
793		 */
794		*datapt++ = '\r';
795		*datapt++ = '\n';
796	}
797	dlen = datapt - (u_char *)rpkt.data;
798	sendlen = dlen + CTL_HEADER_LEN;
799
800	/*
801	 * Pad to a multiple of 32 bits
802	 */
803	while (sendlen & 0x3) {
804		*datapt++ = '\0';
805		sendlen++;
806	}
807
808	/*
809	 * Fill in the packet with the current info
810	 */
811	rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
812	    CTL_OP_MASK));
813	rpkt.count = htons((u_short) dlen);
814	rpkt.offset = htons( (u_short) res_offset);
815	if (res_async) {
816		register int i;
817
818		for (i = 0; i < CTL_MAXTRAPS; i++) {
819			if (ctl_trap[i].tr_flags & TRAP_INUSE) {
820				rpkt.li_vn_mode =
821				    PKT_LI_VN_MODE(sys_leap,
822				    ctl_trap[i].tr_version,
823				    MODE_CONTROL);
824				rpkt.sequence =
825				    htons(ctl_trap[i].tr_sequence);
826				sendpkt(&ctl_trap[i].tr_addr,
827					ctl_trap[i].tr_localaddr, -4,
828					(struct pkt *)&rpkt, sendlen);
829				if (!more)
830					ctl_trap[i].tr_sequence++;
831				numasyncmsgs++;
832			}
833		}
834	} else {
835		if (res_authenticate && sys_authenticate) {
836			int maclen;
837			int totlen = sendlen;
838			keyid_t keyid = htonl(res_keyid);
839
840			/*
841			 * If we are going to authenticate, then there
842			 * is an additional requirement that the MAC
843			 * begin on a 64 bit boundary.
844			 */
845			while (totlen & 7) {
846				*datapt++ = '\0';
847				totlen++;
848			}
849			memcpy(datapt, &keyid, sizeof keyid);
850			maclen = authencrypt(res_keyid,
851			    (u_int32 *)&rpkt, totlen);
852			sendpkt(rmt_addr, lcl_inter, -5,
853			    (struct pkt *)&rpkt, totlen + maclen);
854		} else {
855			sendpkt(rmt_addr, lcl_inter, -6,
856			    (struct pkt *)&rpkt, sendlen);
857		}
858		if (more)
859			numctlfrags++;
860		else
861			numctlresponses++;
862	}
863
864	/*
865	 * Set us up for another go around.
866	 */
867	res_offset += dlen;
868	datapt = (u_char *)rpkt.data;
869}
870
871
872/*
873 * ctl_putdata - write data into the packet, fragmenting and starting
874 * another if this one is full.
875 */
876static void
877ctl_putdata(
878	const char *dp,
879	unsigned int dlen,
880	int bin 		/* set to 1 when data is binary */
881	)
882{
883	int overhead;
884
885	overhead = 0;
886	if (!bin) {
887		datanotbinflag = 1;
888		overhead = 3;
889		if (datapt != rpkt.data) {
890			*datapt++ = ',';
891			datalinelen++;
892			if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
893			    {
894				*datapt++ = '\r';
895				*datapt++ = '\n';
896				datalinelen = 0;
897			} else {
898				*datapt++ = ' ';
899				datalinelen++;
900			}
901		}
902	}
903
904	/*
905	 * Save room for trailing junk
906	 */
907	if (dlen + overhead + datapt > dataend) {
908		/*
909		 * Not enough room in this one, flush it out.
910		 */
911		ctl_flushpkt(CTL_MORE);
912	}
913	memmove((char *)datapt, dp, (unsigned)dlen);
914	datapt += dlen;
915	datalinelen += dlen;
916}
917
918
919/*
920 * ctl_putstr - write a tagged string into the response packet
921 */
922static void
923ctl_putstr(
924	const char *tag,
925	const char *data,
926	unsigned int len
927	)
928{
929	register char *cp;
930	register const char *cq;
931	char buffer[400];
932
933	cp = buffer;
934	cq = tag;
935	while (*cq != '\0')
936		*cp++ = *cq++;
937	if (len > 0) {
938		*cp++ = '=';
939		*cp++ = '"';
940		if (len > (int) (sizeof(buffer) - (cp - buffer) - 1))
941			len = sizeof(buffer) - (cp - buffer) - 1;
942		memmove(cp, data, (unsigned)len);
943		cp += len;
944		*cp++ = '"';
945	}
946	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
947}
948
949
950/*
951 * ctl_putdbl - write a tagged, signed double into the response packet
952 */
953static void
954ctl_putdbl(
955	const char *tag,
956	double ts
957	)
958{
959	register char *cp;
960	register const char *cq;
961	char buffer[200];
962
963	cp = buffer;
964	cq = tag;
965	while (*cq != '\0')
966		*cp++ = *cq++;
967	*cp++ = '=';
968	(void)sprintf(cp, "%.3f", ts);
969	while (*cp != '\0')
970		cp++;
971	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
972}
973
974/*
975 * ctl_putuint - write a tagged unsigned integer into the response
976 */
977static void
978ctl_putuint(
979	const char *tag,
980	u_long uval
981	)
982{
983	register char *cp;
984	register const char *cq;
985	char buffer[200];
986
987	cp = buffer;
988	cq = tag;
989	while (*cq != '\0')
990		*cp++ = *cq++;
991
992	*cp++ = '=';
993	(void) sprintf(cp, "%lu", uval);
994	while (*cp != '\0')
995		cp++;
996	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
997}
998
999
1000/*
1001 * ctl_puthex - write a tagged unsigned integer, in hex, into the response
1002 */
1003static void
1004ctl_puthex(
1005	const char *tag,
1006	u_long uval
1007	)
1008{
1009	register char *cp;
1010	register const char *cq;
1011	char buffer[200];
1012
1013	cp = buffer;
1014	cq = tag;
1015	while (*cq != '\0')
1016		*cp++ = *cq++;
1017
1018	*cp++ = '=';
1019	(void) sprintf(cp, "0x%lx", uval);
1020	while (*cp != '\0')
1021		cp++;
1022	ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
1023}
1024
1025
1026/*
1027 * ctl_putint - write a tagged signed integer into the response
1028 */
1029static void
1030ctl_putint(
1031	const char *tag,
1032	long ival
1033	)
1034{
1035	register char *cp;
1036	register const char *cq;
1037	char buffer[200];
1038
1039	cp = buffer;
1040	cq = tag;
1041	while (*cq != '\0')
1042		*cp++ = *cq++;
1043
1044	*cp++ = '=';
1045	(void) sprintf(cp, "%ld", ival);
1046	while (*cp != '\0')
1047		cp++;
1048	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1049}
1050
1051
1052/*
1053 * ctl_putts - write a tagged timestamp, in hex, into the response
1054 */
1055static void
1056ctl_putts(
1057	const char *tag,
1058	l_fp *ts
1059	)
1060{
1061	register char *cp;
1062	register const char *cq;
1063	char buffer[200];
1064
1065	cp = buffer;
1066	cq = tag;
1067	while (*cq != '\0')
1068		*cp++ = *cq++;
1069
1070	*cp++ = '=';
1071	(void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffL,
1072			   ts->l_uf & 0xffffffffL);
1073	while (*cp != '\0')
1074		cp++;
1075	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1076}
1077
1078
1079/*
1080 * ctl_putadr - write a dotted quad IP address into the response
1081 */
1082static void
1083ctl_putadr(
1084	const char *tag,
1085	u_int32 addr
1086	)
1087{
1088	register char *cp;
1089	register const char *cq;
1090	char buffer[200];
1091
1092	cp = buffer;
1093	cq = tag;
1094	while (*cq != '\0')
1095		*cp++ = *cq++;
1096
1097	*cp++ = '=';
1098	cq = numtoa(addr);
1099	while (*cq != '\0')
1100		*cp++ = *cq++;
1101	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1102}
1103
1104
1105/*
1106 * ctl_putid - write a tagged clock ID into the response
1107 */
1108static void
1109ctl_putid(
1110	const char *tag,
1111	char *id
1112	)
1113{
1114	register char *cp;
1115	register const char *cq;
1116	char buffer[200];
1117
1118	cp = buffer;
1119	cq = tag;
1120	while (*cq != '\0')
1121		*cp++ = *cq++;
1122
1123	*cp++ = '=';
1124	cq = id;
1125	while (*cq != '\0' && (cq - id) < 4)
1126		*cp++ = *cq++;
1127	ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1128}
1129
1130
1131/*
1132 * ctl_putarray - write a tagged eight element double array into the response
1133 */
1134static void
1135ctl_putarray(
1136	const char *tag,
1137	double *arr,
1138	int start
1139	)
1140{
1141	register char *cp;
1142	register const char *cq;
1143	char buffer[200];
1144	int i;
1145
1146	cp = buffer;
1147	cq = tag;
1148	while (*cq != '\0')
1149		*cp++ = *cq++;
1150	i = start;
1151	do {
1152		if (i == 0)
1153			i = NTP_SHIFT;
1154		i--;
1155		(void)sprintf(cp, " %.2f", arr[i] * 1e3);
1156		while (*cp != '\0')
1157			cp++;
1158	} while(i != start);
1159	ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1160}
1161
1162
1163/*
1164 * ctl_putsys - output a system variable
1165 */
1166static void
1167ctl_putsys(
1168	int varid
1169	)
1170{
1171	l_fp tmp;
1172#ifdef HAVE_UNAME
1173	char str[256];
1174#endif
1175
1176	switch (varid) {
1177
1178	case CS_LEAP:
1179		ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
1180		break;
1181
1182	case CS_STRATUM:
1183		ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
1184		break;
1185
1186	case CS_PRECISION:
1187		ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
1188		break;
1189
1190	case CS_ROOTDELAY:
1191		ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
1192		    1e3);
1193		break;
1194
1195	case CS_ROOTDISPERSION:
1196		ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
1197		    sys_rootdispersion * 1e3);
1198		break;
1199
1200	case CS_REFID:
1201		if (sys_stratum > 1)
1202			ctl_putadr(sys_var[CS_REFID].text, sys_refid);
1203		else
1204			ctl_putid(sys_var[CS_REFID].text,
1205			    (char *)&sys_refid);
1206		break;
1207
1208	case CS_REFTIME:
1209		ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
1210		break;
1211
1212	case CS_POLL:
1213		ctl_putuint(sys_var[CS_POLL].text, sys_poll);
1214		break;
1215
1216	case CS_PEERID:
1217		if (sys_peer == NULL)
1218			ctl_putuint(sys_var[CS_PEERID].text, 0);
1219		else
1220			ctl_putuint(sys_var[CS_PEERID].text,
1221				sys_peer->associd);
1222		break;
1223
1224	case CS_STATE:
1225		ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
1226		break;
1227
1228	case CS_OFFSET:
1229		ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
1230		break;
1231
1232	case CS_DRIFT:
1233		ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
1234		break;
1235
1236	case CS_JITTER:
1237		ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
1238		break;
1239
1240	case CS_CLOCK:
1241		get_systime(&tmp);
1242		ctl_putts(sys_var[CS_CLOCK].text, &tmp);
1243		break;
1244
1245	case CS_PROCESSOR:
1246#ifndef HAVE_UNAME
1247		ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
1248		    sizeof(str_processor) - 1);
1249#else
1250		ctl_putstr(sys_var[CS_PROCESSOR].text,
1251		    utsnamebuf.machine, strlen(utsnamebuf.machine));
1252#endif /* HAVE_UNAME */
1253		break;
1254
1255	case CS_SYSTEM:
1256#ifndef HAVE_UNAME
1257		ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
1258		    sizeof(str_system) - 1);
1259#else
1260		(void)strcpy(str, utsnamebuf.sysname);
1261		(void)strcat(str, utsnamebuf.release);
1262		ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
1263#endif /* HAVE_UNAME */
1264		break;
1265
1266	case CS_VERSION:
1267		ctl_putstr(sys_var[CS_VERSION].text, Version,
1268		    strlen(Version));
1269		break;
1270
1271	case CS_STABIL:
1272		ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
1273		    1e6);
1274		break;
1275
1276	case CS_VARLIST:
1277		{
1278			char buf[CTL_MAX_DATA_LEN];
1279			register char *s, *t, *be;
1280			register const char *ss;
1281			register int i;
1282			register struct ctl_var *k;
1283
1284			s = buf;
1285			be = buf + sizeof(buf) -
1286			    strlen(sys_var[CS_VARLIST].text) - 4;
1287			if (s > be)
1288				break;	/* really long var name */
1289
1290			strcpy(s, sys_var[CS_VARLIST].text);
1291			strcat(s, "=\"");
1292			s += strlen(s);
1293			t = s;
1294			for (k = sys_var; !(k->flags &EOV); k++) {
1295				if (k->flags & PADDING)
1296					continue;
1297				i = strlen(k->text);
1298				if (s+i+1 >= be)
1299				break;
1300
1301				if (s != t)
1302				*s++ = ',';
1303				strcpy(s, k->text);
1304				s += i;
1305			}
1306
1307			for (k = ext_sys_var; k && !(k->flags &EOV);
1308			    k++) {
1309				if (k->flags & PADDING)
1310					continue;
1311
1312				ss = k->text;
1313				if (!ss)
1314					continue;
1315
1316				while (*ss && *ss != '=')
1317					ss++;
1318				i = ss - k->text;
1319				if (s + i + 1 >= be)
1320					break;
1321
1322				if (s != t)
1323				*s++ = ',';
1324				strncpy(s, k->text,
1325				    (unsigned)i);
1326				s += i;
1327			}
1328			if (s+2 >= be)
1329				break;
1330
1331			*s++ = '"';
1332			*s = '\0';
1333
1334			ctl_putdata(buf, (unsigned)( s - buf ),
1335			    0);
1336		}
1337		break;
1338
1339#ifdef PUBKEY
1340	case CS_FLAGS:
1341		if (crypto_flags)
1342			ctl_puthex(sys_var[CS_FLAGS].text,
1343			    crypto_flags);
1344		break;
1345
1346	case CS_HOST:
1347		ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
1348			strlen(sys_hostname));
1349		if (host.fstamp != 0)
1350			ctl_putuint(sys_var[CS_PUBLIC].text,
1351			    ntohl(host.fstamp));
1352		break;
1353
1354	case CS_CERTIF:
1355		if (certif.fstamp != 0)
1356			ctl_putuint(sys_var[CS_CERTIF].text,
1357			    ntohl(certif.fstamp));
1358		break;
1359
1360	case CS_DHPARAMS:
1361		if (dhparam.fstamp != 0)
1362			ctl_putuint(sys_var[CS_DHPARAMS].text,
1363			    ntohl(dhparam.fstamp));
1364		break;
1365
1366	case CS_REVTIME:
1367		if (host.tstamp != 0)
1368			ctl_putuint(sys_var[CS_REVTIME].text,
1369			    ntohl(host.tstamp));
1370		break;
1371
1372	case CS_LEAPTAB:
1373		if (tai_leap.fstamp != 0)
1374			ctl_putuint(sys_var[CS_LEAPTAB].text,
1375			    ntohl(tai_leap.fstamp));
1376		if (sys_tai != 0)
1377			ctl_putuint(sys_var[CS_TAI].text, sys_tai);
1378		break;
1379#endif /* PUBKEY */
1380	}
1381}
1382
1383
1384/*
1385 * ctl_putpeer - output a peer variable
1386 */
1387static void
1388ctl_putpeer(
1389	int varid,
1390	struct peer *peer
1391	)
1392{
1393	switch (varid) {
1394
1395	case CP_CONFIG:
1396		ctl_putuint(peer_var[CP_CONFIG].text,
1397		    (unsigned)((peer->flags & FLAG_CONFIG) != 0));
1398		break;
1399
1400	case CP_AUTHENABLE:
1401		ctl_putuint(peer_var[CP_AUTHENABLE].text,
1402		    (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
1403		break;
1404
1405	case CP_AUTHENTIC:
1406		ctl_putuint(peer_var[CP_AUTHENTIC].text,
1407		    (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
1408		break;
1409
1410	case CP_SRCADR:
1411		ctl_putadr(peer_var[CP_SRCADR].text,
1412		    peer->srcadr.sin_addr.s_addr);
1413		break;
1414
1415	case CP_SRCPORT:
1416		ctl_putuint(peer_var[CP_SRCPORT].text,
1417		    ntohs(peer->srcadr.sin_port));
1418		break;
1419
1420	case CP_DSTADR:
1421		ctl_putadr(peer_var[CP_DSTADR].text,
1422		    peer->dstadr->sin.sin_addr.s_addr);
1423		break;
1424
1425	case CP_DSTPORT:
1426		ctl_putuint(peer_var[CP_DSTPORT].text,
1427		    (u_long)(peer->dstadr ?
1428		    ntohs(peer->dstadr->sin.sin_port) : 0));
1429		break;
1430
1431	case CP_LEAP:
1432		ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
1433		break;
1434
1435	case CP_HMODE:
1436		ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
1437		break;
1438
1439	case CP_STRATUM:
1440		ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
1441		break;
1442
1443	case CP_PPOLL:
1444		ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
1445		break;
1446
1447	case CP_HPOLL:
1448		ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
1449		break;
1450
1451	case CP_PRECISION:
1452		ctl_putint(peer_var[CP_PRECISION].text,
1453		    peer->precision);
1454		break;
1455
1456	case CP_ROOTDELAY:
1457		ctl_putdbl(peer_var[CP_ROOTDELAY].text,
1458		    peer->rootdelay * 1e3);
1459		break;
1460
1461	case CP_ROOTDISPERSION:
1462		ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
1463		    peer->rootdispersion * 1e3);
1464		break;
1465
1466	case CP_REFID:
1467		if (peer->stratum > 1) {
1468			if (peer->flags & FLAG_REFCLOCK)
1469			    ctl_putadr(peer_var[CP_REFID].text,
1470			        peer->srcadr.sin_addr.s_addr);
1471			else
1472			    ctl_putadr(peer_var[CP_REFID].text,
1473			        peer->refid);
1474		} else {
1475			ctl_putid(peer_var[CP_REFID].text,
1476			    (char *)&peer->refid);
1477		}
1478		break;
1479
1480	case CP_REFTIME:
1481		ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
1482		break;
1483
1484	case CP_ORG:
1485		ctl_putts(peer_var[CP_ORG].text, &peer->org);
1486		break;
1487
1488	case CP_REC:
1489		ctl_putts(peer_var[CP_REC].text, &peer->rec);
1490		break;
1491
1492	case CP_XMT:
1493		ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
1494		break;
1495
1496	case CP_REACH:
1497		ctl_puthex(peer_var[CP_REACH].text, peer->reach);
1498		break;
1499
1500	case CP_FLASH:
1501		ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
1502		break;
1503
1504	case CP_TTL:
1505		if (!(peer->cast_flags & MDF_ACAST))
1506			break;
1507		ctl_putint(peer_var[CP_TTL].text, peer->ttl);
1508		break;
1509
1510	case CP_TTLMAX:
1511		if (!(peer->cast_flags & (MDF_MCAST | MDF_ACAST)))
1512			break;
1513		ctl_putint(peer_var[CP_TTLMAX].text, peer->ttlmax);
1514		break;
1515
1516	case CP_VALID:
1517		ctl_putuint(peer_var[CP_VALID].text, peer->unreach);
1518		break;
1519
1520	case CP_TIMER:
1521		ctl_putuint(peer_var[CP_TIMER].text,
1522		    peer->nextdate - current_time);
1523		break;
1524
1525	case CP_DELAY:
1526		ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
1527		break;
1528
1529	case CP_OFFSET:
1530		ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
1531		    1e3);
1532		break;
1533
1534	case CP_JITTER:
1535		ctl_putdbl(peer_var[CP_JITTER].text,
1536		    SQRT(peer->jitter) * 1e3);
1537		break;
1538
1539	case CP_DISPERSION:
1540		ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
1541		    1e3);
1542		break;
1543
1544	case CP_KEYID:
1545		ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
1546		break;
1547
1548	case CP_FILTDELAY:
1549		ctl_putarray(peer_var[CP_FILTDELAY].text,
1550		    peer->filter_delay, (int)peer->filter_nextpt);
1551		break;
1552
1553	case CP_FILTOFFSET:
1554		ctl_putarray(peer_var[CP_FILTOFFSET].text,
1555		    peer->filter_offset, (int)peer->filter_nextpt);
1556		break;
1557
1558	case CP_FILTERROR:
1559		ctl_putarray(peer_var[CP_FILTERROR].text,
1560		    peer->filter_disp, (int)peer->filter_nextpt);
1561		break;
1562
1563	case CP_PMODE:
1564		ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
1565		break;
1566
1567	case CP_RECEIVED:
1568		ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
1569		break;
1570
1571	case CP_SENT:
1572		ctl_putuint(peer_var[CP_SENT].text, peer->sent);
1573		break;
1574
1575	case CP_VARLIST:
1576		{
1577			char buf[CTL_MAX_DATA_LEN];
1578			register char *s, *t, *be;
1579			register int i;
1580			register struct ctl_var *k;
1581
1582			s = buf;
1583			be = buf + sizeof(buf) -
1584			    strlen(peer_var[CP_VARLIST].text) - 4;
1585			if (s > be)
1586				break;	/* really long var name */
1587
1588			strcpy(s, peer_var[CP_VARLIST].text);
1589			strcat(s, "=\"");
1590			s += strlen(s);
1591			t = s;
1592			for (k = peer_var; !(k->flags &EOV); k++) {
1593				if (k->flags & PADDING)
1594					continue;
1595
1596				i = strlen(k->text);
1597				if (s + i + 1 >= be)
1598				break;
1599
1600				if (s != t)
1601					*s++ = ',';
1602				strcpy(s, k->text);
1603				s += i;
1604			}
1605			if (s+2 >= be)
1606				break;
1607
1608			*s++ = '"';
1609			*s = '\0';
1610			ctl_putdata(buf, (unsigned)(s - buf), 0);
1611		}
1612		break;
1613#ifdef PUBKEY
1614	case CP_FLAGS:
1615		if (peer->crypto)
1616			ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
1617		break;
1618
1619	case CP_HOST:
1620		if (peer->keystr != NULL)
1621			ctl_putstr(peer_var[CP_HOST].text, peer->keystr,
1622			    strlen(peer->keystr));
1623		if (peer->pubkey.fstamp != 0)
1624			ctl_putuint(peer_var[CP_PUBLIC].text,
1625			    peer->pubkey.fstamp);
1626		break;
1627
1628	case CP_CERTIF:
1629		if (peer->certif.fstamp != 0)
1630			ctl_putuint(peer_var[CP_CERTIF].text,
1631			    peer->certif.fstamp);
1632		break;
1633
1634	case CP_SESKEY:
1635		if (peer->pcookie.key != 0)
1636			ctl_puthex(peer_var[CP_SESKEY].text,
1637			    peer->pcookie.key);
1638		if (peer->hcookie != 0)
1639			ctl_puthex(peer_var[CP_SASKEY].text,
1640			    peer->hcookie);
1641		break;
1642
1643	case CP_INITSEQ:
1644		if (peer->recauto.key == 0)
1645			break;
1646		ctl_putint(peer_var[CP_INITSEQ].text,
1647		    peer->recauto.seq);
1648		ctl_puthex(peer_var[CP_INITKEY].text,
1649		    peer->recauto.key);
1650		ctl_putuint(peer_var[CP_INITTSP].text,
1651		    peer->recauto.tstamp);
1652		break;
1653#endif /* PUBKEY */
1654	}
1655}
1656
1657
1658#ifdef REFCLOCK
1659/*
1660 * ctl_putclock - output clock variables
1661 */
1662static void
1663ctl_putclock(
1664	int varid,
1665	struct refclockstat *clock_stat,
1666	int mustput
1667	)
1668{
1669	switch(varid) {
1670
1671	case CC_TYPE:
1672		if (mustput || clock_stat->clockdesc == NULL
1673			|| *(clock_stat->clockdesc) == '\0') {
1674			ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
1675		}
1676		break;
1677	case CC_TIMECODE:
1678		ctl_putstr(clock_var[CC_TIMECODE].text,
1679		    clock_stat->p_lastcode,
1680		    (unsigned)clock_stat->lencode);
1681		break;
1682
1683	case CC_POLL:
1684		ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
1685		break;
1686
1687	case CC_NOREPLY:
1688		ctl_putuint(clock_var[CC_NOREPLY].text,
1689		    clock_stat->noresponse);
1690		break;
1691
1692	case CC_BADFORMAT:
1693		ctl_putuint(clock_var[CC_BADFORMAT].text,
1694		    clock_stat->badformat);
1695		break;
1696
1697	case CC_BADDATA:
1698		ctl_putuint(clock_var[CC_BADDATA].text,
1699		    clock_stat->baddata);
1700		break;
1701
1702	case CC_FUDGETIME1:
1703		if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
1704			ctl_putdbl(clock_var[CC_FUDGETIME1].text,
1705			    clock_stat->fudgetime1 * 1e3);
1706		break;
1707
1708	case CC_FUDGETIME2:
1709		if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) 			ctl_putdbl(clock_var[CC_FUDGETIME2].text,
1710			    clock_stat->fudgetime2 * 1e3);
1711		break;
1712
1713	case CC_FUDGEVAL1:
1714		if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
1715			ctl_putint(clock_var[CC_FUDGEVAL1].text,
1716			    clock_stat->fudgeval1);
1717		break;
1718
1719	case CC_FUDGEVAL2:
1720		if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
1721			if (clock_stat->fudgeval1 > 1)
1722				ctl_putadr(clock_var[CC_FUDGEVAL2].text,
1723				    (u_int32)clock_stat->fudgeval2);
1724			else
1725				ctl_putid(clock_var[CC_FUDGEVAL2].text,
1726				    (char *)&clock_stat->fudgeval2);
1727		}
1728		break;
1729
1730	case CC_FLAGS:
1731		if (mustput || (clock_stat->haveflags &	(CLK_HAVEFLAG1 |
1732		    CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
1733			ctl_putuint(clock_var[CC_FLAGS].text,
1734			    clock_stat->flags);
1735		break;
1736
1737	case CC_DEVICE:
1738		if (clock_stat->clockdesc == NULL ||
1739		    *(clock_stat->clockdesc) == '\0') {
1740			if (mustput)
1741				ctl_putstr(clock_var[CC_DEVICE].text,
1742				    "", 0);
1743		} else {
1744			ctl_putstr(clock_var[CC_DEVICE].text,
1745			    clock_stat->clockdesc,
1746			    strlen(clock_stat->clockdesc));
1747		}
1748		break;
1749
1750	case CC_VARLIST:
1751		{
1752			char buf[CTL_MAX_DATA_LEN];
1753			register char *s, *t, *be;
1754			register const char *ss;
1755			register int i;
1756			register struct ctl_var *k;
1757
1758			s = buf;
1759			be = buf + sizeof(buf);
1760			if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
1761			    be)
1762				break;	/* really long var name */
1763
1764			strcpy(s, clock_var[CC_VARLIST].text);
1765			strcat(s, "=\"");
1766			s += strlen(s);
1767			t = s;
1768
1769			for (k = clock_var; !(k->flags &EOV); k++) {
1770				if (k->flags & PADDING)
1771					continue;
1772
1773				i = strlen(k->text);
1774				if (s + i + 1 >= be)
1775					break;
1776
1777				if (s != t)
1778				*s++ = ',';
1779				strcpy(s, k->text);
1780				s += i;
1781			}
1782
1783			for (k = clock_stat->kv_list; k && !(k->flags &
1784			    EOV); k++) {
1785				if (k->flags & PADDING)
1786					continue;
1787
1788				ss = k->text;
1789				if (!ss)
1790					continue;
1791
1792				while (*ss && *ss != '=')
1793					ss++;
1794				i = ss - k->text;
1795				if (s+i+1 >= be)
1796					break;
1797
1798				if (s != t)
1799					*s++ = ',';
1800				strncpy(s, k->text, (unsigned)i);
1801				s += i;
1802				*s = '\0';
1803			}
1804			if (s+2 >= be)
1805				break;
1806
1807			*s++ = '"';
1808			*s = '\0';
1809			ctl_putdata(buf, (unsigned)( s - buf ), 0);
1810		}
1811		break;
1812	}
1813}
1814#endif
1815
1816
1817
1818/*
1819 * ctl_getitem - get the next data item from the incoming packet
1820 */
1821static struct ctl_var *
1822ctl_getitem(
1823	struct ctl_var *var_list,
1824	char **data
1825	)
1826{
1827	register struct ctl_var *v;
1828	register char *cp;
1829	register char *tp;
1830	static struct ctl_var eol = { 0, EOV, };
1831	static char buf[128];
1832
1833	/*
1834	 * Delete leading commas and white space
1835	 */
1836	while (reqpt < reqend && (*reqpt == ',' ||
1837	    isspace((unsigned char)*reqpt)))
1838		reqpt++;
1839	if (reqpt >= reqend)
1840		return (0);
1841
1842	if (var_list == (struct ctl_var *)0)
1843		return (&eol);
1844
1845	/*
1846	 * Look for a first character match on the tag.  If we find
1847	 * one, see if it is a full match.
1848	 */
1849	v = var_list;
1850	cp = reqpt;
1851	while (!(v->flags & EOV)) {
1852		if (!(v->flags & PADDING) && *cp == *(v->text)) {
1853			tp = v->text;
1854			while (*tp != '\0' && *tp != '=' && cp <
1855			    reqend && *cp == *tp) {
1856				cp++;
1857				tp++;
1858			}
1859			if ((*tp == '\0') || (*tp == '=')) {
1860				while (cp < reqend && isspace((unsigned char)*cp))
1861					cp++;
1862				if (cp == reqend || *cp == ',') {
1863					buf[0] = '\0';
1864					*data = buf;
1865					if (cp < reqend)
1866						cp++;
1867					reqpt = cp;
1868					return v;
1869				}
1870				if (*cp == '=') {
1871					cp++;
1872					tp = buf;
1873					while (cp < reqend && isspace((int)*cp))
1874						cp++;
1875					while (cp < reqend && *cp != ',') {
1876						*tp++ = *cp++;
1877						if (tp >= buf + sizeof(buf))
1878							return (0);
1879					}
1880					if (cp < reqend)
1881						cp++;
1882					*tp-- = '\0';
1883					while (tp > buf) {
1884						*tp-- = '\0';
1885						if (!isspace((unsigned char)(*tp)))
1886							break;
1887					}
1888					reqpt = cp;
1889					*data = buf;
1890					return (v);
1891				}
1892			}
1893			cp = reqpt;
1894		}
1895		v++;
1896	}
1897	return v;
1898}
1899
1900
1901/*
1902 * control_unspec - response to an unspecified op-code
1903 */
1904/*ARGSUSED*/
1905static void
1906control_unspec(
1907	struct recvbuf *rbufp,
1908	int restrict_mask
1909	)
1910{
1911	struct peer *peer;
1912
1913	/*
1914	 * What is an appropriate response to an unspecified op-code?
1915	 * I return no errors and no data, unless a specified assocation
1916	 * doesn't exist.
1917	 */
1918	if (res_associd != 0) {
1919		if ((peer = findpeerbyassoc(res_associd)) == 0) {
1920			ctl_error(CERR_BADASSOC);
1921			return;
1922		}
1923		rpkt.status = htons(ctlpeerstatus(peer));
1924	} else {
1925		rpkt.status = htons(ctlsysstatus());
1926	}
1927	ctl_flushpkt(0);
1928}
1929
1930
1931/*
1932 * read_status - return either a list of associd's, or a particular
1933 * peer's status.
1934 */
1935/*ARGSUSED*/
1936static void
1937read_status(
1938	struct recvbuf *rbufp,
1939	int restrict_mask
1940	)
1941{
1942	register int i;
1943	register struct peer *peer;
1944	u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
1945
1946#ifdef DEBUG
1947	if (debug > 2)
1948		printf("read_status: ID %d\n", res_associd);
1949#endif
1950	/*
1951	 * Two choices here. If the specified association ID is
1952	 * zero we return all known assocation ID's.  Otherwise
1953	 * we return a bunch of stuff about the particular peer.
1954	 */
1955	if (res_associd == 0) {
1956		register int n;
1957
1958		n = 0;
1959		rpkt.status = htons(ctlsysstatus());
1960		for (i = 0; i < HASH_SIZE; i++) {
1961			for (peer = assoc_hash[i]; peer != 0;
1962				peer = peer->ass_next) {
1963				ass_stat[n++] = htons(peer->associd);
1964				ass_stat[n++] =
1965				    htons(ctlpeerstatus(peer));
1966				if (n ==
1967				    CTL_MAX_DATA_LEN/sizeof(u_short)) {
1968					ctl_putdata((char *)ass_stat,
1969					    n * sizeof(u_short), 1);
1970					n = 0;
1971				}
1972			}
1973		}
1974
1975		if (n != 0)
1976			ctl_putdata((char *)ass_stat, n *
1977			    sizeof(u_short), 1);
1978		ctl_flushpkt(0);
1979	} else {
1980		peer = findpeerbyassoc(res_associd);
1981		if (peer == 0) {
1982			ctl_error(CERR_BADASSOC);
1983		} else {
1984			register u_char *cp;
1985
1986			rpkt.status = htons(ctlpeerstatus(peer));
1987			if (res_authokay)
1988				peer->num_events = 0;
1989			/*
1990			 * For now, output everything we know about the
1991			 * peer. May be more selective later.
1992			 */
1993			for (cp = def_peer_var; *cp != 0; cp++)
1994				ctl_putpeer((int)*cp, peer);
1995			ctl_flushpkt(0);
1996		}
1997	}
1998}
1999
2000
2001/*
2002 * read_variables - return the variables the caller asks for
2003 */
2004/*ARGSUSED*/
2005static void
2006read_variables(
2007	struct recvbuf *rbufp,
2008	int restrict_mask
2009	)
2010{
2011	register struct ctl_var *v;
2012	register int i;
2013	char *valuep;
2014	u_char *wants;
2015	unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
2016	    1) : (CP_MAXCODE + 1);
2017	if (res_associd == 0) {
2018		/*
2019		 * Wants system variables. Figure out which he wants
2020		 * and give them to him.
2021		 */
2022		rpkt.status = htons(ctlsysstatus());
2023		if (res_authokay)
2024			ctl_sys_num_events = 0;
2025		gotvar += count_var(ext_sys_var);
2026		wants = (u_char *)emalloc(gotvar);
2027		memset((char *)wants, 0, gotvar);
2028		gotvar = 0;
2029		while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2030			if (v->flags & EOV) {
2031				if ((v = ctl_getitem(ext_sys_var,
2032				    &valuep)) != 0) {
2033					if (v->flags & EOV) {
2034						ctl_error(CERR_UNKNOWNVAR);
2035						free((char *)wants);
2036						return;
2037					}
2038					wants[CS_MAXCODE + 1 +
2039					    v->code] = 1;
2040					gotvar = 1;
2041					continue;
2042				} else {
2043					break; /* shouldn't happen ! */
2044				}
2045			}
2046			wants[v->code] = 1;
2047			gotvar = 1;
2048		}
2049		if (gotvar) {
2050			for (i = 1; i <= CS_MAXCODE; i++)
2051				if (wants[i])
2052					ctl_putsys(i);
2053			for (i = 0; ext_sys_var &&
2054			    !(ext_sys_var[i].flags & EOV); i++)
2055				if (wants[i + CS_MAXCODE + 1])
2056					ctl_putdata(ext_sys_var[i].text,
2057					    strlen(ext_sys_var[i].text),
2058					    0);
2059		} else {
2060			register u_char *cs;
2061			register struct ctl_var *kv;
2062
2063			for (cs = def_sys_var; *cs != 0; cs++)
2064				ctl_putsys((int)*cs);
2065			for (kv = ext_sys_var; kv && !(kv->flags & EOV);
2066			    kv++)
2067				if (kv->flags & DEF)
2068					ctl_putdata(kv->text,
2069					    strlen(kv->text), 0);
2070		}
2071		free((char *)wants);
2072	} else {
2073		register struct peer *peer;
2074
2075		/*
2076		 * Wants info for a particular peer. See if we know
2077		 * the guy.
2078		 */
2079		peer = findpeerbyassoc(res_associd);
2080		if (peer == 0) {
2081			ctl_error(CERR_BADASSOC);
2082			return;
2083		}
2084		rpkt.status = htons(ctlpeerstatus(peer));
2085		if (res_authokay)
2086			peer->num_events = 0;
2087		wants = (u_char *)emalloc(gotvar);
2088		memset((char*)wants, 0, gotvar);
2089		gotvar = 0;
2090		while ((v = ctl_getitem(peer_var, &valuep)) != 0) {
2091			if (v->flags & EOV) {
2092				ctl_error(CERR_UNKNOWNVAR);
2093				free((char *)wants);
2094				return;
2095			}
2096			wants[v->code] = 1;
2097			gotvar = 1;
2098		}
2099		if (gotvar) {
2100			for (i = 1; i <= CP_MAXCODE; i++)
2101				if (wants[i])
2102					ctl_putpeer(i, peer);
2103		} else {
2104			register u_char *cp;
2105
2106			for (cp = def_peer_var; *cp != 0; cp++)
2107				ctl_putpeer((int)*cp, peer);
2108		}
2109		free((char *)wants);
2110	}
2111	ctl_flushpkt(0);
2112}
2113
2114
2115/*
2116 * write_variables - write into variables. We only allow leap bit
2117 * writing this way.
2118 */
2119/*ARGSUSED*/
2120static void
2121write_variables(
2122	struct recvbuf *rbufp,
2123	int restrict_mask
2124	)
2125{
2126	register struct ctl_var *v;
2127	register int ext_var;
2128	char *valuep;
2129	long val;
2130
2131	/*
2132	 * If he's trying to write into a peer tell him no way
2133	 */
2134	if (res_associd != 0) {
2135		ctl_error(CERR_PERMISSION);
2136		return;
2137	}
2138
2139	/*
2140	 * Set status
2141	 */
2142	rpkt.status = htons(ctlsysstatus());
2143
2144	/*
2145	 * Look through the variables. Dump out at the first sign of
2146	 * trouble.
2147	 */
2148	while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
2149		ext_var = 0;
2150		if (v->flags & EOV) {
2151			if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
2152			    0) {
2153				if (v->flags & EOV) {
2154					ctl_error(CERR_UNKNOWNVAR);
2155					return;
2156				}
2157				ext_var = 1;
2158			} else {
2159				break;
2160			}
2161		}
2162		if (!(v->flags & CAN_WRITE)) {
2163			ctl_error(CERR_PERMISSION);
2164			return;
2165		}
2166		if (!ext_var && (*valuep == '\0' || !atoint(valuep,
2167		    &val))) {
2168			ctl_error(CERR_BADFMT);
2169			return;
2170		}
2171		if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
2172			ctl_error(CERR_BADVALUE);
2173			return;
2174		}
2175
2176		if (ext_var) {
2177			char *s = (char *)emalloc(strlen(v->text) +
2178			    strlen(valuep) + 2);
2179			const char *t;
2180			char *tt = s;
2181
2182			t = v->text;
2183			while (*t && *t != '=')
2184				*tt++ = *t++;
2185
2186			*tt++ = '=';
2187			strcat(tt, valuep);
2188			set_sys_var(s, strlen(s)+1, v->flags);
2189			free(s);
2190		} else {
2191			/*
2192			 * This one seems sane. Save it.
2193			 */
2194			switch(v->code) {
2195
2196			case CS_LEAP:
2197			default:
2198				ctl_error(CERR_UNSPEC); /* really */
2199				return;
2200			}
2201		}
2202	}
2203
2204	/*
2205	 * If we got anything, do it. xxx nothing to do ***
2206	 */
2207	/*
2208	  if (leapind != ~0 || leapwarn != ~0) {
2209	  	if (!leap_setleap((int)leapind, (int)leapwarn)) {
2210	  		ctl_error(CERR_PERMISSION);
2211	  		return;
2212	  	}
2213	  }
2214	*/
2215	ctl_flushpkt(0);
2216}
2217
2218
2219/*
2220 * read_clock_status - return clock radio status
2221 */
2222/*ARGSUSED*/
2223static void
2224read_clock_status(
2225	struct recvbuf *rbufp,
2226	int restrict_mask
2227	)
2228{
2229#ifndef REFCLOCK
2230	/*
2231	 * If no refclock support, no data to return
2232	 */
2233	ctl_error(CERR_BADASSOC);
2234#else
2235	register struct ctl_var *v;
2236	register int i;
2237	register struct peer *peer;
2238	char *valuep;
2239	u_char *wants;
2240	unsigned int gotvar;
2241	struct refclockstat clock_stat;
2242
2243	if (res_associd == 0) {
2244
2245		/*
2246		 * Find a clock for this jerk.	If the system peer
2247		 * is a clock use it, else search the hash tables
2248		 * for one.
2249		 */
2250		if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
2251		    {
2252			peer = sys_peer;
2253		} else {
2254			peer = 0;
2255			for (i = 0; peer == 0 && i < HASH_SIZE; i++) {
2256				for (peer = assoc_hash[i]; peer != 0;
2257					peer = peer->ass_next) {
2258					if (peer->flags & FLAG_REFCLOCK)
2259						break;
2260				}
2261			}
2262			if (peer == 0) {
2263				ctl_error(CERR_BADASSOC);
2264				return;
2265			}
2266		}
2267	} else {
2268		peer = findpeerbyassoc(res_associd);
2269		if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
2270			ctl_error(CERR_BADASSOC);
2271			return;
2272		}
2273	}
2274
2275	/*
2276	 * If we got here we have a peer which is a clock. Get his
2277	 * status.
2278	 */
2279	clock_stat.kv_list = (struct ctl_var *)0;
2280	refclock_control(&peer->srcadr, (struct refclockstat *)0,
2281	    &clock_stat);
2282
2283	/*
2284	 * Look for variables in the packet.
2285	 */
2286	rpkt.status = htons(ctlclkstatus(&clock_stat));
2287	gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
2288	wants = (u_char *)emalloc(gotvar);
2289	memset((char*)wants, 0, gotvar);
2290	gotvar = 0;
2291	while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
2292		if (v->flags & EOV) {
2293			if ((v = ctl_getitem(clock_stat.kv_list,
2294			    &valuep)) != 0) {
2295				if (v->flags & EOV) {
2296					ctl_error(CERR_UNKNOWNVAR);
2297					free((char*)wants);
2298					free_varlist(clock_stat.kv_list);
2299					return;
2300				}
2301				wants[CC_MAXCODE + 1 + v->code] = 1;
2302				gotvar = 1;
2303				continue;
2304			} else {
2305				break; /* shouldn't happen ! */
2306			}
2307		}
2308		wants[v->code] = 1;
2309		gotvar = 1;
2310	}
2311
2312	if (gotvar) {
2313		for (i = 1; i <= CC_MAXCODE; i++)
2314			if (wants[i])
2315			ctl_putclock(i, &clock_stat, 1);
2316		for (i = 0; clock_stat.kv_list &&
2317		    !(clock_stat.kv_list[i].flags & EOV); i++)
2318			if (wants[i + CC_MAXCODE + 1])
2319				ctl_putdata(clock_stat.kv_list[i].text,
2320				    strlen(clock_stat.kv_list[i].text),
2321				    0);
2322	} else {
2323		register u_char *cc;
2324		register struct ctl_var *kv;
2325
2326		for (cc = def_clock_var; *cc != 0; cc++)
2327			ctl_putclock((int)*cc, &clock_stat, 0);
2328		for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
2329		    kv++)
2330			if (kv->flags & DEF)
2331				ctl_putdata(kv->text, strlen(kv->text),
2332				    0);
2333	}
2334
2335	free((char*)wants);
2336	free_varlist(clock_stat.kv_list);
2337
2338	ctl_flushpkt(0);
2339#endif
2340}
2341
2342
2343/*
2344 * write_clock_status - we don't do this
2345 */
2346/*ARGSUSED*/
2347static void
2348write_clock_status(
2349	struct recvbuf *rbufp,
2350	int restrict_mask
2351	)
2352{
2353	ctl_error(CERR_PERMISSION);
2354}
2355
2356/*
2357 * Trap support from here on down. We send async trap messages when the
2358 * upper levels report trouble. Traps can by set either by control
2359 * messages or by configuration.
2360 */
2361/*
2362 * set_trap - set a trap in response to a control message
2363 */
2364static void
2365set_trap(
2366	struct recvbuf *rbufp,
2367	int restrict_mask
2368	)
2369{
2370	int traptype;
2371
2372	/*
2373	 * See if this guy is allowed
2374	 */
2375	if (restrict_mask & RES_NOTRAP) {
2376		ctl_error(CERR_PERMISSION);
2377		return;
2378	}
2379
2380	/*
2381	 * Determine his allowed trap type.
2382	 */
2383	traptype = TRAP_TYPE_PRIO;
2384	if (restrict_mask & RES_LPTRAP)
2385		traptype = TRAP_TYPE_NONPRIO;
2386
2387	/*
2388	 * Call ctlsettrap() to do the work.  Return
2389	 * an error if it can't assign the trap.
2390	 */
2391	if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
2392	    (int)res_version))
2393		ctl_error(CERR_NORESOURCE);
2394	ctl_flushpkt(0);
2395}
2396
2397
2398/*
2399 * unset_trap - unset a trap in response to a control message
2400 */
2401static void
2402unset_trap(
2403	struct recvbuf *rbufp,
2404	int restrict_mask
2405	)
2406{
2407	int traptype;
2408
2409	/*
2410	 * We don't prevent anyone from removing his own trap unless the
2411	 * trap is configured. Note we also must be aware of the
2412	 * possibility that restriction flags were changed since this
2413	 * guy last set his trap. Set the trap type based on this.
2414	 */
2415	traptype = TRAP_TYPE_PRIO;
2416	if (restrict_mask & RES_LPTRAP)
2417		traptype = TRAP_TYPE_NONPRIO;
2418
2419	/*
2420	 * Call ctlclrtrap() to clear this out.
2421	 */
2422	if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
2423		ctl_error(CERR_BADASSOC);
2424	ctl_flushpkt(0);
2425}
2426
2427
2428/*
2429 * ctlsettrap - called to set a trap
2430 */
2431int
2432ctlsettrap(
2433	struct sockaddr_in *raddr,
2434	struct interface *linter,
2435	int traptype,
2436	int version
2437	)
2438{
2439	register struct ctl_trap *tp;
2440	register struct ctl_trap *tptouse;
2441
2442	/*
2443	 * See if we can find this trap.  If so, we only need update
2444	 * the flags and the time.
2445	 */
2446	if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
2447		switch (traptype) {
2448
2449		case TRAP_TYPE_CONFIG:
2450			tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
2451			break;
2452
2453		case TRAP_TYPE_PRIO:
2454			if (tp->tr_flags & TRAP_CONFIGURED)
2455				return (1); /* don't change anything */
2456			tp->tr_flags = TRAP_INUSE;
2457			break;
2458
2459		case TRAP_TYPE_NONPRIO:
2460			if (tp->tr_flags & TRAP_CONFIGURED)
2461				return (1); /* don't change anything */
2462			tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
2463			break;
2464		}
2465		tp->tr_settime = current_time;
2466		tp->tr_resets++;
2467		return (1);
2468	}
2469
2470	/*
2471	 * First we heard of this guy.	Try to find a trap structure
2472	 * for him to use, clearing out lesser priority guys if we
2473	 * have to. Clear out anyone who's expired while we're at it.
2474	 */
2475	tptouse = NULL;
2476	for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2477		if ((tp->tr_flags & TRAP_INUSE) &&
2478		    !(tp->tr_flags & TRAP_CONFIGURED) &&
2479		    ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
2480			tp->tr_flags = 0;
2481			num_ctl_traps--;
2482		}
2483		if (!(tp->tr_flags & TRAP_INUSE)) {
2484			tptouse = tp;
2485		} else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
2486			switch (traptype) {
2487
2488			case TRAP_TYPE_CONFIG:
2489				if (tptouse == NULL) {
2490					tptouse = tp;
2491					break;
2492				}
2493				if (tptouse->tr_flags & TRAP_NONPRIO &&
2494				    !(tp->tr_flags & TRAP_NONPRIO))
2495					break;
2496
2497				if (!(tptouse->tr_flags & TRAP_NONPRIO)
2498				    && tp->tr_flags & TRAP_NONPRIO) {
2499					tptouse = tp;
2500					break;
2501				}
2502				if (tptouse->tr_origtime <
2503				    tp->tr_origtime)
2504					tptouse = tp;
2505				break;
2506
2507			case TRAP_TYPE_PRIO:
2508				if (tp->tr_flags & TRAP_NONPRIO) {
2509					if (tptouse == NULL ||
2510					    (tptouse->tr_flags &
2511					    TRAP_INUSE &&
2512					    tptouse->tr_origtime <
2513					    tp->tr_origtime))
2514						tptouse = tp;
2515				}
2516				break;
2517
2518			case TRAP_TYPE_NONPRIO:
2519				break;
2520			}
2521		}
2522	}
2523
2524	/*
2525	 * If we don't have room for him return an error.
2526	 */
2527	if (tptouse == NULL)
2528		return (0);
2529
2530	/*
2531	 * Set up this structure for him.
2532	 */
2533	tptouse->tr_settime = tptouse->tr_origtime = current_time;
2534	tptouse->tr_count = tptouse->tr_resets = 0;
2535	tptouse->tr_sequence = 1;
2536	tptouse->tr_addr = *raddr;
2537	tptouse->tr_localaddr = linter;
2538	tptouse->tr_version = version;
2539	tptouse->tr_flags = TRAP_INUSE;
2540	if (traptype == TRAP_TYPE_CONFIG)
2541		tptouse->tr_flags |= TRAP_CONFIGURED;
2542	else if (traptype == TRAP_TYPE_NONPRIO)
2543		tptouse->tr_flags |= TRAP_NONPRIO;
2544	num_ctl_traps++;
2545	return (1);
2546}
2547
2548
2549/*
2550 * ctlclrtrap - called to clear a trap
2551 */
2552int
2553ctlclrtrap(
2554	struct sockaddr_in *raddr,
2555	struct interface *linter,
2556	int traptype
2557	)
2558{
2559	register struct ctl_trap *tp;
2560
2561	if ((tp = ctlfindtrap(raddr, linter)) == NULL)
2562		return (0);
2563
2564	if (tp->tr_flags & TRAP_CONFIGURED
2565		&& traptype != TRAP_TYPE_CONFIG)
2566		return (0);
2567
2568	tp->tr_flags = 0;
2569	num_ctl_traps--;
2570	return (1);
2571}
2572
2573
2574/*
2575 * ctlfindtrap - find a trap given the remote and local addresses
2576 */
2577static struct ctl_trap *
2578ctlfindtrap(
2579	struct sockaddr_in *raddr,
2580	struct interface *linter
2581	)
2582{
2583	register struct ctl_trap *tp;
2584
2585	for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
2586		if (tp->tr_flags & TRAP_INUSE && NSRCADR(raddr) ==
2587		    NSRCADR(&tp->tr_addr) && NSRCPORT(raddr) ==
2588		    NSRCPORT(&tp->tr_addr) && linter ==
2589		    tp->tr_localaddr)
2590			return (tp);
2591	}
2592	return (struct ctl_trap *)NULL;
2593}
2594
2595
2596/*
2597 * report_event - report an event to the trappers
2598 */
2599void
2600report_event(
2601	int err,
2602	struct peer *peer
2603	)
2604{
2605	register int i;
2606
2607	/*
2608	 * Record error code in proper spots, but have mercy on the
2609	 * log file.
2610	 */
2611	if (!(err & PEER_EVENT)) {
2612		if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
2613			ctl_sys_num_events++;
2614		if (ctl_sys_last_event != (u_char)err) {
2615			NLOG(NLOG_SYSEVENT)
2616			    msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
2617			    eventstr(err), err,
2618			    sysstatstr(ctlsysstatus()), ctlsysstatus());
2619#ifdef DEBUG
2620			if (debug)
2621				printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
2622				    eventstr(err), err,
2623				    sysstatstr(ctlsysstatus()),
2624				    ctlsysstatus());
2625#endif
2626			ctl_sys_last_event = (u_char)err;
2627		}
2628	} else if (peer != 0) {
2629		char *src;
2630
2631#ifdef REFCLOCK
2632		if (ISREFCLOCKADR(&peer->srcadr))
2633			src = refnumtoa(peer->srcadr.sin_addr.s_addr);
2634		else
2635#endif
2636			src = ntoa(&peer->srcadr);
2637
2638		peer->last_event = (u_char)(err & ~PEER_EVENT);
2639		if (peer->num_events < CTL_PEER_MAXEVENTS)
2640			peer->num_events++;
2641		NLOG(NLOG_PEEREVENT)
2642		    msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
2643		    src, eventstr(err), err,
2644		    peerstatstr(ctlpeerstatus(peer)),
2645		    ctlpeerstatus(peer));
2646#ifdef DEBUG
2647		if (debug)
2648			printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
2649			    src, eventstr(err), err,
2650			    peerstatstr(ctlpeerstatus(peer)),
2651			    ctlpeerstatus(peer));
2652#endif
2653	} else {
2654		msyslog(LOG_ERR,
2655		    "report_event: err '%s' (0x%02x), no peer",
2656		    eventstr(err), err);
2657#ifdef DEBUG
2658		printf(
2659		    "report_event: peer event '%s' (0x%02x), no peer\n",
2660		    eventstr(err), err);
2661#endif
2662		return;
2663	}
2664
2665	/*
2666	 * If no trappers, return.
2667	 */
2668	if (num_ctl_traps <= 0)
2669		return;
2670
2671	/*
2672	 * Set up the outgoing packet variables
2673	 */
2674	res_opcode = CTL_OP_ASYNCMSG;
2675	res_offset = 0;
2676	res_async = 1;
2677	res_authenticate = 0;
2678	datapt = rpkt.data;
2679	dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
2680	if (!(err & PEER_EVENT)) {
2681		rpkt.associd = 0;
2682		rpkt.status = htons(ctlsysstatus());
2683
2684		/*
2685		 * For now, put everything we know about system
2686		 * variables. Don't send crypto strings.
2687		 */
2688		for (i = 1; i <= CS_MAXCODE; i++) {
2689#ifdef PUBKEY
2690			if (i > CS_VARLIST)
2691				continue;
2692#endif /* PUBKEY */
2693			ctl_putsys(i);
2694		}
2695#ifdef REFCLOCK
2696		/*
2697		 * for clock exception events: add clock variables to
2698		 * reflect info on exception
2699		 */
2700		if (err == EVNT_CLOCKEXCPT) {
2701			struct refclockstat clock_stat;
2702			struct ctl_var *kv;
2703
2704			clock_stat.kv_list = (struct ctl_var *)0;
2705			refclock_control(&peer->srcadr,
2706			    (struct refclockstat *)0, &clock_stat);
2707			ctl_puthex("refclockstatus",
2708			    ctlclkstatus(&clock_stat));
2709			for (i = 1; i <= CC_MAXCODE; i++)
2710				ctl_putclock(i, &clock_stat, 0);
2711			for (kv = clock_stat.kv_list; kv &&
2712			    !(kv->flags & EOV); kv++)
2713				if (kv->flags & DEF)
2714					ctl_putdata(kv->text,
2715					    strlen(kv->text), 0);
2716			free_varlist(clock_stat.kv_list);
2717		}
2718#endif /*REFCLOCK*/
2719	} else {
2720		rpkt.associd = htons(peer->associd);
2721		rpkt.status = htons(ctlpeerstatus(peer));
2722
2723		/*
2724		 * Dump it all. Later, maybe less.
2725		 */
2726		for (i = 1; i <= CP_MAXCODE; i++)
2727#ifdef PUBKEY
2728			if (i > CP_VARLIST)
2729				continue;
2730#endif /* PUBKEY */
2731			ctl_putpeer(i, peer);
2732#ifdef REFCLOCK
2733		/*
2734		 * for clock exception events: add clock variables to
2735		 * reflect info on exception
2736		 */
2737		if (err == EVNT_PEERCLOCK) {
2738			struct refclockstat clock_stat;
2739			struct ctl_var *kv;
2740
2741			clock_stat.kv_list = (struct ctl_var *)0;
2742			refclock_control(&peer->srcadr,
2743			    (struct refclockstat *)0, &clock_stat);
2744
2745			ctl_puthex("refclockstatus",
2746			    ctlclkstatus(&clock_stat));
2747
2748			for (i = 1; i <= CC_MAXCODE; i++)
2749				ctl_putclock(i, &clock_stat, 0);
2750			for (kv = clock_stat.kv_list; kv &&
2751			    !(kv->flags & EOV); kv++)
2752				if (kv->flags & DEF)
2753					ctl_putdata(kv->text,
2754					    strlen(kv->text), 0);
2755			free_varlist(clock_stat.kv_list);
2756		}
2757#endif /*REFCLOCK*/
2758	}
2759
2760	/*
2761	 * We're done, return.
2762	 */
2763	ctl_flushpkt(0);
2764}
2765
2766
2767/*
2768 * ctl_clr_stats - clear stat counters
2769 */
2770void
2771ctl_clr_stats(void)
2772{
2773	ctltimereset = current_time;
2774	numctlreq = 0;
2775	numctlbadpkts = 0;
2776	numctlresponses = 0;
2777	numctlfrags = 0;
2778	numctlerrors = 0;
2779	numctlfrags = 0;
2780	numctltooshort = 0;
2781	numctlinputresp = 0;
2782	numctlinputfrag = 0;
2783	numctlinputerr = 0;
2784	numctlbadoffset = 0;
2785	numctlbadversion = 0;
2786	numctldatatooshort = 0;
2787	numctlbadop = 0;
2788	numasyncmsgs = 0;
2789}
2790
2791static u_long
2792count_var(
2793	struct ctl_var *k
2794	)
2795{
2796	register u_long c;
2797
2798	if (!k)
2799		return (0);
2800
2801	c = 0;
2802	while (!(k++->flags & EOV))
2803		c++;
2804	return (c);
2805}
2806
2807char *
2808add_var(
2809	struct ctl_var **kv,
2810	u_long size,
2811	int def
2812	)
2813{
2814	register u_long c;
2815	register struct ctl_var *k;
2816
2817	c = count_var(*kv);
2818
2819	k = *kv;
2820	*kv  = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
2821	if (k) {
2822		memmove((char *)*kv, (char *)k,
2823		    sizeof(struct ctl_var)*c);
2824		free((char *)k);
2825	}
2826	(*kv)[c].code  = (u_short) c;
2827	(*kv)[c].text  = (char *)emalloc(size);
2828	(*kv)[c].flags = def;
2829	(*kv)[c+1].code  = 0;
2830	(*kv)[c+1].text  = (char *)0;
2831	(*kv)[c+1].flags = EOV;
2832	return (char *)(*kv)[c].text;
2833}
2834
2835void
2836set_var(
2837	struct ctl_var **kv,
2838	const char *data,
2839	u_long size,
2840	int def
2841	)
2842{
2843	register struct ctl_var *k;
2844	register const char *s;
2845	register const char *t;
2846	char *td;
2847
2848	if (!data || !size)
2849		return;
2850
2851	if ((k = *kv)) {
2852		while (!(k->flags & EOV)) {
2853			s = data;
2854			t = k->text;
2855			if (t)	{
2856				while (*t != '=' && *s - *t == 0) {
2857					s++;
2858					t++;
2859				}
2860				if (*s == *t && ((*t == '=') || !*t)) {
2861					free((void *)k->text);
2862					td = (char *)emalloc(size);
2863					memmove(td, data, size);
2864					k->text =td;
2865					k->flags = def;
2866					return;
2867				}
2868			} else {
2869				td = (char *)emalloc(size);
2870				memmove(td, data, size);
2871				k->text = td;
2872				k->flags = def;
2873				return;
2874			}
2875			k++;
2876		}
2877	}
2878	td = add_var(kv, size, def);
2879	memmove(td, data, size);
2880}
2881
2882void
2883set_sys_var(
2884	char *data,
2885	u_long size,
2886	int def
2887	)
2888{
2889	set_var(&ext_sys_var, data, size, def);
2890}
2891
2892void
2893free_varlist(
2894	struct ctl_var *kv
2895	)
2896{
2897	struct ctl_var *k;
2898	if (kv) {
2899		for (k = kv; !(k->flags & EOV); k++)
2900			free((void *)k->text);
2901		free((void *)kv);
2902	}
2903}
2904