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