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