]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/ntpd/ntp_control.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.git] / contrib / ntp / ntpd / ntp_control.c
1 /*
2  * ntp_control.c - respond to mode 6 control messages and send async
3  *                 traps.  Provides service to ntpq and others.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
9
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <signal.h>
13 #include <sys/stat.h>
14 #ifdef HAVE_NETINET_IN_H
15 # include <netinet/in.h>
16 #endif
17 #include <arpa/inet.h>
18
19 #include "ntpd.h"
20 #include "ntp_io.h"
21 #include "ntp_refclock.h"
22 #include "ntp_control.h"
23 #include "ntp_unixtime.h"
24 #include "ntp_stdlib.h"
25 #include "ntp_config.h"
26 #include "ntp_crypto.h"
27 #include "ntp_assert.h"
28 #include "ntp_leapsec.h"
29 #include "ntp_md5.h"    /* provides OpenSSL digest API */
30 #include "lib_strbuf.h"
31 #include <rc_cmdlength.h>
32 #ifdef KERNEL_PLL
33 # include "ntp_syscall.h"
34 #endif
35
36
37 /*
38  * Structure to hold request procedure information
39  */
40
41 struct ctl_proc {
42         short control_code;             /* defined request code */
43 #define NO_REQUEST      (-1)
44         u_short flags;                  /* flags word */
45         /* Only one flag.  Authentication required or not. */
46 #define NOAUTH  0
47 #define AUTH    1
48         void (*handler) (struct recvbuf *, int); /* handle request */
49 };
50
51
52 /*
53  * Request processing routines
54  */
55 static  void    ctl_error       (u_char);
56 #ifdef REFCLOCK
57 static  u_short ctlclkstatus    (struct refclockstat *);
58 #endif
59 static  void    ctl_flushpkt    (u_char);
60 static  void    ctl_putdata     (const char *, unsigned int, int);
61 static  void    ctl_putstr      (const char *, const char *, size_t);
62 static  void    ctl_putdblf     (const char *, int, int, double);
63 #define ctl_putdbl(tag, d)      ctl_putdblf(tag, 1, 3, d)
64 #define ctl_putdbl6(tag, d)     ctl_putdblf(tag, 1, 6, d)
65 #define ctl_putsfp(tag, sfp)    ctl_putdblf(tag, 0, -1, \
66                                             FPTOD(sfp))
67 static  void    ctl_putuint     (const char *, u_long);
68 static  void    ctl_puthex      (const char *, u_long);
69 static  void    ctl_putint      (const char *, long);
70 static  void    ctl_putts       (const char *, l_fp *);
71 static  void    ctl_putadr      (const char *, u_int32,
72                                  sockaddr_u *);
73 static  void    ctl_putrefid    (const char *, u_int32);
74 static  void    ctl_putarray    (const char *, double *, int);
75 static  void    ctl_putsys      (int);
76 static  void    ctl_putpeer     (int, struct peer *);
77 static  void    ctl_putfs       (const char *, tstamp_t);
78 #ifdef REFCLOCK
79 static  void    ctl_putclock    (int, struct refclockstat *, int);
80 #endif  /* REFCLOCK */
81 static  const struct ctl_var *ctl_getitem(const struct ctl_var *,
82                                           char **);
83 static  u_short count_var       (const struct ctl_var *);
84 static  void    control_unspec  (struct recvbuf *, int);
85 static  void    read_status     (struct recvbuf *, int);
86 static  void    read_sysvars    (void);
87 static  void    read_peervars   (void);
88 static  void    read_variables  (struct recvbuf *, int);
89 static  void    write_variables (struct recvbuf *, int);
90 static  void    read_clockstatus(struct recvbuf *, int);
91 static  void    write_clockstatus(struct recvbuf *, int);
92 static  void    set_trap        (struct recvbuf *, int);
93 static  void    save_config     (struct recvbuf *, int);
94 static  void    configure       (struct recvbuf *, int);
95 static  void    send_mru_entry  (mon_entry *, int);
96 static  void    send_random_tag_value(int);
97 static  void    read_mru_list   (struct recvbuf *, int);
98 static  void    send_ifstats_entry(endpt *, u_int);
99 static  void    read_ifstats    (struct recvbuf *);
100 static  void    sockaddrs_from_restrict_u(sockaddr_u *, sockaddr_u *,
101                                           restrict_u *, int);
102 static  void    send_restrict_entry(restrict_u *, int, u_int);
103 static  void    send_restrict_list(restrict_u *, int, u_int *);
104 static  void    read_addr_restrictions(struct recvbuf *);
105 static  void    read_ordlist    (struct recvbuf *, int);
106 static  u_int32 derive_nonce    (sockaddr_u *, u_int32, u_int32);
107 static  void    generate_nonce  (struct recvbuf *, char *, size_t);
108 static  int     validate_nonce  (const char *, struct recvbuf *);
109 static  void    req_nonce       (struct recvbuf *, int);
110 static  void    unset_trap      (struct recvbuf *, int);
111 static  struct ctl_trap *ctlfindtrap(sockaddr_u *,
112                                      struct interface *);
113
114 static const struct ctl_proc control_codes[] = {
115         { CTL_OP_UNSPEC,                NOAUTH, control_unspec },
116         { CTL_OP_READSTAT,              NOAUTH, read_status },
117         { CTL_OP_READVAR,               NOAUTH, read_variables },
118         { CTL_OP_WRITEVAR,              AUTH,   write_variables },
119         { CTL_OP_READCLOCK,             NOAUTH, read_clockstatus },
120         { CTL_OP_WRITECLOCK,            NOAUTH, write_clockstatus },
121         { CTL_OP_SETTRAP,               NOAUTH, set_trap },
122         { CTL_OP_CONFIGURE,             AUTH,   configure },
123         { CTL_OP_SAVECONFIG,            AUTH,   save_config },
124         { CTL_OP_READ_MRU,              NOAUTH, read_mru_list },
125         { CTL_OP_READ_ORDLIST_A,        AUTH,   read_ordlist },
126         { CTL_OP_REQ_NONCE,             NOAUTH, req_nonce },
127         { CTL_OP_UNSETTRAP,             NOAUTH, unset_trap },
128         { NO_REQUEST,                   0,      NULL }
129 };
130
131 /*
132  * System variables we understand
133  */
134 #define CS_LEAP                 1
135 #define CS_STRATUM              2
136 #define CS_PRECISION            3
137 #define CS_ROOTDELAY            4
138 #define CS_ROOTDISPERSION       5
139 #define CS_REFID                6
140 #define CS_REFTIME              7
141 #define CS_POLL                 8
142 #define CS_PEERID               9
143 #define CS_OFFSET               10
144 #define CS_DRIFT                11
145 #define CS_JITTER               12
146 #define CS_ERROR                13
147 #define CS_CLOCK                14
148 #define CS_PROCESSOR            15
149 #define CS_SYSTEM               16
150 #define CS_VERSION              17
151 #define CS_STABIL               18
152 #define CS_VARLIST              19
153 #define CS_TAI                  20
154 #define CS_LEAPTAB              21
155 #define CS_LEAPEND              22
156 #define CS_RATE                 23
157 #define CS_MRU_ENABLED          24
158 #define CS_MRU_DEPTH            25
159 #define CS_MRU_DEEPEST          26
160 #define CS_MRU_MINDEPTH         27
161 #define CS_MRU_MAXAGE           28
162 #define CS_MRU_MAXDEPTH         29
163 #define CS_MRU_MEM              30
164 #define CS_MRU_MAXMEM           31
165 #define CS_SS_UPTIME            32
166 #define CS_SS_RESET             33
167 #define CS_SS_RECEIVED          34
168 #define CS_SS_THISVER           35
169 #define CS_SS_OLDVER            36
170 #define CS_SS_BADFORMAT         37
171 #define CS_SS_BADAUTH           38
172 #define CS_SS_DECLINED          39
173 #define CS_SS_RESTRICTED        40
174 #define CS_SS_LIMITED           41
175 #define CS_SS_KODSENT           42
176 #define CS_SS_PROCESSED         43
177 #define CS_PEERADR              44
178 #define CS_PEERMODE             45
179 #define CS_BCASTDELAY           46
180 #define CS_AUTHDELAY            47
181 #define CS_AUTHKEYS             48
182 #define CS_AUTHFREEK            49
183 #define CS_AUTHKLOOKUPS         50
184 #define CS_AUTHKNOTFOUND        51
185 #define CS_AUTHKUNCACHED        52
186 #define CS_AUTHKEXPIRED         53
187 #define CS_AUTHENCRYPTS         54
188 #define CS_AUTHDECRYPTS         55
189 #define CS_AUTHRESET            56
190 #define CS_K_OFFSET             57
191 #define CS_K_FREQ               58
192 #define CS_K_MAXERR             59
193 #define CS_K_ESTERR             60
194 #define CS_K_STFLAGS            61
195 #define CS_K_TIMECONST          62
196 #define CS_K_PRECISION          63
197 #define CS_K_FREQTOL            64
198 #define CS_K_PPS_FREQ           65
199 #define CS_K_PPS_STABIL         66
200 #define CS_K_PPS_JITTER         67
201 #define CS_K_PPS_CALIBDUR       68
202 #define CS_K_PPS_CALIBS         69
203 #define CS_K_PPS_CALIBERRS      70
204 #define CS_K_PPS_JITEXC         71
205 #define CS_K_PPS_STBEXC         72
206 #define CS_KERN_FIRST           CS_K_OFFSET
207 #define CS_KERN_LAST            CS_K_PPS_STBEXC
208 #define CS_IOSTATS_RESET        73
209 #define CS_TOTAL_RBUF           74
210 #define CS_FREE_RBUF            75
211 #define CS_USED_RBUF            76
212 #define CS_RBUF_LOWATER         77
213 #define CS_IO_DROPPED           78
214 #define CS_IO_IGNORED           79
215 #define CS_IO_RECEIVED          80
216 #define CS_IO_SENT              81
217 #define CS_IO_SENDFAILED        82
218 #define CS_IO_WAKEUPS           83
219 #define CS_IO_GOODWAKEUPS       84
220 #define CS_TIMERSTATS_RESET     85
221 #define CS_TIMER_OVERRUNS       86
222 #define CS_TIMER_XMTS           87
223 #define CS_FUZZ                 88
224 #define CS_WANDER_THRESH        89
225 #define CS_LEAPSMEARINTV        90
226 #define CS_LEAPSMEAROFFS        91
227 #define CS_MAX_NOAUTOKEY        CS_LEAPSMEAROFFS
228 #ifdef AUTOKEY
229 #define CS_FLAGS                (1 + CS_MAX_NOAUTOKEY)
230 #define CS_HOST                 (2 + CS_MAX_NOAUTOKEY)
231 #define CS_PUBLIC               (3 + CS_MAX_NOAUTOKEY)
232 #define CS_CERTIF               (4 + CS_MAX_NOAUTOKEY)
233 #define CS_SIGNATURE            (5 + CS_MAX_NOAUTOKEY)
234 #define CS_REVTIME              (6 + CS_MAX_NOAUTOKEY)
235 #define CS_IDENT                (7 + CS_MAX_NOAUTOKEY)
236 #define CS_DIGEST               (8 + CS_MAX_NOAUTOKEY)
237 #define CS_MAXCODE              CS_DIGEST
238 #else   /* !AUTOKEY follows */
239 #define CS_MAXCODE              CS_MAX_NOAUTOKEY
240 #endif  /* !AUTOKEY */
241
242 /*
243  * Peer variables we understand
244  */
245 #define CP_CONFIG               1
246 #define CP_AUTHENABLE           2
247 #define CP_AUTHENTIC            3
248 #define CP_SRCADR               4
249 #define CP_SRCPORT              5
250 #define CP_DSTADR               6
251 #define CP_DSTPORT              7
252 #define CP_LEAP                 8
253 #define CP_HMODE                9
254 #define CP_STRATUM              10
255 #define CP_PPOLL                11
256 #define CP_HPOLL                12
257 #define CP_PRECISION            13
258 #define CP_ROOTDELAY            14
259 #define CP_ROOTDISPERSION       15
260 #define CP_REFID                16
261 #define CP_REFTIME              17
262 #define CP_ORG                  18
263 #define CP_REC                  19
264 #define CP_XMT                  20
265 #define CP_REACH                21
266 #define CP_UNREACH              22
267 #define CP_TIMER                23
268 #define CP_DELAY                24
269 #define CP_OFFSET               25
270 #define CP_JITTER               26
271 #define CP_DISPERSION           27
272 #define CP_KEYID                28
273 #define CP_FILTDELAY            29
274 #define CP_FILTOFFSET           30
275 #define CP_PMODE                31
276 #define CP_RECEIVED             32
277 #define CP_SENT                 33
278 #define CP_FILTERROR            34
279 #define CP_FLASH                35
280 #define CP_TTL                  36
281 #define CP_VARLIST              37
282 #define CP_IN                   38
283 #define CP_OUT                  39
284 #define CP_RATE                 40
285 #define CP_BIAS                 41
286 #define CP_SRCHOST              42
287 #define CP_TIMEREC              43
288 #define CP_TIMEREACH            44
289 #define CP_BADAUTH              45
290 #define CP_BOGUSORG             46
291 #define CP_OLDPKT               47
292 #define CP_SELDISP              48
293 #define CP_SELBROKEN            49
294 #define CP_CANDIDATE            50
295 #define CP_MAX_NOAUTOKEY        CP_CANDIDATE
296 #ifdef AUTOKEY
297 #define CP_FLAGS                (1 + CP_MAX_NOAUTOKEY)
298 #define CP_HOST                 (2 + CP_MAX_NOAUTOKEY)
299 #define CP_VALID                (3 + CP_MAX_NOAUTOKEY)
300 #define CP_INITSEQ              (4 + CP_MAX_NOAUTOKEY)
301 #define CP_INITKEY              (5 + CP_MAX_NOAUTOKEY)
302 #define CP_INITTSP              (6 + CP_MAX_NOAUTOKEY)
303 #define CP_SIGNATURE            (7 + CP_MAX_NOAUTOKEY)
304 #define CP_IDENT                (8 + CP_MAX_NOAUTOKEY)
305 #define CP_MAXCODE              CP_IDENT
306 #else   /* !AUTOKEY follows */
307 #define CP_MAXCODE              CP_MAX_NOAUTOKEY
308 #endif  /* !AUTOKEY */
309
310 /*
311  * Clock variables we understand
312  */
313 #define CC_TYPE         1
314 #define CC_TIMECODE     2
315 #define CC_POLL         3
316 #define CC_NOREPLY      4
317 #define CC_BADFORMAT    5
318 #define CC_BADDATA      6
319 #define CC_FUDGETIME1   7
320 #define CC_FUDGETIME2   8
321 #define CC_FUDGEVAL1    9
322 #define CC_FUDGEVAL2    10
323 #define CC_FLAGS        11
324 #define CC_DEVICE       12
325 #define CC_VARLIST      13
326 #define CC_MAXCODE      CC_VARLIST
327
328 /*
329  * System variable values. The array can be indexed by the variable
330  * index to find the textual name.
331  */
332 static const struct ctl_var sys_var[] = {
333         { 0,            PADDING, "" },          /* 0 */
334         { CS_LEAP,      RW, "leap" },           /* 1 */
335         { CS_STRATUM,   RO, "stratum" },        /* 2 */
336         { CS_PRECISION, RO, "precision" },      /* 3 */
337         { CS_ROOTDELAY, RO, "rootdelay" },      /* 4 */
338         { CS_ROOTDISPERSION, RO, "rootdisp" },  /* 5 */
339         { CS_REFID,     RO, "refid" },          /* 6 */
340         { CS_REFTIME,   RO, "reftime" },        /* 7 */
341         { CS_POLL,      RO, "tc" },             /* 8 */
342         { CS_PEERID,    RO, "peer" },           /* 9 */
343         { CS_OFFSET,    RO, "offset" },         /* 10 */
344         { CS_DRIFT,     RO, "frequency" },      /* 11 */
345         { CS_JITTER,    RO, "sys_jitter" },     /* 12 */
346         { CS_ERROR,     RO, "clk_jitter" },     /* 13 */
347         { CS_CLOCK,     RO, "clock" },          /* 14 */
348         { CS_PROCESSOR, RO, "processor" },      /* 15 */
349         { CS_SYSTEM,    RO, "system" },         /* 16 */
350         { CS_VERSION,   RO, "version" },        /* 17 */
351         { CS_STABIL,    RO, "clk_wander" },     /* 18 */
352         { CS_VARLIST,   RO, "sys_var_list" },   /* 19 */
353         { CS_TAI,       RO, "tai" },            /* 20 */
354         { CS_LEAPTAB,   RO, "leapsec" },        /* 21 */
355         { CS_LEAPEND,   RO, "expire" },         /* 22 */
356         { CS_RATE,      RO, "mintc" },          /* 23 */
357         { CS_MRU_ENABLED,       RO, "mru_enabled" },    /* 24 */
358         { CS_MRU_DEPTH,         RO, "mru_depth" },      /* 25 */
359         { CS_MRU_DEEPEST,       RO, "mru_deepest" },    /* 26 */
360         { CS_MRU_MINDEPTH,      RO, "mru_mindepth" },   /* 27 */
361         { CS_MRU_MAXAGE,        RO, "mru_maxage" },     /* 28 */
362         { CS_MRU_MAXDEPTH,      RO, "mru_maxdepth" },   /* 29 */
363         { CS_MRU_MEM,           RO, "mru_mem" },        /* 30 */
364         { CS_MRU_MAXMEM,        RO, "mru_maxmem" },     /* 31 */
365         { CS_SS_UPTIME,         RO, "ss_uptime" },      /* 32 */
366         { CS_SS_RESET,          RO, "ss_reset" },       /* 33 */
367         { CS_SS_RECEIVED,       RO, "ss_received" },    /* 34 */
368         { CS_SS_THISVER,        RO, "ss_thisver" },     /* 35 */
369         { CS_SS_OLDVER,         RO, "ss_oldver" },      /* 36 */
370         { CS_SS_BADFORMAT,      RO, "ss_badformat" },   /* 37 */
371         { CS_SS_BADAUTH,        RO, "ss_badauth" },     /* 38 */
372         { CS_SS_DECLINED,       RO, "ss_declined" },    /* 39 */
373         { CS_SS_RESTRICTED,     RO, "ss_restricted" },  /* 40 */
374         { CS_SS_LIMITED,        RO, "ss_limited" },     /* 41 */
375         { CS_SS_KODSENT,        RO, "ss_kodsent" },     /* 42 */
376         { CS_SS_PROCESSED,      RO, "ss_processed" },   /* 43 */
377         { CS_PEERADR,           RO, "peeradr" },        /* 44 */
378         { CS_PEERMODE,          RO, "peermode" },       /* 45 */
379         { CS_BCASTDELAY,        RO, "bcastdelay" },     /* 46 */
380         { CS_AUTHDELAY,         RO, "authdelay" },      /* 47 */
381         { CS_AUTHKEYS,          RO, "authkeys" },       /* 48 */
382         { CS_AUTHFREEK,         RO, "authfreek" },      /* 49 */
383         { CS_AUTHKLOOKUPS,      RO, "authklookups" },   /* 50 */
384         { CS_AUTHKNOTFOUND,     RO, "authknotfound" },  /* 51 */
385         { CS_AUTHKUNCACHED,     RO, "authkuncached" },  /* 52 */
386         { CS_AUTHKEXPIRED,      RO, "authkexpired" },   /* 53 */
387         { CS_AUTHENCRYPTS,      RO, "authencrypts" },   /* 54 */
388         { CS_AUTHDECRYPTS,      RO, "authdecrypts" },   /* 55 */
389         { CS_AUTHRESET,         RO, "authreset" },      /* 56 */
390         { CS_K_OFFSET,          RO, "koffset" },        /* 57 */
391         { CS_K_FREQ,            RO, "kfreq" },          /* 58 */
392         { CS_K_MAXERR,          RO, "kmaxerr" },        /* 59 */
393         { CS_K_ESTERR,          RO, "kesterr" },        /* 60 */
394         { CS_K_STFLAGS,         RO, "kstflags" },       /* 61 */
395         { CS_K_TIMECONST,       RO, "ktimeconst" },     /* 62 */
396         { CS_K_PRECISION,       RO, "kprecis" },        /* 63 */
397         { CS_K_FREQTOL,         RO, "kfreqtol" },       /* 64 */
398         { CS_K_PPS_FREQ,        RO, "kppsfreq" },       /* 65 */
399         { CS_K_PPS_STABIL,      RO, "kppsstab" },       /* 66 */
400         { CS_K_PPS_JITTER,      RO, "kppsjitter" },     /* 67 */
401         { CS_K_PPS_CALIBDUR,    RO, "kppscalibdur" },   /* 68 */
402         { CS_K_PPS_CALIBS,      RO, "kppscalibs" },     /* 69 */
403         { CS_K_PPS_CALIBERRS,   RO, "kppscaliberrs" },  /* 70 */
404         { CS_K_PPS_JITEXC,      RO, "kppsjitexc" },     /* 71 */
405         { CS_K_PPS_STBEXC,      RO, "kppsstbexc" },     /* 72 */
406         { CS_IOSTATS_RESET,     RO, "iostats_reset" },  /* 73 */
407         { CS_TOTAL_RBUF,        RO, "total_rbuf" },     /* 74 */
408         { CS_FREE_RBUF,         RO, "free_rbuf" },      /* 75 */
409         { CS_USED_RBUF,         RO, "used_rbuf" },      /* 76 */
410         { CS_RBUF_LOWATER,      RO, "rbuf_lowater" },   /* 77 */
411         { CS_IO_DROPPED,        RO, "io_dropped" },     /* 78 */
412         { CS_IO_IGNORED,        RO, "io_ignored" },     /* 79 */
413         { CS_IO_RECEIVED,       RO, "io_received" },    /* 80 */
414         { CS_IO_SENT,           RO, "io_sent" },        /* 81 */
415         { CS_IO_SENDFAILED,     RO, "io_sendfailed" },  /* 82 */
416         { CS_IO_WAKEUPS,        RO, "io_wakeups" },     /* 83 */
417         { CS_IO_GOODWAKEUPS,    RO, "io_goodwakeups" }, /* 84 */
418         { CS_TIMERSTATS_RESET,  RO, "timerstats_reset" },/* 85 */
419         { CS_TIMER_OVERRUNS,    RO, "timer_overruns" }, /* 86 */
420         { CS_TIMER_XMTS,        RO, "timer_xmts" },     /* 87 */
421         { CS_FUZZ,              RO, "fuzz" },           /* 88 */
422         { CS_WANDER_THRESH,     RO, "clk_wander_threshold" }, /* 89 */
423
424         { CS_LEAPSMEARINTV,     RO, "leapsmearinterval" },    /* 90 */
425         { CS_LEAPSMEAROFFS,     RO, "leapsmearoffset" },      /* 91 */
426
427 #ifdef AUTOKEY
428         { CS_FLAGS,     RO, "flags" },          /* 1 + CS_MAX_NOAUTOKEY */
429         { CS_HOST,      RO, "host" },           /* 2 + CS_MAX_NOAUTOKEY */
430         { CS_PUBLIC,    RO, "update" },         /* 3 + CS_MAX_NOAUTOKEY */
431         { CS_CERTIF,    RO, "cert" },           /* 4 + CS_MAX_NOAUTOKEY */
432         { CS_SIGNATURE, RO, "signature" },      /* 5 + CS_MAX_NOAUTOKEY */
433         { CS_REVTIME,   RO, "until" },          /* 6 + CS_MAX_NOAUTOKEY */
434         { CS_IDENT,     RO, "ident" },          /* 7 + CS_MAX_NOAUTOKEY */
435         { CS_DIGEST,    RO, "digest" },         /* 8 + CS_MAX_NOAUTOKEY */
436 #endif  /* AUTOKEY */
437         { 0,            EOV, "" }               /* 87/95 */
438 };
439
440 static struct ctl_var *ext_sys_var = NULL;
441
442 /*
443  * System variables we print by default (in fuzzball order,
444  * more-or-less)
445  */
446 static const u_char def_sys_var[] = {
447         CS_VERSION,
448         CS_PROCESSOR,
449         CS_SYSTEM,
450         CS_LEAP,
451         CS_STRATUM,
452         CS_PRECISION,
453         CS_ROOTDELAY,
454         CS_ROOTDISPERSION,
455         CS_REFID,
456         CS_REFTIME,
457         CS_CLOCK,
458         CS_PEERID,
459         CS_POLL,
460         CS_RATE,
461         CS_OFFSET,
462         CS_DRIFT,
463         CS_JITTER,
464         CS_ERROR,
465         CS_STABIL,
466         CS_TAI,
467         CS_LEAPTAB,
468         CS_LEAPEND,
469         CS_LEAPSMEARINTV,
470         CS_LEAPSMEAROFFS,
471 #ifdef AUTOKEY
472         CS_HOST,
473         CS_IDENT,
474         CS_FLAGS,
475         CS_DIGEST,
476         CS_SIGNATURE,
477         CS_PUBLIC,
478         CS_CERTIF,
479 #endif  /* AUTOKEY */
480         0
481 };
482
483
484 /*
485  * Peer variable list
486  */
487 static const struct ctl_var peer_var[] = {
488         { 0,            PADDING, "" },          /* 0 */
489         { CP_CONFIG,    RO, "config" },         /* 1 */
490         { CP_AUTHENABLE, RO,    "authenable" }, /* 2 */
491         { CP_AUTHENTIC, RO, "authentic" },      /* 3 */
492         { CP_SRCADR,    RO, "srcadr" },         /* 4 */
493         { CP_SRCPORT,   RO, "srcport" },        /* 5 */
494         { CP_DSTADR,    RO, "dstadr" },         /* 6 */
495         { CP_DSTPORT,   RO, "dstport" },        /* 7 */
496         { CP_LEAP,      RO, "leap" },           /* 8 */
497         { CP_HMODE,     RO, "hmode" },          /* 9 */
498         { CP_STRATUM,   RO, "stratum" },        /* 10 */
499         { CP_PPOLL,     RO, "ppoll" },          /* 11 */
500         { CP_HPOLL,     RO, "hpoll" },          /* 12 */
501         { CP_PRECISION, RO, "precision" },      /* 13 */
502         { CP_ROOTDELAY, RO, "rootdelay" },      /* 14 */
503         { CP_ROOTDISPERSION, RO, "rootdisp" },  /* 15 */
504         { CP_REFID,     RO, "refid" },          /* 16 */
505         { CP_REFTIME,   RO, "reftime" },        /* 17 */
506         { CP_ORG,       RO, "org" },            /* 18 */
507         { CP_REC,       RO, "rec" },            /* 19 */
508         { CP_XMT,       RO, "xleave" },         /* 20 */
509         { CP_REACH,     RO, "reach" },          /* 21 */
510         { CP_UNREACH,   RO, "unreach" },        /* 22 */
511         { CP_TIMER,     RO, "timer" },          /* 23 */
512         { CP_DELAY,     RO, "delay" },          /* 24 */
513         { CP_OFFSET,    RO, "offset" },         /* 25 */
514         { CP_JITTER,    RO, "jitter" },         /* 26 */
515         { CP_DISPERSION, RO, "dispersion" },    /* 27 */
516         { CP_KEYID,     RO, "keyid" },          /* 28 */
517         { CP_FILTDELAY, RO, "filtdelay" },      /* 29 */
518         { CP_FILTOFFSET, RO, "filtoffset" },    /* 30 */
519         { CP_PMODE,     RO, "pmode" },          /* 31 */
520         { CP_RECEIVED,  RO, "received"},        /* 32 */
521         { CP_SENT,      RO, "sent" },           /* 33 */
522         { CP_FILTERROR, RO, "filtdisp" },       /* 34 */
523         { CP_FLASH,     RO, "flash" },          /* 35 */
524         { CP_TTL,       RO, "ttl" },            /* 36 */
525         { CP_VARLIST,   RO, "peer_var_list" },  /* 37 */
526         { CP_IN,        RO, "in" },             /* 38 */
527         { CP_OUT,       RO, "out" },            /* 39 */
528         { CP_RATE,      RO, "headway" },        /* 40 */
529         { CP_BIAS,      RO, "bias" },           /* 41 */
530         { CP_SRCHOST,   RO, "srchost" },        /* 42 */
531         { CP_TIMEREC,   RO, "timerec" },        /* 43 */
532         { CP_TIMEREACH, RO, "timereach" },      /* 44 */
533         { CP_BADAUTH,   RO, "badauth" },        /* 45 */
534         { CP_BOGUSORG,  RO, "bogusorg" },       /* 46 */
535         { CP_OLDPKT,    RO, "oldpkt" },         /* 47 */
536         { CP_SELDISP,   RO, "seldisp" },        /* 48 */
537         { CP_SELBROKEN, RO, "selbroken" },      /* 49 */
538         { CP_CANDIDATE, RO, "candidate" },      /* 50 */
539 #ifdef AUTOKEY
540         { CP_FLAGS,     RO, "flags" },          /* 1 + CP_MAX_NOAUTOKEY */
541         { CP_HOST,      RO, "host" },           /* 2 + CP_MAX_NOAUTOKEY */
542         { CP_VALID,     RO, "valid" },          /* 3 + CP_MAX_NOAUTOKEY */
543         { CP_INITSEQ,   RO, "initsequence" },   /* 4 + CP_MAX_NOAUTOKEY */
544         { CP_INITKEY,   RO, "initkey" },        /* 5 + CP_MAX_NOAUTOKEY */
545         { CP_INITTSP,   RO, "timestamp" },      /* 6 + CP_MAX_NOAUTOKEY */
546         { CP_SIGNATURE, RO, "signature" },      /* 7 + CP_MAX_NOAUTOKEY */
547         { CP_IDENT,     RO, "ident" },          /* 8 + CP_MAX_NOAUTOKEY */
548 #endif  /* AUTOKEY */
549         { 0,            EOV, "" }               /* 50/58 */
550 };
551
552
553 /*
554  * Peer variables we print by default
555  */
556 static const u_char def_peer_var[] = {
557         CP_SRCADR,
558         CP_SRCPORT,
559         CP_SRCHOST,
560         CP_DSTADR,
561         CP_DSTPORT,
562         CP_OUT,
563         CP_IN,
564         CP_LEAP,
565         CP_STRATUM,
566         CP_PRECISION,
567         CP_ROOTDELAY,
568         CP_ROOTDISPERSION,
569         CP_REFID,
570         CP_REFTIME,
571         CP_REC,
572         CP_REACH,
573         CP_UNREACH,
574         CP_HMODE,
575         CP_PMODE,
576         CP_HPOLL,
577         CP_PPOLL,
578         CP_RATE,
579         CP_FLASH,
580         CP_KEYID,
581         CP_TTL,
582         CP_OFFSET,
583         CP_DELAY,
584         CP_DISPERSION,
585         CP_JITTER,
586         CP_XMT,
587         CP_BIAS,
588         CP_FILTDELAY,
589         CP_FILTOFFSET,
590         CP_FILTERROR,
591 #ifdef AUTOKEY
592         CP_HOST,
593         CP_FLAGS,
594         CP_SIGNATURE,
595         CP_VALID,
596         CP_INITSEQ,
597         CP_IDENT,
598 #endif  /* AUTOKEY */
599         0
600 };
601
602
603 #ifdef REFCLOCK
604 /*
605  * Clock variable list
606  */
607 static const struct ctl_var clock_var[] = {
608         { 0,            PADDING, "" },          /* 0 */
609         { CC_TYPE,      RO, "type" },           /* 1 */
610         { CC_TIMECODE,  RO, "timecode" },       /* 2 */
611         { CC_POLL,      RO, "poll" },           /* 3 */
612         { CC_NOREPLY,   RO, "noreply" },        /* 4 */
613         { CC_BADFORMAT, RO, "badformat" },      /* 5 */
614         { CC_BADDATA,   RO, "baddata" },        /* 6 */
615         { CC_FUDGETIME1, RO, "fudgetime1" },    /* 7 */
616         { CC_FUDGETIME2, RO, "fudgetime2" },    /* 8 */
617         { CC_FUDGEVAL1, RO, "stratum" },        /* 9 */
618         { CC_FUDGEVAL2, RO, "refid" },          /* 10 */
619         { CC_FLAGS,     RO, "flags" },          /* 11 */
620         { CC_DEVICE,    RO, "device" },         /* 12 */
621         { CC_VARLIST,   RO, "clock_var_list" }, /* 13 */
622         { 0,            EOV, ""  }              /* 14 */
623 };
624
625
626 /*
627  * Clock variables printed by default
628  */
629 static const u_char def_clock_var[] = {
630         CC_DEVICE,
631         CC_TYPE,        /* won't be output if device = known */
632         CC_TIMECODE,
633         CC_POLL,
634         CC_NOREPLY,
635         CC_BADFORMAT,
636         CC_BADDATA,
637         CC_FUDGETIME1,
638         CC_FUDGETIME2,
639         CC_FUDGEVAL1,
640         CC_FUDGEVAL2,
641         CC_FLAGS,
642         0
643 };
644 #endif
645
646 /*
647  * MRU string constants shared by send_mru_entry() and read_mru_list().
648  */
649 static const char addr_fmt[] =          "addr.%d";
650 static const char last_fmt[] =          "last.%d";
651
652 /*
653  * System and processor definitions.
654  */
655 #ifndef HAVE_UNAME
656 # ifndef STR_SYSTEM
657 #  define               STR_SYSTEM      "UNIX"
658 # endif
659 # ifndef STR_PROCESSOR
660 #  define               STR_PROCESSOR   "unknown"
661 # endif
662
663 static const char str_system[] = STR_SYSTEM;
664 static const char str_processor[] = STR_PROCESSOR;
665 #else
666 # include <sys/utsname.h>
667 static struct utsname utsnamebuf;
668 #endif /* HAVE_UNAME */
669
670 /*
671  * Trap structures. We only allow a few of these, and send a copy of
672  * each async message to each live one. Traps time out after an hour, it
673  * is up to the trap receipient to keep resetting it to avoid being
674  * timed out.
675  */
676 /* ntp_request.c */
677 struct ctl_trap ctl_traps[CTL_MAXTRAPS];
678 int num_ctl_traps;
679
680 /*
681  * Type bits, for ctlsettrap() call.
682  */
683 #define TRAP_TYPE_CONFIG        0       /* used by configuration code */
684 #define TRAP_TYPE_PRIO          1       /* priority trap */
685 #define TRAP_TYPE_NONPRIO       2       /* nonpriority trap */
686
687
688 /*
689  * List relating reference clock types to control message time sources.
690  * Index by the reference clock type. This list will only be used iff
691  * the reference clock driver doesn't set peer->sstclktype to something
692  * different than CTL_SST_TS_UNSPEC.
693  */
694 #ifdef REFCLOCK
695 static const u_char clocktypes[] = {
696         CTL_SST_TS_NTP,         /* REFCLK_NONE (0) */
697         CTL_SST_TS_LOCAL,       /* REFCLK_LOCALCLOCK (1) */
698         CTL_SST_TS_UHF,         /* deprecated REFCLK_GPS_TRAK (2) */
699         CTL_SST_TS_HF,          /* REFCLK_WWV_PST (3) */
700         CTL_SST_TS_LF,          /* REFCLK_WWVB_SPECTRACOM (4) */
701         CTL_SST_TS_UHF,         /* REFCLK_TRUETIME (5) */
702         CTL_SST_TS_UHF,         /* REFCLK_IRIG_AUDIO (6) */
703         CTL_SST_TS_HF,          /* REFCLK_CHU (7) */
704         CTL_SST_TS_LF,          /* REFCLOCK_PARSE (default) (8) */
705         CTL_SST_TS_LF,          /* REFCLK_GPS_MX4200 (9) */
706         CTL_SST_TS_UHF,         /* REFCLK_GPS_AS2201 (10) */
707         CTL_SST_TS_UHF,         /* REFCLK_GPS_ARBITER (11) */
708         CTL_SST_TS_UHF,         /* REFCLK_IRIG_TPRO (12) */
709         CTL_SST_TS_ATOM,        /* REFCLK_ATOM_LEITCH (13) */
710         CTL_SST_TS_LF,          /* deprecated REFCLK_MSF_EES (14) */
711         CTL_SST_TS_NTP,         /* not used (15) */
712         CTL_SST_TS_UHF,         /* REFCLK_IRIG_BANCOMM (16) */
713         CTL_SST_TS_UHF,         /* REFCLK_GPS_DATU (17) */
714         CTL_SST_TS_TELEPHONE,   /* REFCLK_NIST_ACTS (18) */
715         CTL_SST_TS_HF,          /* REFCLK_WWV_HEATH (19) */
716         CTL_SST_TS_UHF,         /* REFCLK_GPS_NMEA (20) */
717         CTL_SST_TS_UHF,         /* REFCLK_GPS_VME (21) */
718         CTL_SST_TS_ATOM,        /* REFCLK_ATOM_PPS (22) */
719         CTL_SST_TS_NTP,         /* not used (23) */
720         CTL_SST_TS_NTP,         /* not used (24) */
721         CTL_SST_TS_NTP,         /* not used (25) */
722         CTL_SST_TS_UHF,         /* REFCLK_GPS_HP (26) */
723         CTL_SST_TS_LF,          /* REFCLK_ARCRON_MSF (27) */
724         CTL_SST_TS_UHF,         /* REFCLK_SHM (28) */
725         CTL_SST_TS_UHF,         /* REFCLK_PALISADE (29) */
726         CTL_SST_TS_UHF,         /* REFCLK_ONCORE (30) */
727         CTL_SST_TS_UHF,         /* REFCLK_JUPITER (31) */
728         CTL_SST_TS_LF,          /* REFCLK_CHRONOLOG (32) */
729         CTL_SST_TS_LF,          /* REFCLK_DUMBCLOCK (33) */
730         CTL_SST_TS_LF,          /* REFCLK_ULINK (34) */
731         CTL_SST_TS_LF,          /* REFCLK_PCF (35) */
732         CTL_SST_TS_HF,          /* REFCLK_WWV (36) */
733         CTL_SST_TS_LF,          /* REFCLK_FG (37) */
734         CTL_SST_TS_UHF,         /* REFCLK_HOPF_SERIAL (38) */
735         CTL_SST_TS_UHF,         /* REFCLK_HOPF_PCI (39) */
736         CTL_SST_TS_LF,          /* REFCLK_JJY (40) */
737         CTL_SST_TS_UHF,         /* REFCLK_TT560 (41) */
738         CTL_SST_TS_UHF,         /* REFCLK_ZYFER (42) */
739         CTL_SST_TS_UHF,         /* REFCLK_RIPENCC (43) */
740         CTL_SST_TS_UHF,         /* REFCLK_NEOCLOCK4X (44) */
741         CTL_SST_TS_UHF,         /* REFCLK_TSYNCPCI (45) */
742         CTL_SST_TS_UHF          /* REFCLK_GPSDJSON (46) */
743 };
744 #endif  /* REFCLOCK */
745
746
747 /*
748  * Keyid used for authenticating write requests.
749  */
750 keyid_t ctl_auth_keyid;
751
752 /*
753  * We keep track of the last error reported by the system internally
754  */
755 static  u_char ctl_sys_last_event;
756 static  u_char ctl_sys_num_events;
757
758
759 /*
760  * Statistic counters to keep track of requests and responses.
761  */
762 u_long ctltimereset;            /* time stats reset */
763 u_long numctlreq;               /* number of requests we've received */
764 u_long numctlbadpkts;           /* number of bad control packets */
765 u_long numctlresponses;         /* number of resp packets sent with data */
766 u_long numctlfrags;             /* number of fragments sent */
767 u_long numctlerrors;            /* number of error responses sent */
768 u_long numctltooshort;          /* number of too short input packets */
769 u_long numctlinputresp;         /* number of responses on input */
770 u_long numctlinputfrag;         /* number of fragments on input */
771 u_long numctlinputerr;          /* number of input pkts with err bit set */
772 u_long numctlbadoffset;         /* number of input pkts with nonzero offset */
773 u_long numctlbadversion;        /* number of input pkts with unknown version */
774 u_long numctldatatooshort;      /* data too short for count */
775 u_long numctlbadop;             /* bad op code found in packet */
776 u_long numasyncmsgs;            /* number of async messages we've sent */
777
778 /*
779  * Response packet used by these routines. Also some state information
780  * so that we can handle packet formatting within a common set of
781  * subroutines.  Note we try to enter data in place whenever possible,
782  * but the need to set the more bit correctly means we occasionally
783  * use the extra buffer and copy.
784  */
785 static struct ntp_control rpkt;
786 static u_char   res_version;
787 static u_char   res_opcode;
788 static associd_t res_associd;
789 static u_short  res_frags;      /* datagrams in this response */
790 static int      res_offset;     /* offset of payload in response */
791 static u_char * datapt;
792 static u_char * dataend;
793 static int      datalinelen;
794 static int      datasent;       /* flag to avoid initial ", " */
795 static int      datanotbinflag;
796 static sockaddr_u *rmt_addr;
797 static struct interface *lcl_inter;
798
799 static u_char   res_authenticate;
800 static u_char   res_authokay;
801 static keyid_t  res_keyid;
802
803 #define MAXDATALINELEN  (72)
804
805 static u_char   res_async;      /* sending async trap response? */
806
807 /*
808  * Pointers for saving state when decoding request packets
809  */
810 static  char *reqpt;
811 static  char *reqend;
812
813 #ifndef MIN
814 #define MIN(a, b) (((a) <= (b)) ? (a) : (b))
815 #endif
816
817 /*
818  * init_control - initialize request data
819  */
820 void
821 init_control(void)
822 {
823         size_t i;
824
825 #ifdef HAVE_UNAME
826         uname(&utsnamebuf);
827 #endif /* HAVE_UNAME */
828
829         ctl_clr_stats();
830
831         ctl_auth_keyid = 0;
832         ctl_sys_last_event = EVNT_UNSPEC;
833         ctl_sys_num_events = 0;
834
835         num_ctl_traps = 0;
836         for (i = 0; i < COUNTOF(ctl_traps); i++)
837                 ctl_traps[i].tr_flags = 0;
838 }
839
840
841 /*
842  * ctl_error - send an error response for the current request
843  */
844 static void
845 ctl_error(
846         u_char errcode
847         )
848 {
849         size_t          maclen;
850
851         numctlerrors++;
852         DPRINTF(3, ("sending control error %u\n", errcode));
853
854         /*
855          * Fill in the fields. We assume rpkt.sequence and rpkt.associd
856          * have already been filled in.
857          */
858         rpkt.r_m_e_op = (u_char)CTL_RESPONSE | CTL_ERROR |
859                         (res_opcode & CTL_OP_MASK);
860         rpkt.status = htons((u_short)(errcode << 8) & 0xff00);
861         rpkt.count = 0;
862
863         /*
864          * send packet and bump counters
865          */
866         if (res_authenticate && sys_authenticate) {
867                 maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
868                                      CTL_HEADER_LEN);
869                 sendpkt(rmt_addr, lcl_inter, -2, (void *)&rpkt,
870                         CTL_HEADER_LEN + maclen);
871         } else
872                 sendpkt(rmt_addr, lcl_inter, -3, (void *)&rpkt,
873                         CTL_HEADER_LEN);
874 }
875
876 /*
877  * save_config - Implements ntpq -c "saveconfig <filename>"
878  *               Writes current configuration including any runtime
879  *               changes by ntpq's :config or config-from-file
880  */
881 void
882 save_config(
883         struct recvbuf *rbufp,
884         int restrict_mask
885         )
886 {
887         /* block directory traversal by searching for characters that
888          * indicate directory components in a file path.
889          *
890          * Conceptually we should be searching for DIRSEP in filename,
891          * however Windows actually recognizes both forward and
892          * backslashes as equivalent directory separators at the API
893          * level.  On POSIX systems we could allow '\\' but such
894          * filenames are tricky to manipulate from a shell, so just
895          * reject both types of slashes on all platforms.
896          */     
897         /* TALOS-CAN-0062: block directory traversal for VMS, too */
898         static const char * illegal_in_filename =
899 #if defined(VMS)
900             ":[]"       /* do not allow drive and path components here */
901 #elif defined(SYS_WINNT)
902             ":\\/"      /* path and drive separators */
903 #else
904             "\\/"       /* separator and critical char for POSIX */
905 #endif
906             ;
907
908
909         char reply[128];
910 #ifdef SAVECONFIG
911         char filespec[128];
912         char filename[128];
913         char fullpath[512];
914         const char savedconfig_eq[] = "savedconfig=";
915         char savedconfig[sizeof(savedconfig_eq) + sizeof(filename)];
916         time_t now;
917         int fd;
918         FILE *fptr;
919 #endif
920
921         if (RES_NOMODIFY & restrict_mask) {
922                 snprintf(reply, sizeof(reply),
923                          "saveconfig prohibited by restrict ... nomodify");
924                 ctl_putdata(reply, strlen(reply), 0);
925                 ctl_flushpkt(0);
926                 NLOG(NLOG_SYSINFO)
927                         msyslog(LOG_NOTICE,
928                                 "saveconfig from %s rejected due to nomodify restriction",
929                                 stoa(&rbufp->recv_srcadr));
930                 sys_restricted++;
931                 return;
932         }
933
934 #ifdef SAVECONFIG
935         if (NULL == saveconfigdir) {
936                 snprintf(reply, sizeof(reply),
937                          "saveconfig prohibited, no saveconfigdir configured");
938                 ctl_putdata(reply, strlen(reply), 0);
939                 ctl_flushpkt(0);
940                 NLOG(NLOG_SYSINFO)
941                         msyslog(LOG_NOTICE,
942                                 "saveconfig from %s rejected, no saveconfigdir",
943                                 stoa(&rbufp->recv_srcadr));
944                 return;
945         }
946
947         if (0 == reqend - reqpt)
948                 return;
949
950         strlcpy(filespec, reqpt, sizeof(filespec));
951         time(&now);
952
953         /*
954          * allow timestamping of the saved config filename with
955          * strftime() format such as:
956          *   ntpq -c "saveconfig ntp-%Y%m%d-%H%M%S.conf"
957          * XXX: Nice feature, but not too safe.
958          */
959         if (0 == strftime(filename, sizeof(filename), filespec,
960                                localtime(&now)))
961                 strlcpy(filename, filespec, sizeof(filename));
962
963         /* block directory/drive traversal */
964         /* TALOS-CAN-0062: block directory traversal for VMS, too */
965         if (NULL != strpbrk(filename, illegal_in_filename)) {
966                 snprintf(reply, sizeof(reply),
967                          "saveconfig does not allow directory in filename");
968                 ctl_putdata(reply, strlen(reply), 0);
969                 ctl_flushpkt(0);
970                 msyslog(LOG_NOTICE,
971                         "saveconfig with path from %s rejected",
972                         stoa(&rbufp->recv_srcadr));
973                 return;
974         }
975
976         snprintf(fullpath, sizeof(fullpath), "%s%s",
977                  saveconfigdir, filename);
978
979         fd = open(fullpath, O_CREAT | O_TRUNC | O_WRONLY,
980                   S_IRUSR | S_IWUSR);
981         if (-1 == fd)
982                 fptr = NULL;
983         else
984                 fptr = fdopen(fd, "w");
985
986         if (NULL == fptr || -1 == dump_all_config_trees(fptr, 1)) {
987                 snprintf(reply, sizeof(reply),
988                          "Unable to save configuration to file %s",
989                          filename);
990                 msyslog(LOG_ERR,
991                         "saveconfig %s from %s failed", filename,
992                         stoa(&rbufp->recv_srcadr));
993         } else {
994                 snprintf(reply, sizeof(reply),
995                          "Configuration saved to %s", filename);
996                 msyslog(LOG_NOTICE,
997                         "Configuration saved to %s (requested by %s)",
998                         fullpath, stoa(&rbufp->recv_srcadr));
999                 /*
1000                  * save the output filename in system variable
1001                  * savedconfig, retrieved with:
1002                  *   ntpq -c "rv 0 savedconfig"
1003                  */
1004                 snprintf(savedconfig, sizeof(savedconfig), "%s%s",
1005                          savedconfig_eq, filename);
1006                 set_sys_var(savedconfig, strlen(savedconfig) + 1, RO);
1007         }
1008
1009         if (NULL != fptr)
1010                 fclose(fptr);
1011 #else   /* !SAVECONFIG follows */
1012         snprintf(reply, sizeof(reply),
1013                  "saveconfig unavailable, configured with --disable-saveconfig");
1014 #endif
1015
1016         ctl_putdata(reply, strlen(reply), 0);
1017         ctl_flushpkt(0);
1018 }
1019
1020
1021 /*
1022  * process_control - process an incoming control message
1023  */
1024 void
1025 process_control(
1026         struct recvbuf *rbufp,
1027         int restrict_mask
1028         )
1029 {
1030         struct ntp_control *pkt;
1031         int req_count;
1032         int req_data;
1033         const struct ctl_proc *cc;
1034         keyid_t *pkid;
1035         int properlen;
1036         size_t maclen;
1037
1038         DPRINTF(3, ("in process_control()\n"));
1039
1040         /*
1041          * Save the addresses for error responses
1042          */
1043         numctlreq++;
1044         rmt_addr = &rbufp->recv_srcadr;
1045         lcl_inter = rbufp->dstadr;
1046         pkt = (struct ntp_control *)&rbufp->recv_pkt;
1047
1048         /*
1049          * If the length is less than required for the header, or
1050          * it is a response or a fragment, ignore this.
1051          */
1052         if (rbufp->recv_length < (int)CTL_HEADER_LEN
1053             || (CTL_RESPONSE | CTL_MORE | CTL_ERROR) & pkt->r_m_e_op
1054             || pkt->offset != 0) {
1055                 DPRINTF(1, ("invalid format in control packet\n"));
1056                 if (rbufp->recv_length < (int)CTL_HEADER_LEN)
1057                         numctltooshort++;
1058                 if (CTL_RESPONSE & pkt->r_m_e_op)
1059                         numctlinputresp++;
1060                 if (CTL_MORE & pkt->r_m_e_op)
1061                         numctlinputfrag++;
1062                 if (CTL_ERROR & pkt->r_m_e_op)
1063                         numctlinputerr++;
1064                 if (pkt->offset != 0)
1065                         numctlbadoffset++;
1066                 return;
1067         }
1068         res_version = PKT_VERSION(pkt->li_vn_mode);
1069         if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
1070                 DPRINTF(1, ("unknown version %d in control packet\n",
1071                             res_version));
1072                 numctlbadversion++;
1073                 return;
1074         }
1075
1076         /*
1077          * Pull enough data from the packet to make intelligent
1078          * responses
1079          */
1080         rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
1081                                          MODE_CONTROL);
1082         res_opcode = pkt->r_m_e_op;
1083         rpkt.sequence = pkt->sequence;
1084         rpkt.associd = pkt->associd;
1085         rpkt.status = 0;
1086         res_frags = 1;
1087         res_offset = 0;
1088         res_associd = htons(pkt->associd);
1089         res_async = FALSE;
1090         res_authenticate = FALSE;
1091         res_keyid = 0;
1092         res_authokay = FALSE;
1093         req_count = (int)ntohs(pkt->count);
1094         datanotbinflag = FALSE;
1095         datalinelen = 0;
1096         datasent = 0;
1097         datapt = rpkt.u.data;
1098         dataend = &rpkt.u.data[CTL_MAX_DATA_LEN];
1099
1100         if ((rbufp->recv_length & 0x3) != 0)
1101                 DPRINTF(3, ("Control packet length %d unrounded\n",
1102                             rbufp->recv_length));
1103
1104         /*
1105          * We're set up now. Make sure we've got at least enough
1106          * incoming data space to match the count.
1107          */
1108         req_data = rbufp->recv_length - CTL_HEADER_LEN;
1109         if (req_data < req_count || rbufp->recv_length & 0x3) {
1110                 ctl_error(CERR_BADFMT);
1111                 numctldatatooshort++;
1112                 return;
1113         }
1114
1115         properlen = req_count + CTL_HEADER_LEN;
1116         /* round up proper len to a 8 octet boundary */
1117
1118         properlen = (properlen + 7) & ~7;
1119         maclen = rbufp->recv_length - properlen;
1120         if ((rbufp->recv_length & 3) == 0 &&
1121             maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
1122             sys_authenticate) {
1123                 res_authenticate = TRUE;
1124                 pkid = (void *)((char *)pkt + properlen);
1125                 res_keyid = ntohl(*pkid);
1126                 DPRINTF(3, ("recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%zu\n",
1127                             rbufp->recv_length, properlen, res_keyid,
1128                             maclen));
1129
1130                 if (!authistrusted(res_keyid))
1131                         DPRINTF(3, ("invalid keyid %08x\n", res_keyid));
1132                 else if (authdecrypt(res_keyid, (u_int32 *)pkt,
1133                                      rbufp->recv_length - maclen,
1134                                      maclen)) {
1135                         res_authokay = TRUE;
1136                         DPRINTF(3, ("authenticated okay\n"));
1137                 } else {
1138                         res_keyid = 0;
1139                         DPRINTF(3, ("authentication failed\n"));
1140                 }
1141         }
1142
1143         /*
1144          * Set up translate pointers
1145          */
1146         reqpt = (char *)pkt->u.data;
1147         reqend = reqpt + req_count;
1148
1149         /*
1150          * Look for the opcode processor
1151          */
1152         for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
1153                 if (cc->control_code == res_opcode) {
1154                         DPRINTF(3, ("opcode %d, found command handler\n",
1155                                     res_opcode));
1156                         if (cc->flags == AUTH
1157                             && (!res_authokay
1158                                 || res_keyid != ctl_auth_keyid)) {
1159                                 ctl_error(CERR_PERMISSION);
1160                                 return;
1161                         }
1162                         (cc->handler)(rbufp, restrict_mask);
1163                         return;
1164                 }
1165         }
1166
1167         /*
1168          * Can't find this one, return an error.
1169          */
1170         numctlbadop++;
1171         ctl_error(CERR_BADOP);
1172         return;
1173 }
1174
1175
1176 /*
1177  * ctlpeerstatus - return a status word for this peer
1178  */
1179 u_short
1180 ctlpeerstatus(
1181         register struct peer *p
1182         )
1183 {
1184         u_short status;
1185
1186         status = p->status;
1187         if (FLAG_CONFIG & p->flags)
1188                 status |= CTL_PST_CONFIG;
1189         if (p->keyid)
1190                 status |= CTL_PST_AUTHENABLE;
1191         if (FLAG_AUTHENTIC & p->flags)
1192                 status |= CTL_PST_AUTHENTIC;
1193         if (p->reach)
1194                 status |= CTL_PST_REACH;
1195         if (MDF_TXONLY_MASK & p->cast_flags)
1196                 status |= CTL_PST_BCAST;
1197
1198         return CTL_PEER_STATUS(status, p->num_events, p->last_event);
1199 }
1200
1201
1202 /*
1203  * ctlclkstatus - return a status word for this clock
1204  */
1205 #ifdef REFCLOCK
1206 static u_short
1207 ctlclkstatus(
1208         struct refclockstat *pcs
1209         )
1210 {
1211         return CTL_PEER_STATUS(0, pcs->lastevent, pcs->currentstatus);
1212 }
1213 #endif
1214
1215
1216 /*
1217  * ctlsysstatus - return the system status word
1218  */
1219 u_short
1220 ctlsysstatus(void)
1221 {
1222         register u_char this_clock;
1223
1224         this_clock = CTL_SST_TS_UNSPEC;
1225 #ifdef REFCLOCK
1226         if (sys_peer != NULL) {
1227                 if (CTL_SST_TS_UNSPEC != sys_peer->sstclktype)
1228                         this_clock = sys_peer->sstclktype;
1229                 else if (sys_peer->refclktype < COUNTOF(clocktypes))
1230                         this_clock = clocktypes[sys_peer->refclktype];
1231         }
1232 #else /* REFCLOCK */
1233         if (sys_peer != 0)
1234                 this_clock = CTL_SST_TS_NTP;
1235 #endif /* REFCLOCK */
1236         return CTL_SYS_STATUS(sys_leap, this_clock, ctl_sys_num_events,
1237                               ctl_sys_last_event);
1238 }
1239
1240
1241 /*
1242  * ctl_flushpkt - write out the current packet and prepare
1243  *                another if necessary.
1244  */
1245 static void
1246 ctl_flushpkt(
1247         u_char more
1248         )
1249 {
1250         size_t i;
1251         size_t dlen;
1252         size_t sendlen;
1253         size_t maclen;
1254         size_t totlen;
1255         keyid_t keyid;
1256
1257         dlen = datapt - rpkt.u.data;
1258         if (!more && datanotbinflag && dlen + 2 < CTL_MAX_DATA_LEN) {
1259                 /*
1260                  * Big hack, output a trailing \r\n
1261                  */
1262                 *datapt++ = '\r';
1263                 *datapt++ = '\n';
1264                 dlen += 2;
1265         }
1266         sendlen = dlen + CTL_HEADER_LEN;
1267
1268         /*
1269          * Pad to a multiple of 32 bits
1270          */
1271         while (sendlen & 0x3) {
1272                 *datapt++ = '\0';
1273                 sendlen++;
1274         }
1275
1276         /*
1277          * Fill in the packet with the current info
1278          */
1279         rpkt.r_m_e_op = CTL_RESPONSE | more |
1280                         (res_opcode & CTL_OP_MASK);
1281         rpkt.count = htons((u_short)dlen);
1282         rpkt.offset = htons((u_short)res_offset);
1283         if (res_async) {
1284                 for (i = 0; i < COUNTOF(ctl_traps); i++) {
1285                         if (TRAP_INUSE & ctl_traps[i].tr_flags) {
1286                                 rpkt.li_vn_mode =
1287                                     PKT_LI_VN_MODE(
1288                                         sys_leap,
1289                                         ctl_traps[i].tr_version,
1290                                         MODE_CONTROL);
1291                                 rpkt.sequence =
1292                                     htons(ctl_traps[i].tr_sequence);
1293                                 sendpkt(&ctl_traps[i].tr_addr,
1294                                         ctl_traps[i].tr_localaddr, -4,
1295                                         (struct pkt *)&rpkt, sendlen);
1296                                 if (!more)
1297                                         ctl_traps[i].tr_sequence++;
1298                                 numasyncmsgs++;
1299                         }
1300                 }
1301         } else {
1302                 if (res_authenticate && sys_authenticate) {
1303                         totlen = sendlen;
1304                         /*
1305                          * If we are going to authenticate, then there
1306                          * is an additional requirement that the MAC
1307                          * begin on a 64 bit boundary.
1308                          */
1309                         while (totlen & 7) {
1310                                 *datapt++ = '\0';
1311                                 totlen++;
1312                         }
1313                         keyid = htonl(res_keyid);
1314                         memcpy(datapt, &keyid, sizeof(keyid));
1315                         maclen = authencrypt(res_keyid,
1316                                              (u_int32 *)&rpkt, totlen);
1317                         sendpkt(rmt_addr, lcl_inter, -5,
1318                                 (struct pkt *)&rpkt, totlen + maclen);
1319                 } else {
1320                         sendpkt(rmt_addr, lcl_inter, -6,
1321                                 (struct pkt *)&rpkt, sendlen);
1322                 }
1323                 if (more)
1324                         numctlfrags++;
1325                 else
1326                         numctlresponses++;
1327         }
1328
1329         /*
1330          * Set us up for another go around.
1331          */
1332         res_frags++;
1333         res_offset += dlen;
1334         datapt = rpkt.u.data;
1335 }
1336
1337
1338 /*
1339  * ctl_putdata - write data into the packet, fragmenting and starting
1340  * another if this one is full.
1341  */
1342 static void
1343 ctl_putdata(
1344         const char *dp,
1345         unsigned int dlen,
1346         int bin                 /* set to 1 when data is binary */
1347         )
1348 {
1349         int overhead;
1350         unsigned int currentlen;
1351
1352         overhead = 0;
1353         if (!bin) {
1354                 datanotbinflag = TRUE;
1355                 overhead = 3;
1356                 if (datasent) {
1357                         *datapt++ = ',';
1358                         datalinelen++;
1359                         if ((dlen + datalinelen + 1) >= MAXDATALINELEN) {
1360                                 *datapt++ = '\r';
1361                                 *datapt++ = '\n';
1362                                 datalinelen = 0;
1363                         } else {
1364                                 *datapt++ = ' ';
1365                                 datalinelen++;
1366                         }
1367                 }
1368         }
1369
1370         /*
1371          * Save room for trailing junk
1372          */
1373         while (dlen + overhead + datapt > dataend) {
1374                 /*
1375                  * Not enough room in this one, flush it out.
1376                  */
1377                 currentlen = MIN(dlen, (unsigned int)(dataend - datapt));
1378
1379                 memcpy(datapt, dp, currentlen);
1380
1381                 datapt += currentlen;
1382                 dp += currentlen;
1383                 dlen -= currentlen;
1384                 datalinelen += currentlen;
1385
1386                 ctl_flushpkt(CTL_MORE);
1387         }
1388
1389         memcpy(datapt, dp, dlen);
1390         datapt += dlen;
1391         datalinelen += dlen;
1392         datasent = TRUE;
1393 }
1394
1395
1396 /*
1397  * ctl_putstr - write a tagged string into the response packet
1398  *              in the form:
1399  *
1400  *              tag="data"
1401  *
1402  *              len is the data length excluding the NUL terminator,
1403  *              as in ctl_putstr("var", "value", strlen("value"));
1404  */
1405 static void
1406 ctl_putstr(
1407         const char *    tag,
1408         const char *    data,
1409         size_t          len
1410         )
1411 {
1412         char buffer[512];
1413         char *cp;
1414         size_t tl;
1415
1416         tl = strlen(tag);
1417         memcpy(buffer, tag, tl);
1418         cp = buffer + tl;
1419         if (len > 0) {
1420                 INSIST(tl + 3 + len <= sizeof(buffer));
1421                 *cp++ = '=';
1422                 *cp++ = '"';
1423                 memcpy(cp, data, len);
1424                 cp += len;
1425                 *cp++ = '"';
1426         }
1427         ctl_putdata(buffer, (u_int)(cp - buffer), 0);
1428 }
1429
1430
1431 /*
1432  * ctl_putunqstr - write a tagged string into the response packet
1433  *                 in the form:
1434  *
1435  *                 tag=data
1436  *
1437  *      len is the data length excluding the NUL terminator.
1438  *      data must not contain a comma or whitespace.
1439  */
1440 static void
1441 ctl_putunqstr(
1442         const char *    tag,
1443         const char *    data,
1444         size_t          len
1445         )
1446 {
1447         char buffer[512];
1448         char *cp;
1449         size_t tl;
1450
1451         tl = strlen(tag);
1452         memcpy(buffer, tag, tl);
1453         cp = buffer + tl;
1454         if (len > 0) {
1455                 INSIST(tl + 1 + len <= sizeof(buffer));
1456                 *cp++ = '=';
1457                 memcpy(cp, data, len);
1458                 cp += len;
1459         }
1460         ctl_putdata(buffer, (u_int)(cp - buffer), 0);
1461 }
1462
1463
1464 /*
1465  * ctl_putdblf - write a tagged, signed double into the response packet
1466  */
1467 static void
1468 ctl_putdblf(
1469         const char *    tag,
1470         int             use_f,
1471         int             precision,
1472         double          d
1473         )
1474 {
1475         char *cp;
1476         const char *cq;
1477         char buffer[200];
1478
1479         cp = buffer;
1480         cq = tag;
1481         while (*cq != '\0')
1482                 *cp++ = *cq++;
1483         *cp++ = '=';
1484         INSIST((size_t)(cp - buffer) < sizeof(buffer));
1485         snprintf(cp, sizeof(buffer) - (cp - buffer), use_f ? "%.*f" : "%.*g",
1486             precision, d);
1487         cp += strlen(cp);
1488         ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1489 }
1490
1491 /*
1492  * ctl_putuint - write a tagged unsigned integer into the response
1493  */
1494 static void
1495 ctl_putuint(
1496         const char *tag,
1497         u_long uval
1498         )
1499 {
1500         register char *cp;
1501         register const char *cq;
1502         char buffer[200];
1503
1504         cp = buffer;
1505         cq = tag;
1506         while (*cq != '\0')
1507                 *cp++ = *cq++;
1508
1509         *cp++ = '=';
1510         INSIST((cp - buffer) < (int)sizeof(buffer));
1511         snprintf(cp, sizeof(buffer) - (cp - buffer), "%lu", uval);
1512         cp += strlen(cp);
1513         ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1514 }
1515
1516 /*
1517  * ctl_putcal - write a decoded calendar data into the response
1518  */
1519 static void
1520 ctl_putcal(
1521         const char *tag,
1522         const struct calendar *pcal
1523         )
1524 {
1525         char buffer[100];
1526         unsigned numch;
1527
1528         numch = snprintf(buffer, sizeof(buffer),
1529                         "%s=%04d%02d%02d%02d%02d",
1530                         tag,
1531                         pcal->year,
1532                         pcal->month,
1533                         pcal->monthday,
1534                         pcal->hour,
1535                         pcal->minute
1536                         );
1537         INSIST(numch < sizeof(buffer));
1538         ctl_putdata(buffer, numch, 0);
1539
1540         return;
1541 }
1542
1543 /*
1544  * ctl_putfs - write a decoded filestamp into the response
1545  */
1546 static void
1547 ctl_putfs(
1548         const char *tag,
1549         tstamp_t uval
1550         )
1551 {
1552         register char *cp;
1553         register const char *cq;
1554         char buffer[200];
1555         struct tm *tm = NULL;
1556         time_t fstamp;
1557
1558         cp = buffer;
1559         cq = tag;
1560         while (*cq != '\0')
1561                 *cp++ = *cq++;
1562
1563         *cp++ = '=';
1564         fstamp = uval - JAN_1970;
1565         tm = gmtime(&fstamp);
1566         if (NULL ==  tm)
1567                 return;
1568         INSIST((cp - buffer) < (int)sizeof(buffer));
1569         snprintf(cp, sizeof(buffer) - (cp - buffer),
1570                  "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
1571                  tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
1572         cp += strlen(cp);
1573         ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1574 }
1575
1576
1577 /*
1578  * ctl_puthex - write a tagged unsigned integer, in hex, into the
1579  * response
1580  */
1581 static void
1582 ctl_puthex(
1583         const char *tag,
1584         u_long uval
1585         )
1586 {
1587         register char *cp;
1588         register const char *cq;
1589         char buffer[200];
1590
1591         cp = buffer;
1592         cq = tag;
1593         while (*cq != '\0')
1594                 *cp++ = *cq++;
1595
1596         *cp++ = '=';
1597         INSIST((cp - buffer) < (int)sizeof(buffer));
1598         snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%lx", uval);
1599         cp += strlen(cp);
1600         ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
1601 }
1602
1603
1604 /*
1605  * ctl_putint - write a tagged signed integer into the response
1606  */
1607 static void
1608 ctl_putint(
1609         const char *tag,
1610         long ival
1611         )
1612 {
1613         register char *cp;
1614         register const char *cq;
1615         char buffer[200];
1616
1617         cp = buffer;
1618         cq = tag;
1619         while (*cq != '\0')
1620                 *cp++ = *cq++;
1621
1622         *cp++ = '=';
1623         INSIST((cp - buffer) < (int)sizeof(buffer));
1624         snprintf(cp, sizeof(buffer) - (cp - buffer), "%ld", ival);
1625         cp += strlen(cp);
1626         ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1627 }
1628
1629
1630 /*
1631  * ctl_putts - write a tagged timestamp, in hex, into the response
1632  */
1633 static void
1634 ctl_putts(
1635         const char *tag,
1636         l_fp *ts
1637         )
1638 {
1639         register char *cp;
1640         register const char *cq;
1641         char buffer[200];
1642
1643         cp = buffer;
1644         cq = tag;
1645         while (*cq != '\0')
1646                 *cp++ = *cq++;
1647
1648         *cp++ = '=';
1649         INSIST((size_t)(cp - buffer) < sizeof(buffer));
1650         snprintf(cp, sizeof(buffer) - (cp - buffer), "0x%08x.%08x",
1651                  (u_int)ts->l_ui, (u_int)ts->l_uf);
1652         cp += strlen(cp);
1653         ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
1654 }
1655
1656
1657 /*
1658  * ctl_putadr - write an IP address into the response
1659  */
1660 static void
1661 ctl_putadr(
1662         const char *tag,
1663         u_int32 addr32,
1664         sockaddr_u *addr
1665         )
1666 {
1667         register char *cp;
1668         register const char *cq;
1669         char buffer[200];
1670
1671         cp = buffer;
1672         cq = tag;
1673         while (*cq != '\0')
1674                 *cp++ = *cq++;
1675
1676         *cp++ = '=';
1677         if (NULL == addr)
1678                 cq = numtoa(addr32);
1679         else
1680                 cq = stoa(addr);
1681         INSIST((cp - buffer) < (int)sizeof(buffer));
1682         snprintf(cp, sizeof(buffer) - (cp - buffer), "%s", cq);
1683         cp += strlen(cp);
1684         ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1685 }
1686
1687
1688 /*
1689  * ctl_putrefid - send a u_int32 refid as printable text
1690  */
1691 static void
1692 ctl_putrefid(
1693         const char *    tag,
1694         u_int32         refid
1695         )
1696 {
1697         char    output[16];
1698         char *  optr;
1699         char *  oplim;
1700         char *  iptr;
1701         char *  iplim;
1702         char *  past_eq;
1703
1704         optr = output;
1705         oplim = output + sizeof(output);
1706         while (optr < oplim && '\0' != *tag)
1707                 *optr++ = *tag++;
1708         if (optr < oplim) {
1709                 *optr++ = '=';
1710                 past_eq = optr;
1711         }
1712         if (!(optr < oplim))
1713                 return;
1714         iptr = (char *)&refid;
1715         iplim = iptr + sizeof(refid);
1716         for ( ; optr < oplim && iptr < iplim && '\0' != *iptr;
1717              iptr++, optr++)
1718                 if (isprint((int)*iptr))
1719                         *optr = *iptr;
1720                 else
1721                         *optr = '.';
1722         if (!(optr <= oplim))
1723                 optr = past_eq;
1724         ctl_putdata(output, (u_int)(optr - output), FALSE);
1725 }
1726
1727
1728 /*
1729  * ctl_putarray - write a tagged eight element double array into the response
1730  */
1731 static void
1732 ctl_putarray(
1733         const char *tag,
1734         double *arr,
1735         int start
1736         )
1737 {
1738         register char *cp;
1739         register const char *cq;
1740         char buffer[200];
1741         int i;
1742         cp = buffer;
1743         cq = tag;
1744         while (*cq != '\0')
1745                 *cp++ = *cq++;
1746         *cp++ = '=';
1747         i = start;
1748         do {
1749                 if (i == 0)
1750                         i = NTP_SHIFT;
1751                 i--;
1752                 INSIST((cp - buffer) < (int)sizeof(buffer));
1753                 snprintf(cp, sizeof(buffer) - (cp - buffer),
1754                          " %.2f", arr[i] * 1e3);
1755                 cp += strlen(cp);
1756         } while (i != start);
1757         ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
1758 }
1759
1760
1761 /*
1762  * ctl_putsys - output a system variable
1763  */
1764 static void
1765 ctl_putsys(
1766         int varid
1767         )
1768 {
1769         l_fp tmp;
1770         char str[256];
1771         u_int u;
1772         double kb;
1773         double dtemp;
1774         const char *ss;
1775 #ifdef AUTOKEY
1776         struct cert_info *cp;
1777 #endif  /* AUTOKEY */
1778 #ifdef KERNEL_PLL
1779         static struct timex ntx;
1780         static u_long ntp_adjtime_time;
1781
1782         static const double to_ms =
1783 # ifdef STA_NANO
1784                 1.0e-6; /* nsec to msec */
1785 # else
1786                 1.0e-3; /* usec to msec */
1787 # endif
1788
1789         /*
1790          * CS_K_* variables depend on up-to-date output of ntp_adjtime()
1791          */
1792         if (CS_KERN_FIRST <= varid && varid <= CS_KERN_LAST &&
1793             current_time != ntp_adjtime_time) {
1794                 ZERO(ntx);
1795                 if (ntp_adjtime(&ntx) < 0)
1796                         msyslog(LOG_ERR, "ntp_adjtime() for mode 6 query failed: %m");
1797                 else
1798                         ntp_adjtime_time = current_time;
1799         }
1800 #endif  /* KERNEL_PLL */
1801
1802         switch (varid) {
1803
1804         case CS_LEAP:
1805                 ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
1806                 break;
1807
1808         case CS_STRATUM:
1809                 ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
1810                 break;
1811
1812         case CS_PRECISION:
1813                 ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
1814                 break;
1815
1816         case CS_ROOTDELAY:
1817                 ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
1818                            1e3);
1819                 break;
1820
1821         case CS_ROOTDISPERSION:
1822                 ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
1823                            sys_rootdisp * 1e3);
1824                 break;
1825
1826         case CS_REFID:
1827                 if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
1828                         ctl_putadr(sys_var[varid].text, sys_refid, NULL);
1829                 else
1830                         ctl_putrefid(sys_var[varid].text, sys_refid);
1831                 break;
1832
1833         case CS_REFTIME:
1834                 ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
1835                 break;
1836
1837         case CS_POLL:
1838                 ctl_putuint(sys_var[CS_POLL].text, sys_poll);
1839                 break;
1840
1841         case CS_PEERID:
1842                 if (sys_peer == NULL)
1843                         ctl_putuint(sys_var[CS_PEERID].text, 0);
1844                 else
1845                         ctl_putuint(sys_var[CS_PEERID].text,
1846                                     sys_peer->associd);
1847                 break;
1848
1849         case CS_PEERADR:
1850                 if (sys_peer != NULL && sys_peer->dstadr != NULL)
1851                         ss = sptoa(&sys_peer->srcadr);
1852                 else
1853                         ss = "0.0.0.0:0";
1854                 ctl_putunqstr(sys_var[CS_PEERADR].text, ss, strlen(ss));
1855                 break;
1856
1857         case CS_PEERMODE:
1858                 u = (sys_peer != NULL)
1859                         ? sys_peer->hmode
1860                         : MODE_UNSPEC;
1861                 ctl_putuint(sys_var[CS_PEERMODE].text, u);
1862                 break;
1863
1864         case CS_OFFSET:
1865                 ctl_putdbl6(sys_var[CS_OFFSET].text, last_offset * 1e3);
1866                 break;
1867
1868         case CS_DRIFT:
1869                 ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
1870                 break;
1871
1872         case CS_JITTER:
1873                 ctl_putdbl6(sys_var[CS_JITTER].text, sys_jitter * 1e3);
1874                 break;
1875
1876         case CS_ERROR:
1877                 ctl_putdbl(sys_var[CS_ERROR].text, clock_jitter * 1e3);
1878                 break;
1879
1880         case CS_CLOCK:
1881                 get_systime(&tmp);
1882                 ctl_putts(sys_var[CS_CLOCK].text, &tmp);
1883                 break;
1884
1885         case CS_PROCESSOR:
1886 #ifndef HAVE_UNAME
1887                 ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
1888                            sizeof(str_processor) - 1);
1889 #else
1890                 ctl_putstr(sys_var[CS_PROCESSOR].text,
1891                            utsnamebuf.machine, strlen(utsnamebuf.machine));
1892 #endif /* HAVE_UNAME */
1893                 break;
1894
1895         case CS_SYSTEM:
1896 #ifndef HAVE_UNAME
1897                 ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
1898                            sizeof(str_system) - 1);
1899 #else
1900                 snprintf(str, sizeof(str), "%s/%s", utsnamebuf.sysname,
1901                          utsnamebuf.release);
1902                 ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
1903 #endif /* HAVE_UNAME */
1904                 break;
1905
1906         case CS_VERSION:
1907                 ctl_putstr(sys_var[CS_VERSION].text, Version,
1908                            strlen(Version));
1909                 break;
1910
1911         case CS_STABIL:
1912                 ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
1913                            1e6);
1914                 break;
1915
1916         case CS_VARLIST:
1917         {
1918                 char buf[CTL_MAX_DATA_LEN];
1919                 //buffPointer, firstElementPointer, buffEndPointer
1920                 char *buffp, *buffend;
1921                 int firstVarName;
1922                 const char *ss1;
1923                 int len;
1924                 const struct ctl_var *k;
1925
1926                 buffp = buf;
1927                 buffend = buf + sizeof(buf);
1928                 if (buffp + strlen(sys_var[CS_VARLIST].text) + 4 > buffend)
1929                         break;  /* really long var name */
1930
1931                 snprintf(buffp, sizeof(buf), "%s=\"",sys_var[CS_VARLIST].text);
1932                 buffp += strlen(buffp);
1933                 firstVarName = TRUE;
1934                 for (k = sys_var; !(k->flags & EOV); k++) {
1935                         if (k->flags & PADDING)
1936                                 continue;
1937                         len = strlen(k->text);
1938                         if (buffp + len + 1 >= buffend)
1939                                 break;
1940                         if (!firstVarName)
1941                                 *buffp++ = ',';
1942                         else
1943                                 firstVarName = FALSE;
1944                         memcpy(buffp, k->text, len);
1945                         buffp += len;
1946                 }
1947
1948                 for (k = ext_sys_var; k && !(k->flags & EOV); k++) {
1949                         if (k->flags & PADDING)
1950                                 continue;
1951                         if (NULL == k->text)
1952                                 continue;
1953                         ss1 = strchr(k->text, '=');
1954                         if (NULL == ss1)
1955                                 len = strlen(k->text);
1956                         else
1957                                 len = ss1 - k->text;
1958                         if (buffp + len + 1 >= buffend)
1959                                 break;
1960                         if (firstVarName) {
1961                                 *buffp++ = ',';
1962                                 firstVarName = FALSE;
1963                         }
1964                         memcpy(buffp, k->text,(unsigned)len);
1965                         buffp += len;
1966                 }
1967                 if (buffp + 2 >= buffend)
1968                         break;
1969
1970                 *buffp++ = '"';
1971                 *buffp = '\0';
1972
1973                 ctl_putdata(buf, (unsigned)( buffp - buf ), 0);
1974                 break;
1975         }
1976
1977         case CS_TAI:
1978                 if (sys_tai > 0)
1979                         ctl_putuint(sys_var[CS_TAI].text, sys_tai);
1980                 break;
1981
1982         case CS_LEAPTAB:
1983         {
1984                 leap_signature_t lsig;
1985                 leapsec_getsig(&lsig);
1986                 if (lsig.ttime > 0)
1987                         ctl_putfs(sys_var[CS_LEAPTAB].text, lsig.ttime);
1988                 break;
1989         }
1990
1991         case CS_LEAPEND:
1992         {
1993                 leap_signature_t lsig;
1994                 leapsec_getsig(&lsig);
1995                 if (lsig.etime > 0)
1996                         ctl_putfs(sys_var[CS_LEAPEND].text, lsig.etime);
1997                 break;
1998         }
1999
2000 #ifdef LEAP_SMEAR
2001         case CS_LEAPSMEARINTV:
2002                 if (leap_smear_intv > 0)
2003                         ctl_putuint(sys_var[CS_LEAPSMEARINTV].text, leap_smear_intv);
2004                 break;
2005
2006         case CS_LEAPSMEAROFFS:
2007                 if (leap_smear_intv > 0)
2008                         ctl_putdbl(sys_var[CS_LEAPSMEAROFFS].text,
2009                                    leap_smear.doffset * 1e3);
2010                 break;
2011 #endif  /* LEAP_SMEAR */
2012
2013         case CS_RATE:
2014                 ctl_putuint(sys_var[CS_RATE].text, ntp_minpoll);
2015                 break;
2016
2017         case CS_MRU_ENABLED:
2018                 ctl_puthex(sys_var[varid].text, mon_enabled);
2019                 break;
2020
2021         case CS_MRU_DEPTH:
2022                 ctl_putuint(sys_var[varid].text, mru_entries);
2023                 break;
2024
2025         case CS_MRU_MEM:
2026                 kb = mru_entries * (sizeof(mon_entry) / 1024.);
2027                 u = (u_int)kb;
2028                 if (kb - u >= 0.5)
2029                         u++;
2030                 ctl_putuint(sys_var[varid].text, u);
2031                 break;
2032
2033         case CS_MRU_DEEPEST:
2034                 ctl_putuint(sys_var[varid].text, mru_peakentries);
2035                 break;
2036
2037         case CS_MRU_MINDEPTH:
2038                 ctl_putuint(sys_var[varid].text, mru_mindepth);
2039                 break;
2040
2041         case CS_MRU_MAXAGE:
2042                 ctl_putint(sys_var[varid].text, mru_maxage);
2043                 break;
2044
2045         case CS_MRU_MAXDEPTH:
2046                 ctl_putuint(sys_var[varid].text, mru_maxdepth);
2047                 break;
2048
2049         case CS_MRU_MAXMEM:
2050                 kb = mru_maxdepth * (sizeof(mon_entry) / 1024.);
2051                 u = (u_int)kb;
2052                 if (kb - u >= 0.5)
2053                         u++;
2054                 ctl_putuint(sys_var[varid].text, u);
2055                 break;
2056
2057         case CS_SS_UPTIME:
2058                 ctl_putuint(sys_var[varid].text, current_time);
2059                 break;
2060
2061         case CS_SS_RESET:
2062                 ctl_putuint(sys_var[varid].text,
2063                             current_time - sys_stattime);
2064                 break;
2065
2066         case CS_SS_RECEIVED:
2067                 ctl_putuint(sys_var[varid].text, sys_received);
2068                 break;
2069
2070         case CS_SS_THISVER:
2071                 ctl_putuint(sys_var[varid].text, sys_newversion);
2072                 break;
2073
2074         case CS_SS_OLDVER:
2075                 ctl_putuint(sys_var[varid].text, sys_oldversion);
2076                 break;
2077
2078         case CS_SS_BADFORMAT:
2079                 ctl_putuint(sys_var[varid].text, sys_badlength);
2080                 break;
2081
2082         case CS_SS_BADAUTH:
2083                 ctl_putuint(sys_var[varid].text, sys_badauth);
2084                 break;
2085
2086         case CS_SS_DECLINED:
2087                 ctl_putuint(sys_var[varid].text, sys_declined);
2088                 break;
2089
2090         case CS_SS_RESTRICTED:
2091                 ctl_putuint(sys_var[varid].text, sys_restricted);
2092                 break;
2093
2094         case CS_SS_LIMITED:
2095                 ctl_putuint(sys_var[varid].text, sys_limitrejected);
2096                 break;
2097
2098         case CS_SS_KODSENT:
2099                 ctl_putuint(sys_var[varid].text, sys_kodsent);
2100                 break;
2101
2102         case CS_SS_PROCESSED:
2103                 ctl_putuint(sys_var[varid].text, sys_processed);
2104                 break;
2105
2106         case CS_BCASTDELAY:
2107                 ctl_putdbl(sys_var[varid].text, sys_bdelay * 1e3);
2108                 break;
2109
2110         case CS_AUTHDELAY:
2111                 LFPTOD(&sys_authdelay, dtemp);
2112                 ctl_putdbl(sys_var[varid].text, dtemp * 1e3);
2113                 break;
2114
2115         case CS_AUTHKEYS:
2116                 ctl_putuint(sys_var[varid].text, authnumkeys);
2117                 break;
2118
2119         case CS_AUTHFREEK:
2120                 ctl_putuint(sys_var[varid].text, authnumfreekeys);
2121                 break;
2122
2123         case CS_AUTHKLOOKUPS:
2124                 ctl_putuint(sys_var[varid].text, authkeylookups);
2125                 break;
2126
2127         case CS_AUTHKNOTFOUND:
2128                 ctl_putuint(sys_var[varid].text, authkeynotfound);
2129                 break;
2130
2131         case CS_AUTHKUNCACHED:
2132                 ctl_putuint(sys_var[varid].text, authkeyuncached);
2133                 break;
2134
2135         case CS_AUTHKEXPIRED:
2136                 ctl_putuint(sys_var[varid].text, authkeyexpired);
2137                 break;
2138
2139         case CS_AUTHENCRYPTS:
2140                 ctl_putuint(sys_var[varid].text, authencryptions);
2141                 break;
2142
2143         case CS_AUTHDECRYPTS:
2144                 ctl_putuint(sys_var[varid].text, authdecryptions);
2145                 break;
2146
2147         case CS_AUTHRESET:
2148                 ctl_putuint(sys_var[varid].text,
2149                             current_time - auth_timereset);
2150                 break;
2151
2152                 /*
2153                  * CTL_IF_KERNLOOP() puts a zero if the kernel loop is
2154                  * unavailable, otherwise calls putfunc with args.
2155                  */
2156 #ifndef KERNEL_PLL
2157 # define        CTL_IF_KERNLOOP(putfunc, args)  \
2158                 ctl_putint(sys_var[varid].text, 0)
2159 #else
2160 # define        CTL_IF_KERNLOOP(putfunc, args)  \
2161                 putfunc args
2162 #endif
2163
2164                 /*
2165                  * CTL_IF_KERNPPS() puts a zero if either the kernel
2166                  * loop is unavailable, or kernel hard PPS is not
2167                  * active, otherwise calls putfunc with args.
2168                  */
2169 #ifndef KERNEL_PLL
2170 # define        CTL_IF_KERNPPS(putfunc, args)   \
2171                 ctl_putint(sys_var[varid].text, 0)
2172 #else
2173 # define        CTL_IF_KERNPPS(putfunc, args)                   \
2174                 if (0 == ntx.shift)                             \
2175                         ctl_putint(sys_var[varid].text, 0);     \
2176                 else                                            \
2177                         putfunc args    /* no trailing ; */
2178 #endif
2179
2180         case CS_K_OFFSET:
2181                 CTL_IF_KERNLOOP(
2182                         ctl_putdblf,
2183                         (sys_var[varid].text, 0, -1, to_ms * ntx.offset)
2184                 );
2185                 break;
2186
2187         case CS_K_FREQ:
2188                 CTL_IF_KERNLOOP(
2189                         ctl_putsfp,
2190                         (sys_var[varid].text, ntx.freq)
2191                 );
2192                 break;
2193
2194         case CS_K_MAXERR:
2195                 CTL_IF_KERNLOOP(
2196                         ctl_putdblf,
2197                         (sys_var[varid].text, 0, 6,
2198                          to_ms * ntx.maxerror)
2199                 );
2200                 break;
2201
2202         case CS_K_ESTERR:
2203                 CTL_IF_KERNLOOP(
2204                         ctl_putdblf,
2205                         (sys_var[varid].text, 0, 6,
2206                          to_ms * ntx.esterror)
2207                 );
2208                 break;
2209
2210         case CS_K_STFLAGS:
2211 #ifndef KERNEL_PLL
2212                 ss = "";
2213 #else
2214                 ss = k_st_flags(ntx.status);
2215 #endif
2216                 ctl_putstr(sys_var[varid].text, ss, strlen(ss));
2217                 break;
2218
2219         case CS_K_TIMECONST:
2220                 CTL_IF_KERNLOOP(
2221                         ctl_putint,
2222                         (sys_var[varid].text, ntx.constant)
2223                 );
2224                 break;
2225
2226         case CS_K_PRECISION:
2227                 CTL_IF_KERNLOOP(
2228                         ctl_putdblf,
2229                         (sys_var[varid].text, 0, 6,
2230                             to_ms * ntx.precision)
2231                 );
2232                 break;
2233
2234         case CS_K_FREQTOL:
2235                 CTL_IF_KERNLOOP(
2236                         ctl_putsfp,
2237                         (sys_var[varid].text, ntx.tolerance)
2238                 );
2239                 break;
2240
2241         case CS_K_PPS_FREQ:
2242                 CTL_IF_KERNPPS(
2243                         ctl_putsfp,
2244                         (sys_var[varid].text, ntx.ppsfreq)
2245                 );
2246                 break;
2247
2248         case CS_K_PPS_STABIL:
2249                 CTL_IF_KERNPPS(
2250                         ctl_putsfp,
2251                         (sys_var[varid].text, ntx.stabil)
2252                 );
2253                 break;
2254
2255         case CS_K_PPS_JITTER:
2256                 CTL_IF_KERNPPS(
2257                         ctl_putdbl,
2258                         (sys_var[varid].text, to_ms * ntx.jitter)
2259                 );
2260                 break;
2261
2262         case CS_K_PPS_CALIBDUR:
2263                 CTL_IF_KERNPPS(
2264                         ctl_putint,
2265                         (sys_var[varid].text, 1 << ntx.shift)
2266                 );
2267                 break;
2268
2269         case CS_K_PPS_CALIBS:
2270                 CTL_IF_KERNPPS(
2271                         ctl_putint,
2272                         (sys_var[varid].text, ntx.calcnt)
2273                 );
2274                 break;
2275
2276         case CS_K_PPS_CALIBERRS:
2277                 CTL_IF_KERNPPS(
2278                         ctl_putint,
2279                         (sys_var[varid].text, ntx.errcnt)
2280                 );
2281                 break;
2282
2283         case CS_K_PPS_JITEXC:
2284                 CTL_IF_KERNPPS(
2285                         ctl_putint,
2286                         (sys_var[varid].text, ntx.jitcnt)
2287                 );
2288                 break;
2289
2290         case CS_K_PPS_STBEXC:
2291                 CTL_IF_KERNPPS(
2292                         ctl_putint,
2293                         (sys_var[varid].text, ntx.stbcnt)
2294                 );
2295                 break;
2296
2297         case CS_IOSTATS_RESET:
2298                 ctl_putuint(sys_var[varid].text,
2299                             current_time - io_timereset);
2300                 break;
2301
2302         case CS_TOTAL_RBUF:
2303                 ctl_putuint(sys_var[varid].text, total_recvbuffs());
2304                 break;
2305
2306         case CS_FREE_RBUF:
2307                 ctl_putuint(sys_var[varid].text, free_recvbuffs());
2308                 break;
2309
2310         case CS_USED_RBUF:
2311                 ctl_putuint(sys_var[varid].text, full_recvbuffs());
2312                 break;
2313
2314         case CS_RBUF_LOWATER:
2315                 ctl_putuint(sys_var[varid].text, lowater_additions());
2316                 break;
2317
2318         case CS_IO_DROPPED:
2319                 ctl_putuint(sys_var[varid].text, packets_dropped);
2320                 break;
2321
2322         case CS_IO_IGNORED:
2323                 ctl_putuint(sys_var[varid].text, packets_ignored);
2324                 break;
2325
2326         case CS_IO_RECEIVED:
2327                 ctl_putuint(sys_var[varid].text, packets_received);
2328                 break;
2329
2330         case CS_IO_SENT:
2331                 ctl_putuint(sys_var[varid].text, packets_sent);
2332                 break;
2333
2334         case CS_IO_SENDFAILED:
2335                 ctl_putuint(sys_var[varid].text, packets_notsent);
2336                 break;
2337
2338         case CS_IO_WAKEUPS:
2339                 ctl_putuint(sys_var[varid].text, handler_calls);
2340                 break;
2341
2342         case CS_IO_GOODWAKEUPS:
2343                 ctl_putuint(sys_var[varid].text, handler_pkts);
2344                 break;
2345
2346         case CS_TIMERSTATS_RESET:
2347                 ctl_putuint(sys_var[varid].text,
2348                             current_time - timer_timereset);
2349                 break;
2350
2351         case CS_TIMER_OVERRUNS:
2352                 ctl_putuint(sys_var[varid].text, alarm_overflow);
2353                 break;
2354
2355         case CS_TIMER_XMTS:
2356                 ctl_putuint(sys_var[varid].text, timer_xmtcalls);
2357                 break;
2358
2359         case CS_FUZZ:
2360                 ctl_putdbl(sys_var[varid].text, sys_fuzz * 1e3);
2361                 break;
2362         case CS_WANDER_THRESH:
2363                 ctl_putdbl(sys_var[varid].text, wander_threshold * 1e6);
2364                 break;
2365 #ifdef AUTOKEY
2366         case CS_FLAGS:
2367                 if (crypto_flags)
2368                         ctl_puthex(sys_var[CS_FLAGS].text,
2369                             crypto_flags);
2370                 break;
2371
2372         case CS_DIGEST:
2373                 if (crypto_flags) {
2374                         strlcpy(str, OBJ_nid2ln(crypto_nid),
2375                             COUNTOF(str));
2376                         ctl_putstr(sys_var[CS_DIGEST].text, str,
2377                             strlen(str));
2378                 }
2379                 break;
2380
2381         case CS_SIGNATURE:
2382                 if (crypto_flags) {
2383                         const EVP_MD *dp;
2384
2385                         dp = EVP_get_digestbynid(crypto_flags >> 16);
2386                         strlcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)),
2387                             COUNTOF(str));
2388                         ctl_putstr(sys_var[CS_SIGNATURE].text, str,
2389                             strlen(str));
2390                 }
2391                 break;
2392
2393         case CS_HOST:
2394                 if (hostval.ptr != NULL)
2395                         ctl_putstr(sys_var[CS_HOST].text, hostval.ptr,
2396                             strlen(hostval.ptr));
2397                 break;
2398
2399         case CS_IDENT:
2400                 if (sys_ident != NULL)
2401                         ctl_putstr(sys_var[CS_IDENT].text, sys_ident,
2402                             strlen(sys_ident));
2403                 break;
2404
2405         case CS_CERTIF:
2406                 for (cp = cinfo; cp != NULL; cp = cp->link) {
2407                         snprintf(str, sizeof(str), "%s %s 0x%x",
2408                             cp->subject, cp->issuer, cp->flags);
2409                         ctl_putstr(sys_var[CS_CERTIF].text, str,
2410                             strlen(str));
2411                         ctl_putcal(sys_var[CS_REVTIME].text, &(cp->last));
2412                 }
2413                 break;
2414
2415         case CS_PUBLIC:
2416                 if (hostval.tstamp != 0)
2417                         ctl_putfs(sys_var[CS_PUBLIC].text,
2418                             ntohl(hostval.tstamp));
2419                 break;
2420 #endif  /* AUTOKEY */
2421
2422         default:
2423                 break;
2424         }
2425 }
2426
2427
2428 /*
2429  * ctl_putpeer - output a peer variable
2430  */
2431 static void
2432 ctl_putpeer(
2433         int id,
2434         struct peer *p
2435         )
2436 {
2437         char buf[CTL_MAX_DATA_LEN];
2438         char *s;
2439         char *t;
2440         char *be;
2441         int i;
2442         const struct ctl_var *k;
2443 #ifdef AUTOKEY
2444         struct autokey *ap;
2445         const EVP_MD *dp;
2446         const char *str;
2447 #endif  /* AUTOKEY */
2448
2449         switch (id) {
2450
2451         case CP_CONFIG:
2452                 ctl_putuint(peer_var[id].text,
2453                             !(FLAG_PREEMPT & p->flags));
2454                 break;
2455
2456         case CP_AUTHENABLE:
2457                 ctl_putuint(peer_var[id].text, !(p->keyid));
2458                 break;
2459
2460         case CP_AUTHENTIC:
2461                 ctl_putuint(peer_var[id].text,
2462                             !!(FLAG_AUTHENTIC & p->flags));
2463                 break;
2464
2465         case CP_SRCADR:
2466                 ctl_putadr(peer_var[id].text, 0, &p->srcadr);
2467                 break;
2468
2469         case CP_SRCPORT:
2470                 ctl_putuint(peer_var[id].text, SRCPORT(&p->srcadr));
2471                 break;
2472
2473         case CP_SRCHOST:
2474                 if (p->hostname != NULL)
2475                         ctl_putstr(peer_var[id].text, p->hostname,
2476                                    strlen(p->hostname));
2477                 break;
2478
2479         case CP_DSTADR:
2480                 ctl_putadr(peer_var[id].text, 0,
2481                            (p->dstadr != NULL)
2482                                 ? &p->dstadr->sin
2483                                 : NULL);
2484                 break;
2485
2486         case CP_DSTPORT:
2487                 ctl_putuint(peer_var[id].text,
2488                             (p->dstadr != NULL)
2489                                 ? SRCPORT(&p->dstadr->sin)
2490                                 : 0);
2491                 break;
2492
2493         case CP_IN:
2494                 if (p->r21 > 0.)
2495                         ctl_putdbl(peer_var[id].text, p->r21 / 1e3);
2496                 break;
2497
2498         case CP_OUT:
2499                 if (p->r34 > 0.)
2500                         ctl_putdbl(peer_var[id].text, p->r34 / 1e3);
2501                 break;
2502
2503         case CP_RATE:
2504                 ctl_putuint(peer_var[id].text, p->throttle);
2505                 break;
2506
2507         case CP_LEAP:
2508                 ctl_putuint(peer_var[id].text, p->leap);
2509                 break;
2510
2511         case CP_HMODE:
2512                 ctl_putuint(peer_var[id].text, p->hmode);
2513                 break;
2514
2515         case CP_STRATUM:
2516                 ctl_putuint(peer_var[id].text, p->stratum);
2517                 break;
2518
2519         case CP_PPOLL:
2520                 ctl_putuint(peer_var[id].text, p->ppoll);
2521                 break;
2522
2523         case CP_HPOLL:
2524                 ctl_putuint(peer_var[id].text, p->hpoll);
2525                 break;
2526
2527         case CP_PRECISION:
2528                 ctl_putint(peer_var[id].text, p->precision);
2529                 break;
2530
2531         case CP_ROOTDELAY:
2532                 ctl_putdbl(peer_var[id].text, p->rootdelay * 1e3);
2533                 break;
2534
2535         case CP_ROOTDISPERSION:
2536                 ctl_putdbl(peer_var[id].text, p->rootdisp * 1e3);
2537                 break;
2538
2539         case CP_REFID:
2540 #ifdef REFCLOCK
2541                 if (p->flags & FLAG_REFCLOCK) {
2542                         ctl_putrefid(peer_var[id].text, p->refid);
2543                         break;
2544                 }
2545 #endif
2546                 if (p->stratum > 1 && p->stratum < STRATUM_UNSPEC)
2547                         ctl_putadr(peer_var[id].text, p->refid,
2548                                    NULL);
2549                 else
2550                         ctl_putrefid(peer_var[id].text, p->refid);
2551                 break;
2552
2553         case CP_REFTIME:
2554                 ctl_putts(peer_var[id].text, &p->reftime);
2555                 break;
2556
2557         case CP_ORG:
2558                 ctl_putts(peer_var[id].text, &p->aorg);
2559                 break;
2560
2561         case CP_REC:
2562                 ctl_putts(peer_var[id].text, &p->dst);
2563                 break;
2564
2565         case CP_XMT:
2566                 if (p->xleave)
2567                         ctl_putdbl(peer_var[id].text, p->xleave * 1e3);
2568                 break;
2569
2570         case CP_BIAS:
2571                 if (p->bias != 0.)
2572                         ctl_putdbl(peer_var[id].text, p->bias * 1e3);
2573                 break;
2574
2575         case CP_REACH:
2576                 ctl_puthex(peer_var[id].text, p->reach);
2577                 break;
2578
2579         case CP_FLASH:
2580                 ctl_puthex(peer_var[id].text, p->flash);
2581                 break;
2582
2583         case CP_TTL:
2584 #ifdef REFCLOCK
2585                 if (p->flags & FLAG_REFCLOCK) {
2586                         ctl_putuint(peer_var[id].text, p->ttl);
2587                         break;
2588                 }
2589 #endif
2590                 if (p->ttl > 0 && p->ttl < COUNTOF(sys_ttl))
2591                         ctl_putint(peer_var[id].text,
2592                                    sys_ttl[p->ttl]);
2593                 break;
2594
2595         case CP_UNREACH:
2596                 ctl_putuint(peer_var[id].text, p->unreach);
2597                 break;
2598
2599         case CP_TIMER:
2600                 ctl_putuint(peer_var[id].text,
2601                             p->nextdate - current_time);
2602                 break;
2603
2604         case CP_DELAY:
2605                 ctl_putdbl(peer_var[id].text, p->delay * 1e3);
2606                 break;
2607
2608         case CP_OFFSET:
2609                 ctl_putdbl(peer_var[id].text, p->offset * 1e3);
2610                 break;
2611
2612         case CP_JITTER:
2613                 ctl_putdbl(peer_var[id].text, p->jitter * 1e3);
2614                 break;
2615
2616         case CP_DISPERSION:
2617                 ctl_putdbl(peer_var[id].text, p->disp * 1e3);
2618                 break;
2619
2620         case CP_KEYID:
2621                 if (p->keyid > NTP_MAXKEY)
2622                         ctl_puthex(peer_var[id].text, p->keyid);
2623                 else
2624                         ctl_putuint(peer_var[id].text, p->keyid);
2625                 break;
2626
2627         case CP_FILTDELAY:
2628                 ctl_putarray(peer_var[id].text, p->filter_delay,
2629                              p->filter_nextpt);
2630                 break;
2631
2632         case CP_FILTOFFSET:
2633                 ctl_putarray(peer_var[id].text, p->filter_offset,
2634                              p->filter_nextpt);
2635                 break;
2636
2637         case CP_FILTERROR:
2638                 ctl_putarray(peer_var[id].text, p->filter_disp,
2639                              p->filter_nextpt);
2640                 break;
2641
2642         case CP_PMODE:
2643                 ctl_putuint(peer_var[id].text, p->pmode);
2644                 break;
2645
2646         case CP_RECEIVED:
2647                 ctl_putuint(peer_var[id].text, p->received);
2648                 break;
2649
2650         case CP_SENT:
2651                 ctl_putuint(peer_var[id].text, p->sent);
2652                 break;
2653
2654         case CP_VARLIST:
2655                 s = buf;
2656                 be = buf + sizeof(buf);
2657                 if (strlen(peer_var[id].text) + 4 > sizeof(buf))
2658                         break;  /* really long var name */
2659
2660                 snprintf(s, sizeof(buf), "%s=\"", peer_var[id].text);
2661                 s += strlen(s);
2662                 t = s;
2663                 for (k = peer_var; !(EOV & k->flags); k++) {
2664                         if (PADDING & k->flags)
2665                                 continue;
2666                         i = strlen(k->text);
2667                         if (s + i + 1 >= be)
2668                                 break;
2669                         if (s != t)
2670                                 *s++ = ',';
2671                         memcpy(s, k->text, i);
2672                         s += i;
2673                 }
2674                 if (s + 2 < be) {
2675                         *s++ = '"';
2676                         *s = '\0';
2677                         ctl_putdata(buf, (u_int)(s - buf), 0);
2678                 }
2679                 break;
2680
2681         case CP_TIMEREC:
2682                 ctl_putuint(peer_var[id].text,
2683                             current_time - p->timereceived);
2684                 break;
2685
2686         case CP_TIMEREACH:
2687                 ctl_putuint(peer_var[id].text,
2688                             current_time - p->timereachable);
2689                 break;
2690
2691         case CP_BADAUTH:
2692                 ctl_putuint(peer_var[id].text, p->badauth);
2693                 break;
2694
2695         case CP_BOGUSORG:
2696                 ctl_putuint(peer_var[id].text, p->bogusorg);
2697                 break;
2698
2699         case CP_OLDPKT:
2700                 ctl_putuint(peer_var[id].text, p->oldpkt);
2701                 break;
2702
2703         case CP_SELDISP:
2704                 ctl_putuint(peer_var[id].text, p->seldisptoolarge);
2705                 break;
2706
2707         case CP_SELBROKEN:
2708                 ctl_putuint(peer_var[id].text, p->selbroken);
2709                 break;
2710
2711         case CP_CANDIDATE:
2712                 ctl_putuint(peer_var[id].text, p->status);
2713                 break;
2714 #ifdef AUTOKEY
2715         case CP_FLAGS:
2716                 if (p->crypto)
2717                         ctl_puthex(peer_var[id].text, p->crypto);
2718                 break;
2719
2720         case CP_SIGNATURE:
2721                 if (p->crypto) {
2722                         dp = EVP_get_digestbynid(p->crypto >> 16);
2723                         str = OBJ_nid2ln(EVP_MD_pkey_type(dp));
2724                         ctl_putstr(peer_var[id].text, str, strlen(str));
2725                 }
2726                 break;
2727
2728         case CP_HOST:
2729                 if (p->subject != NULL)
2730                         ctl_putstr(peer_var[id].text, p->subject,
2731                             strlen(p->subject));
2732                 break;
2733
2734         case CP_VALID:          /* not used */
2735                 break;
2736
2737         case CP_INITSEQ:
2738                 if (NULL == (ap = p->recval.ptr))
2739                         break;
2740
2741                 ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
2742                 ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
2743                 ctl_putfs(peer_var[CP_INITTSP].text,
2744                           ntohl(p->recval.tstamp));
2745                 break;
2746
2747         case CP_IDENT:
2748                 if (p->ident != NULL)
2749                         ctl_putstr(peer_var[id].text, p->ident,
2750                             strlen(p->ident));
2751                 break;
2752
2753
2754 #endif  /* AUTOKEY */
2755         }
2756 }
2757
2758
2759 #ifdef REFCLOCK
2760 /*
2761  * ctl_putclock - output clock variables
2762  */
2763 static void
2764 ctl_putclock(
2765         int id,
2766         struct refclockstat *pcs,
2767         int mustput
2768         )
2769 {
2770         char buf[CTL_MAX_DATA_LEN];
2771         char *s, *t, *be;
2772         const char *ss;
2773         int i;
2774         const struct ctl_var *k;
2775
2776         switch (id) {
2777
2778         case CC_TYPE:
2779                 if (mustput || pcs->clockdesc == NULL
2780                     || *(pcs->clockdesc) == '\0') {
2781                         ctl_putuint(clock_var[id].text, pcs->type);
2782                 }
2783                 break;
2784         case CC_TIMECODE:
2785                 ctl_putstr(clock_var[id].text,
2786                            pcs->p_lastcode,
2787                            (unsigned)pcs->lencode);
2788                 break;
2789
2790         case CC_POLL:
2791                 ctl_putuint(clock_var[id].text, pcs->polls);
2792                 break;
2793
2794         case CC_NOREPLY:
2795                 ctl_putuint(clock_var[id].text,
2796                             pcs->noresponse);
2797                 break;
2798
2799         case CC_BADFORMAT:
2800                 ctl_putuint(clock_var[id].text,
2801                             pcs->badformat);
2802                 break;
2803
2804         case CC_BADDATA:
2805                 ctl_putuint(clock_var[id].text,
2806                             pcs->baddata);
2807                 break;
2808
2809         case CC_FUDGETIME1:
2810                 if (mustput || (pcs->haveflags & CLK_HAVETIME1))
2811                         ctl_putdbl(clock_var[id].text,
2812                                    pcs->fudgetime1 * 1e3);
2813                 break;
2814
2815         case CC_FUDGETIME2:
2816                 if (mustput || (pcs->haveflags & CLK_HAVETIME2))
2817                         ctl_putdbl(clock_var[id].text,
2818                                    pcs->fudgetime2 * 1e3);
2819                 break;
2820
2821         case CC_FUDGEVAL1:
2822                 if (mustput || (pcs->haveflags & CLK_HAVEVAL1))
2823                         ctl_putint(clock_var[id].text,
2824                                    pcs->fudgeval1);
2825                 break;
2826
2827         case CC_FUDGEVAL2:
2828                 if (mustput || (pcs->haveflags & CLK_HAVEVAL2)) {
2829                         if (pcs->fudgeval1 > 1)
2830                                 ctl_putadr(clock_var[id].text,
2831                                            pcs->fudgeval2, NULL);
2832                         else
2833                                 ctl_putrefid(clock_var[id].text,
2834                                              pcs->fudgeval2);
2835                 }
2836                 break;
2837
2838         case CC_FLAGS:
2839                 ctl_putuint(clock_var[id].text, pcs->flags);
2840                 break;
2841
2842         case CC_DEVICE:
2843                 if (pcs->clockdesc == NULL ||
2844                     *(pcs->clockdesc) == '\0') {
2845                         if (mustput)
2846                                 ctl_putstr(clock_var[id].text,
2847                                            "", 0);
2848                 } else {
2849                         ctl_putstr(clock_var[id].text,
2850                                    pcs->clockdesc,
2851                                    strlen(pcs->clockdesc));
2852                 }
2853                 break;
2854
2855         case CC_VARLIST:
2856                 s = buf;
2857                 be = buf + sizeof(buf);
2858                 if (strlen(clock_var[CC_VARLIST].text) + 4 >
2859                     sizeof(buf))
2860                         break;  /* really long var name */
2861
2862                 snprintf(s, sizeof(buf), "%s=\"",
2863                          clock_var[CC_VARLIST].text);
2864                 s += strlen(s);
2865                 t = s;
2866
2867                 for (k = clock_var; !(EOV & k->flags); k++) {
2868                         if (PADDING & k->flags)
2869                                 continue;
2870
2871                         i = strlen(k->text);
2872                         if (s + i + 1 >= be)
2873                                 break;
2874
2875                         if (s != t)
2876                                 *s++ = ',';
2877                         memcpy(s, k->text, i);
2878                         s += i;
2879                 }
2880
2881                 for (k = pcs->kv_list; k && !(EOV & k->flags); k++) {
2882                         if (PADDING & k->flags)
2883                                 continue;
2884
2885                         ss = k->text;
2886                         if (NULL == ss)
2887                                 continue;
2888
2889                         while (*ss && *ss != '=')
2890                                 ss++;
2891                         i = ss - k->text;
2892                         if (s + i + 1 >= be)
2893                                 break;
2894
2895                         if (s != t)
2896                                 *s++ = ',';
2897                         memcpy(s, k->text, (unsigned)i);
2898                         s += i;
2899                         *s = '\0';
2900                 }
2901                 if (s + 2 >= be)
2902                         break;
2903
2904                 *s++ = '"';
2905                 *s = '\0';
2906                 ctl_putdata(buf, (unsigned)(s - buf), 0);
2907                 break;
2908         }
2909 }
2910 #endif
2911
2912
2913
2914 /*
2915  * ctl_getitem - get the next data item from the incoming packet
2916  */
2917 static const struct ctl_var *
2918 ctl_getitem(
2919         const struct ctl_var *var_list,
2920         char **data
2921         )
2922 {
2923         static const struct ctl_var eol = { 0, EOV, NULL };
2924         static char buf[128];
2925         static u_long quiet_until;
2926         const struct ctl_var *v;
2927         const char *pch;
2928         char *cp;
2929         char *tp;
2930
2931         /*
2932          * Delete leading commas and white space
2933          */
2934         while (reqpt < reqend && (*reqpt == ',' ||
2935                                   isspace((unsigned char)*reqpt)))
2936                 reqpt++;
2937         if (reqpt >= reqend)
2938                 return NULL;
2939
2940         if (NULL == var_list)
2941                 return &eol;
2942
2943         /*
2944          * Look for a first character match on the tag.  If we find
2945          * one, see if it is a full match.
2946          */
2947         cp = reqpt;
2948         for (v = var_list; !(EOV & v->flags); v++) {
2949                 if (!(PADDING & v->flags) && *cp == *(v->text)) {
2950                         pch = v->text;
2951                         while ('\0' != *pch && '=' != *pch && cp < reqend
2952                                && *cp == *pch) {
2953                                 cp++;
2954                                 pch++;
2955                         }
2956                         if ('\0' == *pch || '=' == *pch) {
2957                                 while (cp < reqend && isspace((u_char)*cp))
2958                                         cp++;
2959                                 if (cp == reqend || ',' == *cp) {
2960                                         buf[0] = '\0';
2961                                         *data = buf;
2962                                         if (cp < reqend)
2963                                                 cp++;
2964                                         reqpt = cp;
2965                                         return v;
2966                                 }
2967                                 if ('=' == *cp) {
2968                                         cp++;
2969                                         tp = buf;
2970                                         while (cp < reqend && isspace((u_char)*cp))
2971                                                 cp++;
2972                                         while (cp < reqend && *cp != ',') {
2973                                                 *tp++ = *cp++;
2974                                                 if ((size_t)(tp - buf) >= sizeof(buf)) {
2975                                                         ctl_error(CERR_BADFMT);
2976                                                         numctlbadpkts++;
2977                                                         NLOG(NLOG_SYSEVENT)
2978                                                                 if (quiet_until <= current_time) {
2979                                                                         quiet_until = current_time + 300;
2980                                                                         msyslog(LOG_WARNING,
2981 "Possible 'ntpdx' exploit from %s#%u (possibly spoofed)", stoa(rmt_addr), SRCPORT(rmt_addr));
2982                                                                 }
2983                                                         return NULL;
2984                                                 }
2985                                         }
2986                                         if (cp < reqend)
2987                                                 cp++;
2988                                         *tp-- = '\0';
2989                                         while (tp >= buf && isspace((u_char)*tp))
2990                                                 *tp-- = '\0';
2991                                         reqpt = cp;
2992                                         *data = buf;
2993                                         return v;
2994                                 }
2995                         }
2996                         cp = reqpt;
2997                 }
2998         }
2999         return v;
3000 }
3001
3002
3003 /*
3004  * control_unspec - response to an unspecified op-code
3005  */
3006 /*ARGSUSED*/
3007 static void
3008 control_unspec(
3009         struct recvbuf *rbufp,
3010         int restrict_mask
3011         )
3012 {
3013         struct peer *peer;
3014
3015         /*
3016          * What is an appropriate response to an unspecified op-code?
3017          * I return no errors and no data, unless a specified assocation
3018          * doesn't exist.
3019          */
3020         if (res_associd) {
3021                 peer = findpeerbyassoc(res_associd);
3022                 if (NULL == peer) {
3023                         ctl_error(CERR_BADASSOC);
3024                         return;
3025                 }
3026                 rpkt.status = htons(ctlpeerstatus(peer));
3027         } else
3028                 rpkt.status = htons(ctlsysstatus());
3029         ctl_flushpkt(0);
3030 }
3031
3032
3033 /*
3034  * read_status - return either a list of associd's, or a particular
3035  * peer's status.
3036  */
3037 /*ARGSUSED*/
3038 static void
3039 read_status(
3040         struct recvbuf *rbufp,
3041         int restrict_mask
3042         )
3043 {
3044         struct peer *peer;
3045         const u_char *cp;
3046         size_t n;
3047         /* a_st holds association ID, status pairs alternating */
3048         u_short a_st[CTL_MAX_DATA_LEN / sizeof(u_short)];
3049
3050 #ifdef DEBUG
3051         if (debug > 2)
3052                 printf("read_status: ID %d\n", res_associd);
3053 #endif
3054         /*
3055          * Two choices here. If the specified association ID is
3056          * zero we return all known assocation ID's.  Otherwise
3057          * we return a bunch of stuff about the particular peer.
3058          */
3059         if (res_associd) {
3060                 peer = findpeerbyassoc(res_associd);
3061                 if (NULL == peer) {
3062                         ctl_error(CERR_BADASSOC);
3063                         return;
3064                 }
3065                 rpkt.status = htons(ctlpeerstatus(peer));
3066                 if (res_authokay)
3067                         peer->num_events = 0;
3068                 /*
3069                  * For now, output everything we know about the
3070                  * peer. May be more selective later.
3071                  */
3072                 for (cp = def_peer_var; *cp != 0; cp++)
3073                         ctl_putpeer((int)*cp, peer);
3074                 ctl_flushpkt(0);
3075                 return;
3076         }
3077         n = 0;
3078         rpkt.status = htons(ctlsysstatus());
3079         for (peer = peer_list; peer != NULL; peer = peer->p_link) {
3080                 a_st[n++] = htons(peer->associd);
3081                 a_st[n++] = htons(ctlpeerstatus(peer));
3082                 /* two entries each loop iteration, so n + 1 */
3083                 if (n + 1 >= COUNTOF(a_st)) {
3084                         ctl_putdata((void *)a_st, n * sizeof(a_st[0]),
3085                                     1);
3086                         n = 0;
3087                 }
3088         }
3089         if (n)
3090                 ctl_putdata((void *)a_st, n * sizeof(a_st[0]), 1);
3091         ctl_flushpkt(0);
3092 }
3093
3094
3095 /*
3096  * read_peervars - half of read_variables() implementation
3097  */
3098 static void
3099 read_peervars(void)
3100 {
3101         const struct ctl_var *v;
3102         struct peer *peer;
3103         const u_char *cp;
3104         size_t i;
3105         char *  valuep;
3106         u_char  wants[CP_MAXCODE + 1];
3107         u_int   gotvar;
3108
3109         /*
3110          * Wants info for a particular peer. See if we know
3111          * the guy.
3112          */
3113         peer = findpeerbyassoc(res_associd);
3114         if (NULL == peer) {
3115                 ctl_error(CERR_BADASSOC);
3116                 return;
3117         }
3118         rpkt.status = htons(ctlpeerstatus(peer));
3119         if (res_authokay)
3120                 peer->num_events = 0;
3121         ZERO(wants);
3122         gotvar = 0;
3123         while (NULL != (v = ctl_getitem(peer_var, &valuep))) {
3124                 if (v->flags & EOV) {
3125                         ctl_error(CERR_UNKNOWNVAR);
3126                         return;
3127                 }
3128                 INSIST(v->code < COUNTOF(wants));
3129                 wants[v->code] = 1;
3130                 gotvar = 1;
3131         }
3132         if (gotvar) {
3133                 for (i = 1; i < COUNTOF(wants); i++)
3134                         if (wants[i])
3135                                 ctl_putpeer(i, peer);
3136         } else
3137                 for (cp = def_peer_var; *cp != 0; cp++)
3138                         ctl_putpeer((int)*cp, peer);
3139         ctl_flushpkt(0);
3140 }
3141
3142
3143 /*
3144  * read_sysvars - half of read_variables() implementation
3145  */
3146 static void
3147 read_sysvars(void)
3148 {
3149         const struct ctl_var *v;
3150         struct ctl_var *kv;
3151         u_int   n;
3152         u_int   gotvar;
3153         const u_char *cs;
3154         char *  valuep;
3155         const char * pch;
3156         u_char *wants;
3157         size_t  wants_count;
3158
3159         /*
3160          * Wants system variables. Figure out which he wants
3161          * and give them to him.
3162          */
3163         rpkt.status = htons(ctlsysstatus());
3164         if (res_authokay)
3165                 ctl_sys_num_events = 0;
3166         wants_count = CS_MAXCODE + 1 + count_var(ext_sys_var);
3167         wants = emalloc_zero(wants_count);
3168         gotvar = 0;
3169         while (NULL != (v = ctl_getitem(sys_var, &valuep))) {
3170                 if (!(EOV & v->flags)) {
3171                         INSIST(v->code < wants_count);
3172                         wants[v->code] = 1;
3173                         gotvar = 1;
3174                 } else {
3175                         v = ctl_getitem(ext_sys_var, &valuep);
3176                         INSIST(v != NULL);
3177                         if (EOV & v->flags) {
3178                                 ctl_error(CERR_UNKNOWNVAR);
3179                                 free(wants);
3180                                 return;
3181                         }
3182                         n = v->code + CS_MAXCODE + 1;
3183                         INSIST(n < wants_count);
3184                         wants[n] = 1;
3185                         gotvar = 1;
3186                 }
3187         }
3188         if (gotvar) {
3189                 for (n = 1; n <= CS_MAXCODE; n++)
3190                         if (wants[n])
3191                                 ctl_putsys(n);
3192                 for (n = 0; n + CS_MAXCODE + 1 < wants_count; n++)
3193                         if (wants[n + CS_MAXCODE + 1]) {
3194                                 pch = ext_sys_var[n].text;
3195                                 ctl_putdata(pch, strlen(pch), 0);
3196                         }
3197         } else {
3198                 for (cs = def_sys_var; *cs != 0; cs++)
3199                         ctl_putsys((int)*cs);
3200                 for (kv = ext_sys_var; kv && !(EOV & kv->flags); kv++)
3201                         if (DEF & kv->flags)
3202                                 ctl_putdata(kv->text, strlen(kv->text),
3203                                             0);
3204         }
3205         free(wants);
3206         ctl_flushpkt(0);
3207 }
3208
3209
3210 /*
3211  * read_variables - return the variables the caller asks for
3212  */
3213 /*ARGSUSED*/
3214 static void
3215 read_variables(
3216         struct recvbuf *rbufp,
3217         int restrict_mask
3218         )
3219 {
3220         if (res_associd)
3221                 read_peervars();
3222         else
3223                 read_sysvars();
3224 }
3225
3226
3227 /*
3228  * write_variables - write into variables. We only allow leap bit
3229  * writing this way.
3230  */
3231 /*ARGSUSED*/
3232 static void
3233 write_variables(
3234         struct recvbuf *rbufp,
3235         int restrict_mask
3236         )
3237 {
3238         const struct ctl_var *v;
3239         int ext_var;
3240         char *valuep;
3241         long val;
3242         size_t octets;
3243         char *vareqv;
3244         const char *t;
3245         char *tt;
3246
3247         val = 0;
3248         /*
3249          * If he's trying to write into a peer tell him no way
3250          */
3251         if (res_associd != 0) {
3252                 ctl_error(CERR_PERMISSION);
3253                 return;
3254         }
3255
3256         /*
3257          * Set status
3258          */
3259         rpkt.status = htons(ctlsysstatus());
3260
3261         /*
3262          * Look through the variables. Dump out at the first sign of
3263          * trouble.
3264          */
3265         while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
3266                 ext_var = 0;
3267                 if (v->flags & EOV) {
3268                         if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
3269                             0) {
3270                                 if (v->flags & EOV) {
3271                                         ctl_error(CERR_UNKNOWNVAR);
3272                                         return;
3273                                 }
3274                                 ext_var = 1;
3275                         } else {
3276                                 break;
3277                         }
3278                 }
3279                 if (!(v->flags & CAN_WRITE)) {
3280                         ctl_error(CERR_PERMISSION);
3281                         return;
3282                 }
3283                 if (!ext_var && (*valuep == '\0' || !atoint(valuep,
3284                                                             &val))) {
3285                         ctl_error(CERR_BADFMT);
3286                         return;
3287                 }
3288                 if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
3289                         ctl_error(CERR_BADVALUE);
3290                         return;
3291                 }
3292
3293                 if (ext_var) {
3294                         octets = strlen(v->text) + strlen(valuep) + 2;
3295                         vareqv = emalloc(octets);
3296                         tt = vareqv;
3297                         t = v->text;
3298                         while (*t && *t != '=')
3299                                 *tt++ = *t++;
3300                         *tt++ = '=';
3301                         memcpy(tt, valuep, 1 + strlen(valuep));
3302                         set_sys_var(vareqv, 1 + strlen(vareqv), v->flags);
3303                         free(vareqv);
3304                 } else {
3305                         ctl_error(CERR_UNSPEC); /* really */
3306                         return;
3307                 }
3308         }
3309
3310         /*
3311          * If we got anything, do it. xxx nothing to do ***
3312          */
3313         /*
3314           if (leapind != ~0 || leapwarn != ~0) {
3315           if (!leap_setleap((int)leapind, (int)leapwarn)) {
3316           ctl_error(CERR_PERMISSION);
3317           return;
3318           }
3319           }
3320         */
3321         ctl_flushpkt(0);
3322 }
3323
3324
3325 /*
3326  * configure() processes ntpq :config/config-from-file, allowing
3327  *              generic runtime reconfiguration.
3328  */
3329 static void configure(
3330         struct recvbuf *rbufp,
3331         int restrict_mask
3332         )
3333 {
3334         size_t data_count;
3335         int retval;
3336
3337         /* I haven't yet implemented changes to an existing association.
3338          * Hence check if the association id is 0
3339          */
3340         if (res_associd != 0) {
3341                 ctl_error(CERR_BADVALUE);
3342                 return;
3343         }
3344
3345         if (RES_NOMODIFY & restrict_mask) {
3346                 snprintf(remote_config.err_msg,
3347                          sizeof(remote_config.err_msg),
3348                          "runtime configuration prohibited by restrict ... nomodify");
3349                 ctl_putdata(remote_config.err_msg,
3350                             strlen(remote_config.err_msg), 0);
3351                 ctl_flushpkt(0);
3352                 NLOG(NLOG_SYSINFO)
3353                         msyslog(LOG_NOTICE,
3354                                 "runtime config from %s rejected due to nomodify restriction",
3355                                 stoa(&rbufp->recv_srcadr));
3356                 sys_restricted++;
3357                 return;
3358         }
3359
3360         /* Initialize the remote config buffer */
3361         data_count = remoteconfig_cmdlength(reqpt, reqend);
3362
3363         if (data_count > sizeof(remote_config.buffer) - 2) {
3364                 snprintf(remote_config.err_msg,
3365                          sizeof(remote_config.err_msg),
3366                          "runtime configuration failed: request too long");
3367                 ctl_putdata(remote_config.err_msg,
3368                             strlen(remote_config.err_msg), 0);
3369                 ctl_flushpkt(0);
3370                 msyslog(LOG_NOTICE,
3371                         "runtime config from %s rejected: request too long",
3372                         stoa(&rbufp->recv_srcadr));
3373                 return;
3374         }
3375         /* Bug 2853 -- check if all characters were acceptable */
3376         if (data_count != (size_t)(reqend - reqpt)) {
3377                 snprintf(remote_config.err_msg,
3378                          sizeof(remote_config.err_msg),
3379                          "runtime configuration failed: request contains an unprintable character");
3380                 ctl_putdata(remote_config.err_msg,
3381                             strlen(remote_config.err_msg), 0);
3382                 ctl_flushpkt(0);
3383                 msyslog(LOG_NOTICE,
3384                         "runtime config from %s rejected: request contains an unprintable character: %0x",
3385                         stoa(&rbufp->recv_srcadr),
3386                         reqpt[data_count]);
3387                 return;
3388         }
3389
3390         memcpy(remote_config.buffer, reqpt, data_count);
3391         /* The buffer has no trailing linefeed or NUL right now. For
3392          * logging, we do not want a newline, so we do that first after
3393          * adding the necessary NUL byte.
3394          */
3395         remote_config.buffer[data_count] = '\0';
3396         DPRINTF(1, ("Got Remote Configuration Command: %s\n",
3397                 remote_config.buffer));
3398         msyslog(LOG_NOTICE, "%s config: %s",
3399                 stoa(&rbufp->recv_srcadr),
3400                 remote_config.buffer);
3401
3402         /* Now we have to make sure there is a NL/NUL sequence at the
3403          * end of the buffer before we parse it.
3404          */
3405         remote_config.buffer[data_count++] = '\n';
3406         remote_config.buffer[data_count] = '\0';
3407         remote_config.pos = 0;
3408         remote_config.err_pos = 0;
3409         remote_config.no_errors = 0;
3410         config_remotely(&rbufp->recv_srcadr);
3411
3412         /*
3413          * Check if errors were reported. If not, output 'Config
3414          * Succeeded'.  Else output the error count.  It would be nice
3415          * to output any parser error messages.
3416          */
3417         if (0 == remote_config.no_errors) {
3418                 retval = snprintf(remote_config.err_msg,
3419                                   sizeof(remote_config.err_msg),
3420                                   "Config Succeeded");
3421                 if (retval > 0)
3422                         remote_config.err_pos += retval;
3423         }
3424
3425         ctl_putdata(remote_config.err_msg, remote_config.err_pos, 0);
3426         ctl_flushpkt(0);
3427
3428         DPRINTF(1, ("Reply: %s\n", remote_config.err_msg));
3429
3430         if (remote_config.no_errors > 0)
3431                 msyslog(LOG_NOTICE, "%d error in %s config",
3432                         remote_config.no_errors,
3433                         stoa(&rbufp->recv_srcadr));
3434 }
3435
3436
3437 /*
3438  * derive_nonce - generate client-address-specific nonce value
3439  *                associated with a given timestamp.
3440  */
3441 static u_int32 derive_nonce(
3442         sockaddr_u *    addr,
3443         u_int32         ts_i,
3444         u_int32         ts_f
3445         )
3446 {
3447         static u_int32  salt[4];
3448         static u_long   last_salt_update;
3449         union d_tag {
3450                 u_char  digest[EVP_MAX_MD_SIZE];
3451                 u_int32 extract;
3452         }               d;
3453         EVP_MD_CTX      ctx;
3454         u_int           len;
3455
3456         while (!salt[0] || current_time - last_salt_update >= 3600) {
3457                 salt[0] = ntp_random();
3458                 salt[1] = ntp_random();
3459                 salt[2] = ntp_random();
3460                 salt[3] = ntp_random();
3461                 last_salt_update = current_time;
3462         }
3463
3464         EVP_DigestInit(&ctx, EVP_get_digestbynid(NID_md5));
3465         EVP_DigestUpdate(&ctx, salt, sizeof(salt));
3466         EVP_DigestUpdate(&ctx, &ts_i, sizeof(ts_i));
3467         EVP_DigestUpdate(&ctx, &ts_f, sizeof(ts_f));
3468         if (IS_IPV4(addr))
3469                 EVP_DigestUpdate(&ctx, &SOCK_ADDR4(addr),
3470                                  sizeof(SOCK_ADDR4(addr)));
3471         else
3472                 EVP_DigestUpdate(&ctx, &SOCK_ADDR6(addr),
3473                                  sizeof(SOCK_ADDR6(addr)));
3474         EVP_DigestUpdate(&ctx, &NSRCPORT(addr), sizeof(NSRCPORT(addr)));
3475         EVP_DigestUpdate(&ctx, salt, sizeof(salt));
3476         EVP_DigestFinal(&ctx, d.digest, &len);
3477
3478         return d.extract;
3479 }
3480
3481
3482 /*
3483  * generate_nonce - generate client-address-specific nonce string.
3484  */
3485 static void generate_nonce(
3486         struct recvbuf *        rbufp,
3487         char *                  nonce,
3488         size_t                  nonce_octets
3489         )
3490 {
3491         u_int32 derived;
3492
3493         derived = derive_nonce(&rbufp->recv_srcadr,
3494                                rbufp->recv_time.l_ui,
3495                                rbufp->recv_time.l_uf);
3496         snprintf(nonce, nonce_octets, "%08x%08x%08x",
3497                  rbufp->recv_time.l_ui, rbufp->recv_time.l_uf, derived);
3498 }
3499
3500
3501 /*
3502  * validate_nonce - validate client-address-specific nonce string.
3503  *
3504  * Returns TRUE if the local calculation of the nonce matches the
3505  * client-provided value and the timestamp is recent enough.
3506  */
3507 static int validate_nonce(
3508         const char *            pnonce,
3509         struct recvbuf *        rbufp
3510         )
3511 {
3512         u_int   ts_i;
3513         u_int   ts_f;
3514         l_fp    ts;
3515         l_fp    now_delta;
3516         u_int   supposed;
3517         u_int   derived;
3518
3519         if (3 != sscanf(pnonce, "%08x%08x%08x", &ts_i, &ts_f, &supposed))
3520                 return FALSE;
3521
3522         ts.l_ui = (u_int32)ts_i;
3523         ts.l_uf = (u_int32)ts_f;
3524         derived = derive_nonce(&rbufp->recv_srcadr, ts.l_ui, ts.l_uf);
3525         get_systime(&now_delta);
3526         L_SUB(&now_delta, &ts);
3527
3528         return (supposed == derived && now_delta.l_ui < 16);
3529 }
3530
3531
3532 /*
3533  * send_random_tag_value - send a randomly-generated three character
3534  *                         tag prefix, a '.', an index, a '=' and a
3535  *                         random integer value.
3536  *
3537  * To try to force clients to ignore unrecognized tags in mrulist,
3538  * reslist, and ifstats responses, the first and last rows are spiced
3539  * with randomly-generated tag names with correct .# index.  Make it
3540  * three characters knowing that none of the currently-used subscripted
3541  * tags have that length, avoiding the need to test for
3542  * tag collision.
3543  */
3544 static void
3545 send_random_tag_value(
3546         int     indx
3547         )
3548 {
3549         int     noise;
3550         char    buf[32];
3551
3552         noise = rand() ^ (rand() << 16);
3553         buf[0] = 'a' + noise % 26;
3554         noise >>= 5;
3555         buf[1] = 'a' + noise % 26;
3556         noise >>= 5;
3557         buf[2] = 'a' + noise % 26;
3558         noise >>= 5;
3559         buf[3] = '.';
3560         snprintf(&buf[4], sizeof(buf) - 4, "%d", indx);
3561         ctl_putuint(buf, noise);
3562 }
3563
3564
3565 /*
3566  * Send a MRU list entry in response to a "ntpq -c mrulist" operation.
3567  *
3568  * To keep clients honest about not depending on the order of values,
3569  * and thereby avoid being locked into ugly workarounds to maintain
3570  * backward compatibility later as new fields are added to the response,
3571  * the order is random.
3572  */
3573 static void
3574 send_mru_entry(
3575         mon_entry *     mon,
3576         int             count
3577         )
3578 {
3579         const char first_fmt[] =        "first.%d";
3580         const char ct_fmt[] =           "ct.%d";
3581         const char mv_fmt[] =           "mv.%d";
3582         const char rs_fmt[] =           "rs.%d";
3583         char    tag[32];
3584         u_char  sent[6]; /* 6 tag=value pairs */
3585         u_int32 noise;
3586         u_int   which;
3587         u_int   remaining;
3588         const char * pch;
3589
3590         remaining = COUNTOF(sent);
3591         ZERO(sent);
3592         noise = (u_int32)(rand() ^ (rand() << 16));
3593         while (remaining > 0) {
3594                 which = (noise & 7) % COUNTOF(sent);
3595                 noise >>= 3;
3596                 while (sent[which])
3597                         which = (which + 1) % COUNTOF(sent);
3598
3599                 switch (which) {
3600
3601                 case 0:
3602                         snprintf(tag, sizeof(tag), addr_fmt, count);
3603                         pch = sptoa(&mon->rmtadr);
3604                         ctl_putunqstr(tag, pch, strlen(pch));
3605                         break;
3606
3607                 case 1:
3608                         snprintf(tag, sizeof(tag), last_fmt, count);
3609                         ctl_putts(tag, &mon->last);
3610                         break;
3611
3612                 case 2:
3613                         snprintf(tag, sizeof(tag), first_fmt, count);
3614                         ctl_putts(tag, &mon->first);
3615                         break;
3616
3617                 case 3:
3618                         snprintf(tag, sizeof(tag), ct_fmt, count);
3619                         ctl_putint(tag, mon->count);
3620                         break;
3621
3622                 case 4:
3623                         snprintf(tag, sizeof(tag), mv_fmt, count);
3624                         ctl_putuint(tag, mon->vn_mode);
3625                         break;
3626
3627                 case 5:
3628                         snprintf(tag, sizeof(tag), rs_fmt, count);
3629                         ctl_puthex(tag, mon->flags);
3630                         break;
3631                 }
3632                 sent[which] = TRUE;
3633                 remaining--;
3634         }
3635 }
3636
3637
3638 /*
3639  * read_mru_list - supports ntpq's mrulist command.
3640  *
3641  * The challenge here is to match ntpdc's monlist functionality without
3642  * being limited to hundreds of entries returned total, and without
3643  * requiring state on the server.  If state were required, ntpq's
3644  * mrulist command would require authentication.
3645  *
3646  * The approach was suggested by Ry Jones.  A finite and variable number
3647  * of entries are retrieved per request, to avoid having responses with
3648  * such large numbers of packets that socket buffers are overflowed and
3649  * packets lost.  The entries are retrieved oldest-first, taking into
3650  * account that the MRU list will be changing between each request.  We
3651  * can expect to see duplicate entries for addresses updated in the MRU
3652  * list during the fetch operation.  In the end, the client can assemble
3653  * a close approximation of the MRU list at the point in time the last
3654  * response was sent by ntpd.  The only difference is it may be longer,
3655  * containing some number of oldest entries which have since been
3656  * reclaimed.  If necessary, the protocol could be extended to zap those
3657  * from the client snapshot at the end, but so far that doesn't seem
3658  * useful.
3659  *
3660  * To accomodate the changing MRU list, the starting point for requests
3661  * after the first request is supplied as a series of last seen
3662  * timestamps and associated addresses, the newest ones the client has
3663  * received.  As long as at least one of those entries hasn't been
3664  * bumped to the head of the MRU list, ntpd can pick up at that point.
3665  * Otherwise, the request is failed and it is up to ntpq to back up and
3666  * provide the next newest entry's timestamps and addresses, conceivably
3667  * backing up all the way to the starting point.
3668  *
3669  * input parameters:
3670  *      nonce=          Regurgitated nonce retrieved by the client
3671  *                      previously using CTL_OP_REQ_NONCE, demonstrating
3672  *                      ability to receive traffic sent to its address.
3673  *      frags=          Limit on datagrams (fragments) in response.  Used
3674  *                      by newer ntpq versions instead of limit= when
3675  *                      retrieving multiple entries.
3676  *      limit=          Limit on MRU entries returned.  One of frags= or
3677  *                      limit= must be provided.
3678  *                      limit=1 is a special case:  Instead of fetching
3679  *                      beginning with the supplied starting point's
3680  *                      newer neighbor, fetch the supplied entry, and
3681  *                      in that case the #.last timestamp can be zero.
3682  *                      This enables fetching a single entry by IP
3683  *                      address.  When limit is not one and frags= is
3684  *                      provided, the fragment limit controls.
3685  *      mincount=       (decimal) Return entries with count >= mincount.
3686  *      laddr=          Return entries associated with the server's IP
3687  *                      address given.  No port specification is needed,
3688  *                      and any supplied is ignored.
3689  *      resall=         0x-prefixed hex restrict bits which must all be
3690  *                      lit for an MRU entry to be included.
3691  *                      Has precedence over any resany=.
3692  *      resany=         0x-prefixed hex restrict bits, at least one of
3693  *                      which must be list for an MRU entry to be
3694  *                      included.
3695  *      last.0=         0x-prefixed hex l_fp timestamp of newest entry
3696  *                      which client previously received.
3697  *      addr.0=         text of newest entry's IP address and port,
3698  *                      IPv6 addresses in bracketed form: [::]:123
3699  *      last.1=         timestamp of 2nd newest entry client has.
3700  *      addr.1=         address of 2nd newest entry.
3701  *      [...]
3702  *
3703  * ntpq provides as many last/addr pairs as will fit in a single request
3704  * packet, except for the first request in a MRU fetch operation.
3705  *
3706  * The response begins with a new nonce value to be used for any
3707  * followup request.  Following the nonce is the next newer entry than
3708  * referred to by last.0 and addr.0, if the "0" entry has not been
3709  * bumped to the front.  If it has, the first entry returned will be the
3710  * next entry newer than referred to by last.1 and addr.1, and so on.
3711  * If none of the referenced entries remain unchanged, the request fails
3712  * and ntpq backs up to the next earlier set of entries to resync.
3713  *
3714  * Except for the first response, the response begins with confirmation
3715  * of the entry that precedes the first additional entry provided:
3716  *
3717  *      last.older=     hex l_fp timestamp matching one of the input
3718  *                      .last timestamps, which entry now precedes the
3719  *                      response 0. entry in the MRU list.
3720  *      addr.older=     text of address corresponding to older.last.
3721  *
3722  * And in any case, a successful response contains sets of values
3723  * comprising entries, with the oldest numbered 0 and incrementing from
3724  * there:
3725  *
3726  *      addr.#          text of IPv4 or IPv6 address and port
3727  *      last.#          hex l_fp timestamp of last receipt
3728  *      first.#         hex l_fp timestamp of first receipt
3729  *      ct.#            count of packets received
3730  *      mv.#            mode and version
3731  *      rs.#            restriction mask (RES_* bits)
3732  *
3733  * Note the code currently assumes there are no valid three letter
3734  * tags sent with each row, and needs to be adjusted if that changes.
3735  *
3736  * The client should accept the values in any order, and ignore .#
3737  * values which it does not understand, to allow a smooth path to
3738  * future changes without requiring a new opcode.  Clients can rely
3739  * on all *.0 values preceding any *.1 values, that is all values for
3740  * a given index number are together in the response.
3741  *
3742  * The end of the response list is noted with one or two tag=value
3743  * pairs.  Unconditionally:
3744  *
3745  *      now=            0x-prefixed l_fp timestamp at the server marking
3746  *                      the end of the operation.
3747  *
3748  * If any entries were returned, now= is followed by:
3749  *
3750  *      last.newest=    hex l_fp identical to last.# of the prior
3751  *                      entry.
3752  */
3753 static void read_mru_list(
3754         struct recvbuf *rbufp,
3755         int restrict_mask
3756         )
3757 {
3758         const char              nonce_text[] =          "nonce";
3759         const char              frags_text[] =          "frags";
3760         const char              limit_text[] =          "limit";
3761         const char              mincount_text[] =       "mincount";
3762         const char              resall_text[] =         "resall";
3763         const char              resany_text[] =         "resany";
3764         const char              maxlstint_text[] =      "maxlstint";
3765         const char              laddr_text[] =          "laddr";
3766         const char              resaxx_fmt[] =          "0x%hx";
3767         u_int                   limit;
3768         u_short                 frags;
3769         u_short                 resall;
3770         u_short                 resany;
3771         int                     mincount;
3772         u_int                   maxlstint;
3773         sockaddr_u              laddr;
3774         struct interface *      lcladr;
3775         u_int                   count;
3776         u_int                   ui;
3777         u_int                   uf;
3778         l_fp                    last[16];
3779         sockaddr_u              addr[COUNTOF(last)];
3780         char                    buf[128];
3781         struct ctl_var *        in_parms;
3782         const struct ctl_var *  v;
3783         char *                  val;
3784         const char *            pch;
3785         char *                  pnonce;
3786         int                     nonce_valid;
3787         size_t                  i;
3788         int                     priors;
3789         u_short                 hash;
3790         mon_entry *             mon;
3791         mon_entry *             prior_mon;
3792         l_fp                    now;
3793
3794         if (RES_NOMRULIST & restrict_mask) {
3795                 ctl_error(CERR_PERMISSION);
3796                 NLOG(NLOG_SYSINFO)
3797                         msyslog(LOG_NOTICE,
3798                                 "mrulist from %s rejected due to nomrulist restriction",
3799                                 stoa(&rbufp->recv_srcadr));
3800                 sys_restricted++;
3801                 return;
3802         }
3803         /*
3804          * fill in_parms var list with all possible input parameters.
3805          */
3806         in_parms = NULL;
3807         set_var(&in_parms, nonce_text, sizeof(nonce_text), 0);
3808         set_var(&in_parms, frags_text, sizeof(frags_text), 0);
3809         set_var(&in_parms, limit_text, sizeof(limit_text), 0);
3810         set_var(&in_parms, mincount_text, sizeof(mincount_text), 0);
3811         set_var(&in_parms, resall_text, sizeof(resall_text), 0);
3812         set_var(&in_parms, resany_text, sizeof(resany_text), 0);
3813         set_var(&in_parms, maxlstint_text, sizeof(maxlstint_text), 0);
3814         set_var(&in_parms, laddr_text, sizeof(laddr_text), 0);
3815         for (i = 0; i < COUNTOF(last); i++) {
3816                 snprintf(buf, sizeof(buf), last_fmt, (int)i);
3817                 set_var(&in_parms, buf, strlen(buf) + 1, 0);
3818                 snprintf(buf, sizeof(buf), addr_fmt, (int)i);
3819                 set_var(&in_parms, buf, strlen(buf) + 1, 0);
3820         }
3821
3822         /* decode input parms */
3823         pnonce = NULL;
3824         frags = 0;
3825         limit = 0;
3826         mincount = 0;
3827         resall = 0;
3828         resany = 0;
3829         maxlstint = 0;
3830         lcladr = NULL;
3831         priors = 0;
3832         ZERO(last);
3833         ZERO(addr);
3834
3835         while (NULL != (v = ctl_getitem(in_parms, &val)) &&
3836                !(EOV & v->flags)) {
3837                 int si;
3838
3839                 if (!strcmp(nonce_text, v->text)) {
3840                         if (NULL != pnonce)
3841                                 free(pnonce);
3842                         pnonce = estrdup(val);
3843                 } else if (!strcmp(frags_text, v->text)) {
3844                         sscanf(val, "%hu", &frags);
3845                 } else if (!strcmp(limit_text, v->text)) {
3846                         sscanf(val, "%u", &limit);
3847                 } else if (!strcmp(mincount_text, v->text)) {
3848                         if (1 != sscanf(val, "%d", &mincount) ||
3849                             mincount < 0)
3850                                 mincount = 0;
3851                 } else if (!strcmp(resall_text, v->text)) {
3852                         sscanf(val, resaxx_fmt, &resall);
3853                 } else if (!strcmp(resany_text, v->text)) {
3854                         sscanf(val, resaxx_fmt, &resany);
3855                 } else if (!strcmp(maxlstint_text, v->text)) {
3856                         sscanf(val, "%u", &maxlstint);
3857                 } else if (!strcmp(laddr_text, v->text)) {
3858                         if (decodenetnum(val, &laddr))
3859                                 lcladr = getinterface(&laddr, 0);
3860                 } else if (1 == sscanf(v->text, last_fmt, &si) &&
3861                            (size_t)si < COUNTOF(last)) {
3862                         if (2 == sscanf(val, "0x%08x.%08x", &ui, &uf)) {
3863                                 last[si].l_ui = ui;
3864                                 last[si].l_uf = uf;
3865                                 if (!SOCK_UNSPEC(&addr[si]) &&
3866                                     si == priors)
3867                                         priors++;
3868                         }
3869                 } else if (1 == sscanf(v->text, addr_fmt, &si) &&
3870                            (size_t)si < COUNTOF(addr)) {
3871                         if (decodenetnum(val, &addr[si])
3872                             && last[si].l_ui && last[si].l_uf &&
3873                             si == priors)
3874                                 priors++;
3875                 }
3876         }
3877         free_varlist(in_parms);
3878         in_parms = NULL;
3879
3880         /* return no responses until the nonce is validated */
3881         if (NULL == pnonce)
3882                 return;
3883
3884         nonce_valid = validate_nonce(pnonce, rbufp);
3885         free(pnonce);
3886         if (!nonce_valid)
3887                 return;
3888
3889         if ((0 == frags && !(0 < limit && limit <= MRU_ROW_LIMIT)) ||
3890             frags > MRU_FRAGS_LIMIT) {
3891                 ctl_error(CERR_BADVALUE);
3892                 return;
3893         }
3894
3895         /*
3896          * If either frags or limit is not given, use the max.
3897          */
3898         if (0 != frags && 0 == limit)
3899                 limit = UINT_MAX;
3900         else if (0 != limit && 0 == frags)
3901                 frags = MRU_FRAGS_LIMIT;
3902
3903         /*
3904          * Find the starting point if one was provided.
3905          */
3906         mon = NULL;
3907         for (i = 0; i < (size_t)priors; i++) {
3908                 hash = MON_HASH(&addr[i]);
3909                 for (mon = mon_hash[hash];
3910                      mon != NULL;
3911                      mon = mon->hash_next)
3912                         if (ADDR_PORT_EQ(&mon->rmtadr, &addr[i]))
3913                                 break;
3914                 if (mon != NULL) {
3915                         if (L_ISEQU(&mon->last, &last[i]))
3916                                 break;
3917                         mon = NULL;
3918                 }
3919         }
3920
3921         /* If a starting point was provided... */
3922         if (priors) {
3923                 /* and none could be found unmodified... */
3924                 if (NULL == mon) {
3925                         /* tell ntpq to try again with older entries */
3926                         ctl_error(CERR_UNKNOWNVAR);
3927                         return;
3928                 }
3929                 /* confirm the prior entry used as starting point */
3930                 ctl_putts("last.older", &mon->last);
3931                 pch = sptoa(&mon->rmtadr);
3932                 ctl_putunqstr("addr.older", pch, strlen(pch));
3933
3934                 /*
3935                  * Move on to the first entry the client doesn't have,
3936                  * except in the special case of a limit of one.  In
3937                  * that case return the starting point entry.
3938                  */
3939                 if (limit > 1)
3940                         mon = PREV_DLIST(mon_mru_list, mon, mru);
3941         } else {        /* start with the oldest */
3942                 mon = TAIL_DLIST(mon_mru_list, mru);
3943         }
3944
3945         /*
3946          * send up to limit= entries in up to frags= datagrams
3947          */
3948         get_systime(&now);
3949         generate_nonce(rbufp, buf, sizeof(buf));
3950         ctl_putunqstr("nonce", buf, strlen(buf));
3951         prior_mon = NULL;
3952         for (count = 0;
3953              mon != NULL && res_frags < frags && count < limit;
3954              mon = PREV_DLIST(mon_mru_list, mon, mru)) {
3955
3956                 if (mon->count < mincount)
3957                         continue;
3958                 if (resall && resall != (resall & mon->flags))
3959                         continue;
3960                 if (resany && !(resany & mon->flags))
3961                         continue;
3962                 if (maxlstint > 0 && now.l_ui - mon->last.l_ui >
3963                     maxlstint)
3964                         continue;
3965                 if (lcladr != NULL && mon->lcladr != lcladr)
3966                         continue;
3967
3968                 send_mru_entry(mon, count);
3969                 if (!count)
3970                         send_random_tag_value(0);
3971                 count++;
3972                 prior_mon = mon;
3973         }
3974
3975         /*
3976          * If this batch completes the MRU list, say so explicitly with
3977          * a now= l_fp timestamp.
3978          */
3979         if (NULL == mon) {
3980                 if (count > 1)
3981                         send_random_tag_value(count - 1);
3982                 ctl_putts("now", &now);
3983                 /* if any entries were returned confirm the last */
3984                 if (prior_mon != NULL)
3985                         ctl_putts("last.newest", &prior_mon->last);
3986         }
3987         ctl_flushpkt(0);
3988 }
3989
3990
3991 /*
3992  * Send a ifstats entry in response to a "ntpq -c ifstats" request.
3993  *
3994  * To keep clients honest about not depending on the order of values,
3995  * and thereby avoid being locked into ugly workarounds to maintain
3996  * backward compatibility later as new fields are added to the response,
3997  * the order is random.
3998  */
3999 static void
4000 send_ifstats_entry(
4001         endpt * la,
4002         u_int   ifnum
4003         )
4004 {
4005         const char addr_fmtu[] =        "addr.%u";
4006         const char bcast_fmt[] =        "bcast.%u";
4007         const char en_fmt[] =           "en.%u";        /* enabled */
4008         const char name_fmt[] =         "name.%u";
4009         const char flags_fmt[] =        "flags.%u";
4010         const char tl_fmt[] =           "tl.%u";        /* ttl */
4011         const char mc_fmt[] =           "mc.%u";        /* mcast count */
4012         const char rx_fmt[] =           "rx.%u";
4013         const char tx_fmt[] =           "tx.%u";
4014         const char txerr_fmt[] =        "txerr.%u";
4015         const char pc_fmt[] =           "pc.%u";        /* peer count */
4016         const char up_fmt[] =           "up.%u";        /* uptime */
4017         char    tag[32];
4018         u_char  sent[IFSTATS_FIELDS]; /* 12 tag=value pairs */
4019         int     noisebits;
4020         u_int32 noise;
4021         u_int   which;
4022         u_int   remaining;
4023         const char *pch;
4024
4025         remaining = COUNTOF(sent);
4026         ZERO(sent);
4027         noise = 0;
4028         noisebits = 0;
4029         while (remaining > 0) {
4030                 if (noisebits < 4) {
4031                         noise = rand() ^ (rand() << 16);
4032                         noisebits = 31;
4033                 }
4034                 which = (noise & 0xf) % COUNTOF(sent);
4035                 noise >>= 4;
4036                 noisebits -= 4;
4037
4038                 while (sent[which])
4039                         which = (which + 1) % COUNTOF(sent);
4040
4041                 switch (which) {
4042
4043                 case 0:
4044                         snprintf(tag, sizeof(tag), addr_fmtu, ifnum);
4045                         pch = sptoa(&la->sin);
4046                         ctl_putunqstr(tag, pch, strlen(pch));
4047                         break;
4048
4049                 case 1:
4050                         snprintf(tag, sizeof(tag), bcast_fmt, ifnum);
4051                         if (INT_BCASTOPEN & la->flags)
4052                                 pch = sptoa(&la->bcast);
4053                         else
4054                                 pch = "";
4055                         ctl_putunqstr(tag, pch, strlen(pch));
4056                         break;
4057
4058                 case 2:
4059                         snprintf(tag, sizeof(tag), en_fmt, ifnum);
4060                         ctl_putint(tag, !la->ignore_packets);
4061                         break;
4062
4063                 case 3:
4064                         snprintf(tag, sizeof(tag), name_fmt, ifnum);
4065                         ctl_putstr(tag, la->name, strlen(la->name));
4066                         break;
4067
4068                 case 4:
4069                         snprintf(tag, sizeof(tag), flags_fmt, ifnum);
4070                         ctl_puthex(tag, (u_int)la->flags);
4071                         break;
4072
4073                 case 5:
4074                         snprintf(tag, sizeof(tag), tl_fmt, ifnum);
4075                         ctl_putint(tag, la->last_ttl);
4076                         break;
4077
4078                 case 6:
4079                         snprintf(tag, sizeof(tag), mc_fmt, ifnum);
4080                         ctl_putint(tag, la->num_mcast);
4081                         break;
4082
4083                 case 7:
4084                         snprintf(tag, sizeof(tag), rx_fmt, ifnum);
4085                         ctl_putint(tag, la->received);
4086                         break;
4087
4088                 case 8:
4089                         snprintf(tag, sizeof(tag), tx_fmt, ifnum);
4090                         ctl_putint(tag, la->sent);
4091                         break;
4092
4093                 case 9:
4094                         snprintf(tag, sizeof(tag), txerr_fmt, ifnum);
4095                         ctl_putint(tag, la->notsent);
4096                         break;
4097
4098                 case 10:
4099                         snprintf(tag, sizeof(tag), pc_fmt, ifnum);
4100                         ctl_putuint(tag, la->peercnt);
4101                         break;
4102
4103                 case 11:
4104                         snprintf(tag, sizeof(tag), up_fmt, ifnum);
4105                         ctl_putuint(tag, current_time - la->starttime);
4106                         break;
4107                 }
4108                 sent[which] = TRUE;
4109                 remaining--;
4110         }
4111         send_random_tag_value((int)ifnum);
4112 }
4113
4114
4115 /*
4116  * read_ifstats - send statistics for each local address, exposed by
4117  *                ntpq -c ifstats
4118  */
4119 static void
4120 read_ifstats(
4121         struct recvbuf *        rbufp
4122         )
4123 {
4124         u_int   ifidx;
4125         endpt * la;
4126
4127         /*
4128          * loop over [0..sys_ifnum] searching ep_list for each
4129          * ifnum in turn.
4130          */
4131         for (ifidx = 0; ifidx < sys_ifnum; ifidx++) {
4132                 for (la = ep_list; la != NULL; la = la->elink)
4133                         if (ifidx == la->ifnum)
4134                                 break;
4135                 if (NULL == la)
4136                         continue;
4137                 /* return stats for one local address */
4138                 send_ifstats_entry(la, ifidx);
4139         }
4140         ctl_flushpkt(0);
4141 }
4142
4143 static void
4144 sockaddrs_from_restrict_u(
4145         sockaddr_u *    psaA,
4146         sockaddr_u *    psaM,
4147         restrict_u *    pres,
4148         int             ipv6
4149         )
4150 {
4151         ZERO(*psaA);
4152         ZERO(*psaM);
4153         if (!ipv6) {
4154                 psaA->sa.sa_family = AF_INET;
4155                 psaA->sa4.sin_addr.s_addr = htonl(pres->u.v4.addr);
4156                 psaM->sa.sa_family = AF_INET;
4157                 psaM->sa4.sin_addr.s_addr = htonl(pres->u.v4.mask);
4158         } else {
4159                 psaA->sa.sa_family = AF_INET6;
4160                 memcpy(&psaA->sa6.sin6_addr, &pres->u.v6.addr,
4161                        sizeof(psaA->sa6.sin6_addr));
4162                 psaM->sa.sa_family = AF_INET6;
4163                 memcpy(&psaM->sa6.sin6_addr, &pres->u.v6.mask,
4164                        sizeof(psaA->sa6.sin6_addr));
4165         }
4166 }
4167
4168
4169 /*
4170  * Send a restrict entry in response to a "ntpq -c reslist" request.
4171  *
4172  * To keep clients honest about not depending on the order of values,
4173  * and thereby avoid being locked into ugly workarounds to maintain
4174  * backward compatibility later as new fields are added to the response,
4175  * the order is random.
4176  */
4177 static void
4178 send_restrict_entry(
4179         restrict_u *    pres,
4180         int             ipv6,
4181         u_int           idx
4182         )
4183 {
4184         const char addr_fmtu[] =        "addr.%u";
4185         const char mask_fmtu[] =        "mask.%u";
4186         const char hits_fmt[] =         "hits.%u";
4187         const char flags_fmt[] =        "flags.%u";
4188         char            tag[32];
4189         u_char          sent[RESLIST_FIELDS]; /* 4 tag=value pairs */
4190         int             noisebits;
4191         u_int32         noise;
4192         u_int           which;
4193         u_int           remaining;
4194         sockaddr_u      addr;
4195         sockaddr_u      mask;
4196         const char *    pch;
4197         char *          buf;
4198         const char *    match_str;
4199         const char *    access_str;
4200
4201         sockaddrs_from_restrict_u(&addr, &mask, pres, ipv6);
4202         remaining = COUNTOF(sent);
4203         ZERO(sent);
4204         noise = 0;
4205         noisebits = 0;
4206         while (remaining > 0) {
4207                 if (noisebits < 2) {
4208                         noise = rand() ^ (rand() << 16);
4209                         noisebits = 31;
4210                 }
4211                 which = (noise & 0x3) % COUNTOF(sent);
4212                 noise >>= 2;
4213                 noisebits -= 2;
4214
4215                 while (sent[which])
4216                         which = (which + 1) % COUNTOF(sent);
4217
4218                 switch (which) {
4219
4220                 case 0:
4221                         snprintf(tag, sizeof(tag), addr_fmtu, idx);
4222                         pch = stoa(&addr);
4223                         ctl_putunqstr(tag, pch, strlen(pch));
4224                         break;
4225
4226                 case 1:
4227                         snprintf(tag, sizeof(tag), mask_fmtu, idx);
4228                         pch = stoa(&mask);
4229                         ctl_putunqstr(tag, pch, strlen(pch));
4230                         break;
4231
4232                 case 2:
4233                         snprintf(tag, sizeof(tag), hits_fmt, idx);
4234                         ctl_putuint(tag, pres->count);
4235                         break;
4236
4237                 case 3:
4238                         snprintf(tag, sizeof(tag), flags_fmt, idx);
4239                         match_str = res_match_flags(pres->mflags);
4240                         access_str = res_access_flags(pres->flags);
4241                         if ('\0' == match_str[0]) {
4242                                 pch = access_str;
4243                         } else {
4244                                 LIB_GETBUF(buf);
4245                                 snprintf(buf, LIB_BUFLENGTH, "%s %s",
4246                                          match_str, access_str);
4247                                 pch = buf;
4248                         }
4249                         ctl_putunqstr(tag, pch, strlen(pch));
4250                         break;
4251                 }
4252                 sent[which] = TRUE;
4253                 remaining--;
4254         }
4255         send_random_tag_value((int)idx);
4256 }
4257
4258
4259 static void
4260 send_restrict_list(
4261         restrict_u *    pres,
4262         int             ipv6,
4263         u_int *         pidx
4264         )
4265 {
4266         for ( ; pres != NULL; pres = pres->link) {
4267                 send_restrict_entry(pres, ipv6, *pidx);
4268                 (*pidx)++;
4269         }
4270 }
4271
4272
4273 /*
4274  * read_addr_restrictions - returns IPv4 and IPv6 access control lists
4275  */
4276 static void
4277 read_addr_restrictions(
4278         struct recvbuf *        rbufp
4279 )
4280 {
4281         u_int idx;
4282
4283         idx = 0;
4284         send_restrict_list(restrictlist4, FALSE, &idx);
4285         send_restrict_list(restrictlist6, TRUE, &idx);
4286         ctl_flushpkt(0);
4287 }
4288
4289
4290 /*
4291  * read_ordlist - CTL_OP_READ_ORDLIST_A for ntpq -c ifstats & reslist
4292  */
4293 static void
4294 read_ordlist(
4295         struct recvbuf *        rbufp,
4296         int                     restrict_mask
4297         )
4298 {
4299         const char ifstats_s[] = "ifstats";
4300         const size_t ifstats_chars = COUNTOF(ifstats_s) - 1;
4301         const char addr_rst_s[] = "addr_restrictions";
4302         const size_t a_r_chars = COUNTOF(addr_rst_s) - 1;
4303         struct ntp_control *    cpkt;
4304         u_short                 qdata_octets;
4305
4306         /*
4307          * CTL_OP_READ_ORDLIST_A was first named CTL_OP_READ_IFSTATS and
4308          * used only for ntpq -c ifstats.  With the addition of reslist
4309          * the same opcode was generalized to retrieve ordered lists
4310          * which require authentication.  The request data is empty or
4311          * contains "ifstats" (not null terminated) to retrieve local
4312          * addresses and associated stats.  It is "addr_restrictions"
4313          * to retrieve the IPv4 then IPv6 remote address restrictions,
4314          * which are access control lists.  Other request data return
4315          * CERR_UNKNOWNVAR.
4316          */
4317         cpkt = (struct ntp_control *)&rbufp->recv_pkt;
4318         qdata_octets = ntohs(cpkt->count);
4319         if (0 == qdata_octets || (ifstats_chars == qdata_octets &&
4320             !memcmp(ifstats_s, cpkt->u.data, ifstats_chars))) {
4321                 read_ifstats(rbufp);
4322                 return;
4323         }
4324         if (a_r_chars == qdata_octets &&
4325             !memcmp(addr_rst_s, cpkt->u.data, a_r_chars)) {
4326                 read_addr_restrictions(rbufp);
4327                 return;
4328         }
4329         ctl_error(CERR_UNKNOWNVAR);
4330 }
4331
4332
4333 /*
4334  * req_nonce - CTL_OP_REQ_NONCE for ntpq -c mrulist prerequisite.
4335  */
4336 static void req_nonce(
4337         struct recvbuf *        rbufp,
4338         int                     restrict_mask
4339         )
4340 {
4341         char    buf[64];
4342
4343         generate_nonce(rbufp, buf, sizeof(buf));
4344         ctl_putunqstr("nonce", buf, strlen(buf));
4345         ctl_flushpkt(0);
4346 }
4347
4348
4349 /*
4350  * read_clockstatus - return clock radio status
4351  */
4352 /*ARGSUSED*/
4353 static void
4354 read_clockstatus(
4355         struct recvbuf *rbufp,
4356         int restrict_mask
4357         )
4358 {
4359 #ifndef REFCLOCK
4360         /*
4361          * If no refclock support, no data to return
4362          */
4363         ctl_error(CERR_BADASSOC);
4364 #else
4365         const struct ctl_var *  v;
4366         int                     i;
4367         struct peer *           peer;
4368         char *                  valuep;
4369         u_char *                wants;
4370         size_t                  wants_alloc;
4371         int                     gotvar;
4372         const u_char *          cc;
4373         struct ctl_var *        kv;
4374         struct refclockstat     cs;
4375
4376         if (res_associd != 0) {
4377                 peer = findpeerbyassoc(res_associd);
4378         } else {
4379                 /*
4380                  * Find a clock for this jerk.  If the system peer
4381                  * is a clock use it, else search peer_list for one.
4382                  */
4383                 if (sys_peer != NULL && (FLAG_REFCLOCK &
4384                     sys_peer->flags))
4385                         peer = sys_peer;
4386                 else
4387                         for (peer = peer_list;
4388                              peer != NULL;
4389                              peer = peer->p_link)
4390                                 if (FLAG_REFCLOCK & peer->flags)
4391                                         break;
4392         }
4393         if (NULL == peer || !(FLAG_REFCLOCK & peer->flags)) {
4394                 ctl_error(CERR_BADASSOC);
4395                 return;
4396         }
4397         /*
4398          * If we got here we have a peer which is a clock. Get his
4399          * status.
4400          */
4401         cs.kv_list = NULL;
4402         refclock_control(&peer->srcadr, NULL, &cs);
4403         kv = cs.kv_list;
4404         /*
4405          * Look for variables in the packet.
4406          */
4407         rpkt.status = htons(ctlclkstatus(&cs));
4408         wants_alloc = CC_MAXCODE + 1 + count_var(kv);
4409         wants = emalloc_zero(wants_alloc);
4410         gotvar = FALSE;
4411         while (NULL != (v = ctl_getitem(clock_var, &valuep))) {
4412                 if (!(EOV & v->flags)) {
4413                         wants[v->code] = TRUE;
4414                         gotvar = TRUE;
4415                 } else {
4416                         v = ctl_getitem(kv, &valuep);
4417                         INSIST(NULL != v);
4418                         if (EOV & v->flags) {
4419                                 ctl_error(CERR_UNKNOWNVAR);
4420                                 free(wants);
4421                                 free_varlist(cs.kv_list);
4422                                 return;
4423                         }
4424                         wants[CC_MAXCODE + 1 + v->code] = TRUE;
4425                         gotvar = TRUE;
4426                 }
4427         }
4428
4429         if (gotvar) {
4430                 for (i = 1; i <= CC_MAXCODE; i++)
4431                         if (wants[i])
4432                                 ctl_putclock(i, &cs, TRUE);
4433                 if (kv != NULL)
4434                         for (i = 0; !(EOV & kv[i].flags); i++)
4435                                 if (wants[i + CC_MAXCODE + 1])
4436                                         ctl_putdata(kv[i].text,
4437                                                     strlen(kv[i].text),
4438                                                     FALSE);
4439         } else {
4440                 for (cc = def_clock_var; *cc != 0; cc++)
4441                         ctl_putclock((int)*cc, &cs, FALSE);
4442                 for ( ; kv != NULL && !(EOV & kv->flags); kv++)
4443                         if (DEF & kv->flags)
4444                                 ctl_putdata(kv->text, strlen(kv->text),
4445                                             FALSE);
4446         }
4447
4448         free(wants);
4449         free_varlist(cs.kv_list);
4450
4451         ctl_flushpkt(0);
4452 #endif
4453 }
4454
4455
4456 /*
4457  * write_clockstatus - we don't do this
4458  */
4459 /*ARGSUSED*/
4460 static void
4461 write_clockstatus(
4462         struct recvbuf *rbufp,
4463         int restrict_mask
4464         )
4465 {
4466         ctl_error(CERR_PERMISSION);
4467 }
4468
4469 /*
4470  * Trap support from here on down. We send async trap messages when the
4471  * upper levels report trouble. Traps can by set either by control
4472  * messages or by configuration.
4473  */
4474 /*
4475  * set_trap - set a trap in response to a control message
4476  */
4477 static void
4478 set_trap(
4479         struct recvbuf *rbufp,
4480         int restrict_mask
4481         )
4482 {
4483         int traptype;
4484
4485         /*
4486          * See if this guy is allowed
4487          */
4488         if (restrict_mask & RES_NOTRAP) {
4489                 ctl_error(CERR_PERMISSION);
4490                 return;
4491         }
4492
4493         /*
4494          * Determine his allowed trap type.
4495          */
4496         traptype = TRAP_TYPE_PRIO;
4497         if (restrict_mask & RES_LPTRAP)
4498                 traptype = TRAP_TYPE_NONPRIO;
4499
4500         /*
4501          * Call ctlsettrap() to do the work.  Return
4502          * an error if it can't assign the trap.
4503          */
4504         if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
4505                         (int)res_version))
4506                 ctl_error(CERR_NORESOURCE);
4507         ctl_flushpkt(0);
4508 }
4509
4510
4511 /*
4512  * unset_trap - unset a trap in response to a control message
4513  */
4514 static void
4515 unset_trap(
4516         struct recvbuf *rbufp,
4517         int restrict_mask
4518         )
4519 {
4520         int traptype;
4521
4522         /*
4523          * We don't prevent anyone from removing his own trap unless the
4524          * trap is configured. Note we also must be aware of the
4525          * possibility that restriction flags were changed since this
4526          * guy last set his trap. Set the trap type based on this.
4527          */
4528         traptype = TRAP_TYPE_PRIO;
4529         if (restrict_mask & RES_LPTRAP)
4530                 traptype = TRAP_TYPE_NONPRIO;
4531
4532         /*
4533          * Call ctlclrtrap() to clear this out.
4534          */
4535         if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
4536                 ctl_error(CERR_BADASSOC);
4537         ctl_flushpkt(0);
4538 }
4539
4540
4541 /*
4542  * ctlsettrap - called to set a trap
4543  */
4544 int
4545 ctlsettrap(
4546         sockaddr_u *raddr,
4547         struct interface *linter,
4548         int traptype,
4549         int version
4550         )
4551 {
4552         size_t n;
4553         struct ctl_trap *tp;
4554         struct ctl_trap *tptouse;
4555
4556         /*
4557          * See if we can find this trap.  If so, we only need update
4558          * the flags and the time.
4559          */
4560         if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
4561                 switch (traptype) {
4562
4563                 case TRAP_TYPE_CONFIG:
4564                         tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
4565                         break;
4566
4567                 case TRAP_TYPE_PRIO:
4568                         if (tp->tr_flags & TRAP_CONFIGURED)
4569                                 return (1); /* don't change anything */
4570                         tp->tr_flags = TRAP_INUSE;
4571                         break;
4572
4573                 case TRAP_TYPE_NONPRIO:
4574                         if (tp->tr_flags & TRAP_CONFIGURED)
4575                                 return (1); /* don't change anything */
4576                         tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
4577                         break;
4578                 }
4579                 tp->tr_settime = current_time;
4580                 tp->tr_resets++;
4581                 return (1);
4582         }
4583
4584         /*
4585          * First we heard of this guy.  Try to find a trap structure
4586          * for him to use, clearing out lesser priority guys if we
4587          * have to. Clear out anyone who's expired while we're at it.
4588          */
4589         tptouse = NULL;
4590         for (n = 0; n < COUNTOF(ctl_traps); n++) {
4591                 tp = &ctl_traps[n];
4592                 if ((TRAP_INUSE & tp->tr_flags) &&
4593                     !(TRAP_CONFIGURED & tp->tr_flags) &&
4594                     ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
4595                         tp->tr_flags = 0;
4596                         num_ctl_traps--;
4597                 }
4598                 if (!(TRAP_INUSE & tp->tr_flags)) {
4599                         tptouse = tp;
4600                 } else if (!(TRAP_CONFIGURED & tp->tr_flags)) {
4601                         switch (traptype) {
4602
4603                         case TRAP_TYPE_CONFIG:
4604                                 if (tptouse == NULL) {
4605                                         tptouse = tp;
4606                                         break;
4607                                 }
4608                                 if ((TRAP_NONPRIO & tptouse->tr_flags) &&
4609                                     !(TRAP_NONPRIO & tp->tr_flags))
4610                                         break;
4611
4612                                 if (!(TRAP_NONPRIO & tptouse->tr_flags)
4613                                     && (TRAP_NONPRIO & tp->tr_flags)) {
4614                                         tptouse = tp;
4615                                         break;
4616                                 }
4617                                 if (tptouse->tr_origtime <
4618                                     tp->tr_origtime)
4619                                         tptouse = tp;
4620                                 break;
4621
4622                         case TRAP_TYPE_PRIO:
4623                                 if ( TRAP_NONPRIO & tp->tr_flags) {
4624                                         if (tptouse == NULL ||
4625                                             ((TRAP_INUSE &
4626                                               tptouse->tr_flags) &&
4627                                              tptouse->tr_origtime <
4628                                              tp->tr_origtime))
4629                                                 tptouse = tp;
4630                                 }
4631                                 break;
4632
4633                         case TRAP_TYPE_NONPRIO:
4634                                 break;
4635                         }
4636                 }
4637         }
4638
4639         /*
4640          * If we don't have room for him return an error.
4641          */
4642         if (tptouse == NULL)
4643                 return (0);
4644
4645         /*
4646          * Set up this structure for him.
4647          */
4648         tptouse->tr_settime = tptouse->tr_origtime = current_time;
4649         tptouse->tr_count = tptouse->tr_resets = 0;
4650         tptouse->tr_sequence = 1;
4651         tptouse->tr_addr = *raddr;
4652         tptouse->tr_localaddr = linter;
4653         tptouse->tr_version = (u_char) version;
4654         tptouse->tr_flags = TRAP_INUSE;
4655         if (traptype == TRAP_TYPE_CONFIG)
4656                 tptouse->tr_flags |= TRAP_CONFIGURED;
4657         else if (traptype == TRAP_TYPE_NONPRIO)
4658                 tptouse->tr_flags |= TRAP_NONPRIO;
4659         num_ctl_traps++;
4660         return (1);
4661 }
4662
4663
4664 /*
4665  * ctlclrtrap - called to clear a trap
4666  */
4667 int
4668 ctlclrtrap(
4669         sockaddr_u *raddr,
4670         struct interface *linter,
4671         int traptype
4672         )
4673 {
4674         register struct ctl_trap *tp;
4675
4676         if ((tp = ctlfindtrap(raddr, linter)) == NULL)
4677                 return (0);
4678
4679         if (tp->tr_flags & TRAP_CONFIGURED
4680             && traptype != TRAP_TYPE_CONFIG)
4681                 return (0);
4682
4683         tp->tr_flags = 0;
4684         num_ctl_traps--;
4685         return (1);
4686 }
4687
4688
4689 /*
4690  * ctlfindtrap - find a trap given the remote and local addresses
4691  */
4692 static struct ctl_trap *
4693 ctlfindtrap(
4694         sockaddr_u *raddr,
4695         struct interface *linter
4696         )
4697 {
4698         size_t  n;
4699
4700         for (n = 0; n < COUNTOF(ctl_traps); n++)
4701                 if ((ctl_traps[n].tr_flags & TRAP_INUSE)
4702                     && ADDR_PORT_EQ(raddr, &ctl_traps[n].tr_addr)
4703                     && (linter == ctl_traps[n].tr_localaddr))
4704                         return &ctl_traps[n];
4705
4706         return NULL;
4707 }
4708
4709
4710 /*
4711  * report_event - report an event to the trappers
4712  */
4713 void
4714 report_event(
4715         int     err,            /* error code */
4716         struct peer *peer,      /* peer structure pointer */
4717         const char *str         /* protostats string */
4718         )
4719 {
4720         char    statstr[NTP_MAXSTRLEN];
4721         int     i;
4722         size_t  len;
4723
4724         /*
4725          * Report the error to the protostats file, system log and
4726          * trappers.
4727          */
4728         if (peer == NULL) {
4729
4730                 /*
4731                  * Discard a system report if the number of reports of
4732                  * the same type exceeds the maximum.
4733                  */
4734                 if (ctl_sys_last_event != (u_char)err)
4735                         ctl_sys_num_events= 0;
4736                 if (ctl_sys_num_events >= CTL_SYS_MAXEVENTS)
4737                         return;
4738
4739                 ctl_sys_last_event = (u_char)err;
4740                 ctl_sys_num_events++;
4741                 snprintf(statstr, sizeof(statstr),
4742                     "0.0.0.0 %04x %02x %s",
4743                     ctlsysstatus(), err, eventstr(err));
4744                 if (str != NULL) {
4745                         len = strlen(statstr);
4746                         snprintf(statstr + len, sizeof(statstr) - len,
4747                             " %s", str);
4748                 }
4749                 NLOG(NLOG_SYSEVENT)
4750                         msyslog(LOG_INFO, "%s", statstr);
4751         } else {
4752
4753                 /*
4754                  * Discard a peer report if the number of reports of
4755                  * the same type exceeds the maximum for that peer.
4756                  */
4757                 const char *    src;
4758                 u_char          errlast;
4759
4760                 errlast = (u_char)err & ~PEER_EVENT;
4761                 if (peer->last_event == errlast)
4762                         peer->num_events = 0;
4763                 if (peer->num_events >= CTL_PEER_MAXEVENTS)
4764                         return;
4765
4766                 peer->last_event = errlast;
4767                 peer->num_events++;
4768                 if (ISREFCLOCKADR(&peer->srcadr))
4769                         src = refnumtoa(&peer->srcadr);
4770                 else
4771                         src = stoa(&peer->srcadr);
4772
4773                 snprintf(statstr, sizeof(statstr),
4774                     "%s %04x %02x %s", src,
4775                     ctlpeerstatus(peer), err, eventstr(err));
4776                 if (str != NULL) {
4777                         len = strlen(statstr);
4778                         snprintf(statstr + len, sizeof(statstr) - len,
4779                             " %s", str);
4780                 }
4781                 NLOG(NLOG_PEEREVENT)
4782                         msyslog(LOG_INFO, "%s", statstr);
4783         }
4784         record_proto_stats(statstr);
4785 #if DEBUG
4786         if (debug)
4787                 printf("event at %lu %s\n", current_time, statstr);
4788 #endif
4789
4790         /*
4791          * If no trappers, return.
4792          */
4793         if (num_ctl_traps <= 0)
4794                 return;
4795
4796         /*
4797          * Set up the outgoing packet variables
4798          */
4799         res_opcode = CTL_OP_ASYNCMSG;
4800         res_offset = 0;
4801         res_async = TRUE;
4802         res_authenticate = FALSE;
4803         datapt = rpkt.u.data;
4804         dataend = &rpkt.u.data[CTL_MAX_DATA_LEN];
4805         if (!(err & PEER_EVENT)) {
4806                 rpkt.associd = 0;
4807                 rpkt.status = htons(ctlsysstatus());
4808
4809                 /* Include the core system variables and the list. */
4810                 for (i = 1; i <= CS_VARLIST; i++)
4811                         ctl_putsys(i);
4812         } else {
4813                 INSIST(peer != NULL);
4814                 rpkt.associd = htons(peer->associd);
4815                 rpkt.status = htons(ctlpeerstatus(peer));
4816
4817                 /* Dump it all. Later, maybe less. */
4818                 for (i = 1; i <= CP_MAX_NOAUTOKEY; i++)
4819                         ctl_putpeer(i, peer);
4820 #ifdef REFCLOCK
4821                 /*
4822                  * for clock exception events: add clock variables to
4823                  * reflect info on exception
4824                  */
4825                 if (err == PEVNT_CLOCK) {
4826                         struct refclockstat cs;
4827                         struct ctl_var *kv;
4828
4829                         cs.kv_list = NULL;
4830                         refclock_control(&peer->srcadr, NULL, &cs);
4831
4832                         ctl_puthex("refclockstatus",
4833                                    ctlclkstatus(&cs));
4834
4835                         for (i = 1; i <= CC_MAXCODE; i++)
4836                                 ctl_putclock(i, &cs, FALSE);
4837                         for (kv = cs.kv_list;
4838                              kv != NULL && !(EOV & kv->flags);
4839                              kv++)
4840                                 if (DEF & kv->flags)
4841                                         ctl_putdata(kv->text,
4842                                                     strlen(kv->text),
4843                                                     FALSE);
4844                         free_varlist(cs.kv_list);
4845                 }
4846 #endif /* REFCLOCK */
4847         }
4848
4849         /*
4850          * We're done, return.
4851          */
4852         ctl_flushpkt(0);
4853 }
4854
4855
4856 /*
4857  * mprintf_event - printf-style varargs variant of report_event()
4858  */
4859 int
4860 mprintf_event(
4861         int             evcode,         /* event code */
4862         struct peer *   p,              /* may be NULL */
4863         const char *    fmt,            /* msnprintf format */
4864         ...
4865         )
4866 {
4867         va_list ap;
4868         int     rc;
4869         char    msg[512];
4870
4871         va_start(ap, fmt);
4872         rc = mvsnprintf(msg, sizeof(msg), fmt, ap);
4873         va_end(ap);
4874         report_event(evcode, p, msg);
4875
4876         return rc;
4877 }
4878
4879
4880 /*
4881  * ctl_clr_stats - clear stat counters
4882  */
4883 void
4884 ctl_clr_stats(void)
4885 {
4886         ctltimereset = current_time;
4887         numctlreq = 0;
4888         numctlbadpkts = 0;
4889         numctlresponses = 0;
4890         numctlfrags = 0;
4891         numctlerrors = 0;
4892         numctlfrags = 0;
4893         numctltooshort = 0;
4894         numctlinputresp = 0;
4895         numctlinputfrag = 0;
4896         numctlinputerr = 0;
4897         numctlbadoffset = 0;
4898         numctlbadversion = 0;
4899         numctldatatooshort = 0;
4900         numctlbadop = 0;
4901         numasyncmsgs = 0;
4902 }
4903
4904 static u_short
4905 count_var(
4906         const struct ctl_var *k
4907         )
4908 {
4909         u_int c;
4910
4911         if (NULL == k)
4912                 return 0;
4913
4914         c = 0;
4915         while (!(EOV & (k++)->flags))
4916                 c++;
4917
4918         ENSURE(c <= USHRT_MAX);
4919         return (u_short)c;
4920 }
4921
4922
4923 char *
4924 add_var(
4925         struct ctl_var **kv,
4926         u_long size,
4927         u_short def
4928         )
4929 {
4930         u_short         c;
4931         struct ctl_var *k;
4932         char *          buf;
4933
4934         c = count_var(*kv);
4935         *kv  = erealloc(*kv, (c + 2) * sizeof(**kv));
4936         k = *kv;
4937         buf = emalloc(size);
4938         k[c].code  = c;
4939         k[c].text  = buf;
4940         k[c].flags = def;
4941         k[c + 1].code  = 0;
4942         k[c + 1].text  = NULL;
4943         k[c + 1].flags = EOV;
4944
4945         return buf;
4946 }
4947
4948
4949 void
4950 set_var(
4951         struct ctl_var **kv,
4952         const char *data,
4953         u_long size,
4954         u_short def
4955         )
4956 {
4957         struct ctl_var *k;
4958         const char *s;
4959         const char *t;
4960         char *td;
4961
4962         if (NULL == data || !size)
4963                 return;
4964
4965         k = *kv;
4966         if (k != NULL) {
4967                 while (!(EOV & k->flags)) {
4968                         if (NULL == k->text)    {
4969                                 td = emalloc(size);
4970                                 memcpy(td, data, size);
4971                                 k->text = td;
4972                                 k->flags = def;
4973                                 return;
4974                         } else {
4975                                 s = data;
4976                                 t = k->text;
4977                                 while (*t != '=' && *s == *t) {
4978                                         s++;
4979                                         t++;
4980                                 }
4981                                 if (*s == *t && ((*t == '=') || !*t)) {
4982                                         td = erealloc((void *)(intptr_t)k->text, size);
4983                                         memcpy(td, data, size);
4984                                         k->text = td;
4985                                         k->flags = def;
4986                                         return;
4987                                 }
4988                         }
4989                         k++;
4990                 }
4991         }
4992         td = add_var(kv, size, def);
4993         memcpy(td, data, size);
4994 }
4995
4996
4997 void
4998 set_sys_var(
4999         const char *data,
5000         u_long size,
5001         u_short def
5002         )
5003 {
5004         set_var(&ext_sys_var, data, size, def);
5005 }
5006
5007
5008 /*
5009  * get_ext_sys_var() retrieves the value of a user-defined variable or
5010  * NULL if the variable has not been setvar'd.
5011  */
5012 const char *
5013 get_ext_sys_var(const char *tag)
5014 {
5015         struct ctl_var *        v;
5016         size_t                  c;
5017         const char *            val;
5018
5019         val = NULL;
5020         c = strlen(tag);
5021         for (v = ext_sys_var; !(EOV & v->flags); v++) {
5022                 if (NULL != v->text && !memcmp(tag, v->text, c)) {
5023                         if ('=' == v->text[c]) {
5024                                 val = v->text + c + 1;
5025                                 break;
5026                         } else if ('\0' == v->text[c]) {
5027                                 val = "";
5028                                 break;
5029                         }
5030                 }
5031         }
5032
5033         return val;
5034 }
5035
5036
5037 void
5038 free_varlist(
5039         struct ctl_var *kv
5040         )
5041 {
5042         struct ctl_var *k;
5043         if (kv) {
5044                 for (k = kv; !(k->flags & EOV); k++)
5045                         free((void *)(intptr_t)k->text);
5046                 free((void *)kv);
5047         }
5048 }