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