]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/libntp/statestr.c
Fix multiple denial of service in ntpd.
[FreeBSD/FreeBSD.git] / contrib / ntp / libntp / statestr.c
1 /*
2  * pretty printing of status information
3  */
4 #ifdef HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7 #include <stdio.h>
8 #include "ntp_stdlib.h"
9 #include "ntp_fp.h"
10 #include "ntp.h"
11 #include "lib_strbuf.h"
12 #include "ntp_refclock.h"
13 #include "ntp_control.h"
14 #include "ntp_string.h"
15 #ifdef KERNEL_PLL
16 # include "ntp_syscall.h"
17 #endif
18
19
20 /*
21  * Structure for turning various constants into a readable string.
22  */
23 struct codestring {
24         int code;
25         const char * const string1;
26         const char * const string0;
27 };
28
29 /*
30  * Leap status (leap)
31  */
32 static const struct codestring leap_codes[] = {
33         { LEAP_NOWARNING,       "leap_none",    0 },
34         { LEAP_ADDSECOND,       "leap_add_sec", 0 },
35         { LEAP_DELSECOND,       "leap_del_sec", 0 },
36         { LEAP_NOTINSYNC,       "leap_alarm",   0 },
37         { -1,                   "leap",         0 }
38 };
39
40 /*
41  * Clock source status (sync)
42  */
43 static const struct codestring sync_codes[] = {
44         { CTL_SST_TS_UNSPEC,    "sync_unspec",          0 },
45         { CTL_SST_TS_ATOM,      "sync_pps",             0 },
46         { CTL_SST_TS_LF,        "sync_lf_radio",        0 },
47         { CTL_SST_TS_HF,        "sync_hf_radio",        0 },
48         { CTL_SST_TS_UHF,       "sync_uhf_radio",       0 },
49         { CTL_SST_TS_LOCAL,     "sync_local",           0 },
50         { CTL_SST_TS_NTP,       "sync_ntp",             0 },
51         { CTL_SST_TS_UDPTIME,   "sync_other",           0 },
52         { CTL_SST_TS_WRSTWTCH,  "sync_wristwatch",      0 },
53         { CTL_SST_TS_TELEPHONE, "sync_telephone",       0 },
54         { -1,                   "sync",                 0 }
55 };
56
57 /*
58  * Peer selection status (sel)
59  */
60 static const struct codestring select_codes[] = {
61         { CTL_PST_SEL_REJECT,   "sel_reject",           0 },
62         { CTL_PST_SEL_SANE,     "sel_falsetick",        0 },
63         { CTL_PST_SEL_CORRECT,  "sel_excess",           0 },
64         { CTL_PST_SEL_SELCAND,  "sel_outlier",          0 },
65         { CTL_PST_SEL_SYNCCAND, "sel_candidate",        0 },
66         { CTL_PST_SEL_EXCESS,   "sel_backup",           0 },
67         { CTL_PST_SEL_SYSPEER,  "sel_sys.peer",         0 },
68         { CTL_PST_SEL_PPS,      "sel_pps.peer",         0 },
69         { -1,                   "sel",                  0 }
70 };
71
72 /*
73  * Clock status (clk)
74  */
75 static const struct codestring clock_codes[] = {
76         { CTL_CLK_OKAY,         "clk_unspec",           0 },
77         { CTL_CLK_NOREPLY,      "clk_no_reply",         0 },
78         { CTL_CLK_BADFORMAT,    "clk_bad_format",       0 },
79         { CTL_CLK_FAULT,        "clk_fault",            0 },
80         { CTL_CLK_PROPAGATION,  "clk_bad_signal",       0 },
81         { CTL_CLK_BADDATE,      "clk_bad_date",         0 },
82         { CTL_CLK_BADTIME,      "clk_bad_time",         0 },
83         { -1,                   "clk",                  0 }
84 };
85
86
87 #ifdef FLASH_CODES_UNUSED
88 /*
89  * Flash bits -- see ntpq.c tstflags & tstflagnames
90  */
91 static const struct codestring flash_codes[] = {
92         { TEST1,                "pkt_dup",      0 },
93         { TEST2,                "pkt_bogus",    0 },
94         { TEST3,                "pkt_unsync",   0 },
95         { TEST4,                "pkt_denied",   0 },
96         { TEST5,                "pkt_auth",     0 },
97         { TEST6,                "pkt_stratum",  0 },
98         { TEST7,                "pkt_header",   0 },
99         { TEST8,                "pkt_autokey",  0 },
100         { TEST9,                "pkt_crypto",   0 },
101         { TEST10,               "peer_stratum", 0 },
102         { TEST11,               "peer_dist",    0 },
103         { TEST12,               "peer_loop",    0 },
104         { TEST13,               "peer_unreach", 0 },
105         { -1,                   "flash",        0 }
106 };
107 #endif
108
109
110 /*
111  * System events (sys)
112  */
113 static const struct codestring sys_codes[] = {
114         { EVNT_UNSPEC,          "unspecified",                  0 },
115         { EVNT_NSET,            "freq_not_set",                 0 },
116         { EVNT_FSET,            "freq_set",                     0 },
117         { EVNT_SPIK,            "spike_detect",                 0 },
118         { EVNT_FREQ,            "freq_mode",                    0 },
119         { EVNT_SYNC,            "clock_sync",                   0 },
120         { EVNT_SYSRESTART,      "restart",                      0 },
121         { EVNT_SYSFAULT,        "panic_stop",                   0 },
122         { EVNT_NOPEER,          "no_sys_peer",                  0 },
123         { EVNT_ARMED,           "leap_armed",                   0 },
124         { EVNT_DISARMED,        "leap_disarmed",                0 },
125         { EVNT_LEAP,            "leap_event",                   0 },
126         { EVNT_CLOCKRESET,      "clock_step",                   0 },
127         { EVNT_KERN,            "kern",                         0 },
128         { EVNT_TAI,             "TAI",                          0 },
129         { EVNT_LEAPVAL,         "stale_leapsecond_values",      0 },
130         { -1,                   "",                             0 }
131 };
132
133 /*
134  * Peer events (peer)
135  */
136 static const struct codestring peer_codes[] = {
137         { PEVNT_MOBIL & ~PEER_EVENT,    "mobilize",             0 },
138         { PEVNT_DEMOBIL & ~PEER_EVENT,  "demobilize",           0 },
139         { PEVNT_UNREACH & ~PEER_EVENT,  "unreachable",          0 },
140         { PEVNT_REACH & ~PEER_EVENT,    "reachable",            0 },
141         { PEVNT_RESTART & ~PEER_EVENT,  "restart",              0 },
142         { PEVNT_REPLY & ~PEER_EVENT,    "no_reply",             0 },
143         { PEVNT_RATE & ~PEER_EVENT,     "rate_exceeded",        0 },
144         { PEVNT_DENY & ~PEER_EVENT,     "access_denied",        0 },
145         { PEVNT_ARMED & ~PEER_EVENT,    "leap_armed",           0 },
146         { PEVNT_NEWPEER & ~PEER_EVENT,  "sys_peer",             0 },
147         { PEVNT_CLOCK & ~PEER_EVENT,    "clock_event",          0 },
148         { PEVNT_AUTH & ~PEER_EVENT,     "bad_auth",             0 },
149         { PEVNT_POPCORN & ~PEER_EVENT,  "popcorn",              0 },
150         { PEVNT_XLEAVE & ~PEER_EVENT,   "interleave_mode",      0 },
151         { PEVNT_XERR & ~PEER_EVENT,     "interleave_error",     0 },
152         { -1,                           "",                     0 }
153 };
154
155 /*
156  * Peer status bits
157  */
158 static const struct codestring peer_st_bits[] = {
159         { CTL_PST_CONFIG,               "conf",         0 },
160         { CTL_PST_AUTHENABLE,           "authenb",      0 },
161         { CTL_PST_AUTHENTIC,            "auth",         0 },
162         { CTL_PST_REACH,                "reach",        0 },
163         { CTL_PST_BCAST,                "bcast",        0 },
164         /* not used with getcode(), no terminating entry needed */
165 };
166
167 /*
168  * Restriction match bits
169  */
170 static const struct codestring res_match_bits[] = {
171         { RESM_NTPONLY,                 "ntpport",      0 },
172         { RESM_INTERFACE,               "interface",    0 },
173         { RESM_SOURCE,                  "source",       0 },
174         /* not used with getcode(), no terminating entry needed */
175 };
176
177 /*
178  * Restriction access bits
179  */
180 static const struct codestring res_access_bits[] = {
181         { RES_IGNORE,                   "ignore",       0 },
182         { RES_DONTSERVE,                "noserve",      "serve" },
183         { RES_DONTTRUST,                "notrust",      "trust" },
184         { RES_VERSION,                  "version",      0 },
185         { RES_NOPEER,                   "nopeer",       "peer" },
186         { RES_NOEPEER,                  "noepeer",      "epeer" },
187         { RES_LIMITED,                  "limited",      0 },
188
189         { RES_NOQUERY,                  "noquery",      "query" },
190         { RES_NOMODIFY,                 "nomodify",     0 },
191         { RES_NOTRAP,                   "notrap",       "trap" },
192         { RES_LPTRAP,                   "lptrap",       0 },
193
194         { RES_KOD,                      "kod",          0 },
195         { RES_MSSNTP,                   "mssntp",       0 },
196         { RES_FLAKE,                    "flake",        0 },
197         { RES_NOMRULIST,                "nomrulist",    0 },
198
199         { RES_SRVRSPFUZ,                "serverresponse fuzz",  0 },
200
201         /* not used with getcode(), no terminating entry needed */
202 };
203
204 #ifdef AUTOKEY
205 /*
206  * Crypto events (cryp)
207  */
208 static const struct codestring crypto_codes[] = {
209         { XEVNT_OK & ~CRPT_EVENT,       "success",                      0 },
210         { XEVNT_LEN & ~CRPT_EVENT,      "bad_field_format_or_length",   0 },
211         { XEVNT_TSP & ~CRPT_EVENT,      "bad_timestamp",                0 },
212         { XEVNT_FSP & ~CRPT_EVENT,      "bad_filestamp",                0 },
213         { XEVNT_PUB & ~CRPT_EVENT,      "bad_or_missing_public_key",    0 },
214         { XEVNT_MD & ~CRPT_EVENT,       "unsupported_digest_type",      0 },
215         { XEVNT_KEY & ~CRPT_EVENT,      "unsupported_identity_type",    0 },
216         { XEVNT_SGL & ~CRPT_EVENT,      "bad_signature_length",         0 },
217         { XEVNT_SIG & ~CRPT_EVENT,      "signature_not_verified",       0 },
218         { XEVNT_VFY & ~CRPT_EVENT,      "certificate_not_verified",     0 },
219         { XEVNT_PER & ~CRPT_EVENT,      "host_certificate_expired",     0 },
220         { XEVNT_CKY & ~CRPT_EVENT,      "bad_or_missing_cookie",        0 },
221         { XEVNT_DAT & ~CRPT_EVENT,      "bad_or_missing_leapseconds",   0 },
222         { XEVNT_CRT & ~CRPT_EVENT,      "bad_or_missing_certificate",   0 },    
223         { XEVNT_ID & ~CRPT_EVENT,       "bad_or_missing_group key",     0 },
224         { XEVNT_ERR & ~CRPT_EVENT,      "protocol_error",               0 },
225         { -1,                           "",                             0 }
226 };
227 #endif  /* AUTOKEY */
228
229 #ifdef KERNEL_PLL
230 /*
231  * kernel discipline status bits
232  */
233 static const struct codestring k_st_bits[] = {
234 # ifdef STA_PLL
235         { STA_PLL,                      "pll",          0 },
236 # endif
237 # ifdef STA_PPSFREQ
238         { STA_PPSFREQ,                  "ppsfreq",      0 },
239 # endif
240 # ifdef STA_PPSTIME
241         { STA_PPSTIME,                  "ppstime",      0 },
242 # endif
243 # ifdef STA_FLL
244         { STA_FLL,                      "fll",          0 },
245 # endif
246 # ifdef STA_INS
247         { STA_INS,                      "ins",          0 },
248 # endif
249 # ifdef STA_DEL
250         { STA_DEL,                      "del",          0 },
251 # endif
252 # ifdef STA_UNSYNC
253         { STA_UNSYNC,                   "unsync",       0 },
254 # endif
255 # ifdef STA_FREQHOLD
256         { STA_FREQHOLD,                 "freqhold",     0 },
257 # endif
258 # ifdef STA_PPSSIGNAL
259         { STA_PPSSIGNAL,                "ppssignal",    0 },
260 # endif
261 # ifdef STA_PPSJITTER
262         { STA_PPSJITTER,                "ppsjitter",    0 },
263 # endif
264 # ifdef STA_PPSWANDER
265         { STA_PPSWANDER,                "ppswander",    0 },
266 # endif
267 # ifdef STA_PPSERROR
268         { STA_PPSERROR,                 "ppserror",     0 },
269 # endif
270 # ifdef STA_CLOCKERR
271         { STA_CLOCKERR,                 "clockerr",     0 },
272 # endif
273 # ifdef STA_NANO
274         { STA_NANO,                     "nano",         0 },
275 # endif
276 # ifdef STA_MODE
277         { STA_MODE,                     "mode=fll",     0 },
278 # endif
279 # ifdef STA_CLK
280         { STA_CLK,                      "src=B",        0 },
281 # endif
282         /* not used with getcode(), no terminating entry needed */
283 };
284 #endif  /* KERNEL_PLL */
285
286 /* Forwards */
287 static const char *     getcode(int, const struct codestring *);
288 static const char *     getevents(int);
289 static const char *     peer_st_flags(u_char pst);
290
291 /*
292  * getcode - return string corresponding to code
293  */
294 static const char *
295 getcode(
296         int                             code,
297         const struct codestring *       codetab
298         )
299 {
300         char *  buf;
301
302         while (codetab->code != -1) {
303                 if (codetab->code == code)
304                         return codetab->string1;
305                 codetab++;
306         }
307
308         LIB_GETBUF(buf);
309         snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string1, code);
310
311         return buf;
312 }
313
314 /*
315  * getevents - return a descriptive string for the event count
316  */
317 static const char *
318 getevents(
319         int cnt
320         )
321 {
322         char *  buf;
323
324         if (cnt == 0)
325                 return "no events";
326
327         LIB_GETBUF(buf);
328         snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt,
329                  (1 == cnt)
330                      ? ""
331                      : "s");
332
333         return buf;
334 }
335
336
337 /*
338  * decode_bitflags()
339  *
340  * returns a human-readable string with a keyword from tab for each bit
341  * set in bits, separating multiple entries with text of sep2.
342  */
343 static const char *
344 decode_bitflags(
345         int                             bits,
346         const char *                    sep2,
347         const struct codestring *       tab,
348         size_t                          tab_ct
349         )
350 {
351         const char *    sep;
352         char *          buf;
353         char *          pch;
354         char *          lim;
355         size_t          b;
356         int             rc;
357         int             saved_errno;    /* for use in DPRINTF with %m */
358
359         saved_errno = errno;
360         LIB_GETBUF(buf);
361         pch = buf;
362         lim = buf + LIB_BUFLENGTH;
363         sep = "";
364
365         for (b = 0; b < tab_ct; b++) {
366                 const char * flagstr;
367
368                 if (tab[b].code & bits) {
369                         flagstr = tab[b].string1;
370                 } else {
371                         flagstr = tab[b].string0;
372                 }
373
374                 if (flagstr) {
375                         size_t avail = lim - pch;
376                         rc = snprintf(pch, avail, "%s%s", sep,
377                                       flagstr);
378                         if ((size_t)rc >= avail)
379                                 goto toosmall;
380                         pch += rc;
381                         sep = sep2;
382                 }
383         }
384
385         return buf;
386
387     toosmall:
388         snprintf(buf, LIB_BUFLENGTH,
389                  "decode_bitflags(%s) can't decode 0x%x in %d bytes",
390                  (tab == peer_st_bits)
391                      ? "peer_st"
392                      : 
393 #ifdef KERNEL_PLL
394                        (tab == k_st_bits)
395                            ? "kern_st"
396                            :
397 #endif
398                              "",
399                  bits, (int)LIB_BUFLENGTH);
400         errno = saved_errno;
401
402         return buf;
403 }
404
405
406 static const char *
407 peer_st_flags(
408         u_char pst
409         )
410 {
411         return decode_bitflags(pst, ", ", peer_st_bits,
412                                COUNTOF(peer_st_bits));
413 }
414
415
416 const char *
417 res_match_flags(
418         u_short mf
419         )
420 {
421         return decode_bitflags(mf, " ", res_match_bits,
422                                COUNTOF(res_match_bits));
423 }
424
425
426 const char *
427 res_access_flags(
428         u_int32 af
429         )
430 {
431         return decode_bitflags(af, " ", res_access_bits,
432                                COUNTOF(res_access_bits));
433 }
434
435
436 #ifdef KERNEL_PLL
437 const char *
438 k_st_flags(
439         u_int32 st
440         )
441 {
442         return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits));
443 }
444 #endif  /* KERNEL_PLL */
445
446
447 /*
448  * statustoa - return a descriptive string for a peer status
449  */
450 char *
451 statustoa(
452         int type,
453         int st
454         )
455 {
456         char *  cb;
457         char *  cc;
458         u_char  pst;
459
460         LIB_GETBUF(cb);
461
462         switch (type) {
463
464         case TYPE_SYS:
465                 snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s",
466                          getcode(CTL_SYS_LI(st), leap_codes),
467                          getcode(CTL_SYS_SOURCE(st), sync_codes),
468                          getevents(CTL_SYS_NEVNT(st)),
469                          getcode(CTL_SYS_EVENT(st), sys_codes));
470                 break;
471         
472         case TYPE_PEER:
473                 pst = (u_char)CTL_PEER_STATVAL(st);
474                 snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s",
475                          peer_st_flags(pst),
476                          getcode(pst & 0x7, select_codes),
477                          getevents(CTL_PEER_NEVNT(st)));
478                 if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) {
479                         cc = cb + strlen(cb);
480                         snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s",
481                                  getcode(CTL_PEER_EVENT(st),
482                                          peer_codes));
483                 }
484                 break;
485         
486         case TYPE_CLOCK:
487                 snprintf(cb, LIB_BUFLENGTH, "%s, %s",
488                          getevents(CTL_SYS_NEVNT(st)),
489                          getcode((st) & 0xf, clock_codes));
490                 break;
491         }
492
493         return cb;
494 }
495
496 const char *
497 eventstr(
498         int num
499         )
500 {
501         if (num & PEER_EVENT)
502                 return (getcode(num & ~PEER_EVENT, peer_codes));
503 #ifdef AUTOKEY
504         else if (num & CRPT_EVENT)
505                 return (getcode(num & ~CRPT_EVENT, crypto_codes));
506 #endif  /* AUTOKEY */
507         else
508                 return (getcode(num, sys_codes));
509 }
510
511 const char *
512 ceventstr(
513         int num
514         )
515 {
516         return getcode(num, clock_codes);
517 }