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