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