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