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