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