]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/ntp/libntp/statestr.c
Fix multiple vulnerabilities in ntp. [SA-18:02.ntp]
[FreeBSD/releng/10.3.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_NOQUERY,                  "noquery",      "query" },
185         { RES_NOMODIFY,                 "nomodify",     0 },
186         { RES_NOPEER,                   "nopeer",       "peer" },
187         { RES_NOEPEER,                  "noepeer",      "epeer" },
188         { RES_NOTRAP,                   "notrap",       "trap" },
189         { RES_LPTRAP,                   "lptrap",       0 },
190         { RES_LIMITED,                  "limited",      0 },
191         { RES_VERSION,                  "version",      0 },
192         { RES_KOD,                      "kod",          0 },
193         { RES_FLAKE,                    "flake",        0 },
194         /* not used with getcode(), no terminating entry needed */
195 };
196
197 #ifdef AUTOKEY
198 /*
199  * Crypto events (cryp)
200  */
201 static const struct codestring crypto_codes[] = {
202         { XEVNT_OK & ~CRPT_EVENT,       "success",                      0 },
203         { XEVNT_LEN & ~CRPT_EVENT,      "bad_field_format_or_length",   0 },
204         { XEVNT_TSP & ~CRPT_EVENT,      "bad_timestamp",                0 },
205         { XEVNT_FSP & ~CRPT_EVENT,      "bad_filestamp",                0 },
206         { XEVNT_PUB & ~CRPT_EVENT,      "bad_or_missing_public_key",    0 },
207         { XEVNT_MD & ~CRPT_EVENT,       "unsupported_digest_type",      0 },
208         { XEVNT_KEY & ~CRPT_EVENT,      "unsupported_identity_type",    0 },
209         { XEVNT_SGL & ~CRPT_EVENT,      "bad_signature_length",         0 },
210         { XEVNT_SIG & ~CRPT_EVENT,      "signature_not_verified",       0 },
211         { XEVNT_VFY & ~CRPT_EVENT,      "certificate_not_verified",     0 },
212         { XEVNT_PER & ~CRPT_EVENT,      "host_certificate_expired",     0 },
213         { XEVNT_CKY & ~CRPT_EVENT,      "bad_or_missing_cookie",        0 },
214         { XEVNT_DAT & ~CRPT_EVENT,      "bad_or_missing_leapseconds",   0 },
215         { XEVNT_CRT & ~CRPT_EVENT,      "bad_or_missing_certificate",   0 },    
216         { XEVNT_ID & ~CRPT_EVENT,       "bad_or_missing_group key",     0 },
217         { XEVNT_ERR & ~CRPT_EVENT,      "protocol_error",               0 },
218         { -1,                           "",                             0 }
219 };
220 #endif  /* AUTOKEY */
221
222 #ifdef KERNEL_PLL
223 /*
224  * kernel discipline status bits
225  */
226 static const struct codestring k_st_bits[] = {
227 # ifdef STA_PLL
228         { STA_PLL,                      "pll",          0 },
229 # endif
230 # ifdef STA_PPSFREQ
231         { STA_PPSFREQ,                  "ppsfreq",      0 },
232 # endif
233 # ifdef STA_PPSTIME
234         { STA_PPSTIME,                  "ppstime",      0 },
235 # endif
236 # ifdef STA_FLL
237         { STA_FLL,                      "fll",          0 },
238 # endif
239 # ifdef STA_INS
240         { STA_INS,                      "ins",          0 },
241 # endif
242 # ifdef STA_DEL
243         { STA_DEL,                      "del",          0 },
244 # endif
245 # ifdef STA_UNSYNC
246         { STA_UNSYNC,                   "unsync",       0 },
247 # endif
248 # ifdef STA_FREQHOLD
249         { STA_FREQHOLD,                 "freqhold",     0 },
250 # endif
251 # ifdef STA_PPSSIGNAL
252         { STA_PPSSIGNAL,                "ppssignal",    0 },
253 # endif
254 # ifdef STA_PPSJITTER
255         { STA_PPSJITTER,                "ppsjitter",    0 },
256 # endif
257 # ifdef STA_PPSWANDER
258         { STA_PPSWANDER,                "ppswander",    0 },
259 # endif
260 # ifdef STA_PPSERROR
261         { STA_PPSERROR,                 "ppserror",     0 },
262 # endif
263 # ifdef STA_CLOCKERR
264         { STA_CLOCKERR,                 "clockerr",     0 },
265 # endif
266 # ifdef STA_NANO
267         { STA_NANO,                     "nano",         0 },
268 # endif
269 # ifdef STA_MODE
270         { STA_MODE,                     "mode=fll",     0 },
271 # endif
272 # ifdef STA_CLK
273         { STA_CLK,                      "src=B",        0 },
274 # endif
275         /* not used with getcode(), no terminating entry needed */
276 };
277 #endif  /* KERNEL_PLL */
278
279 /* Forwards */
280 static const char *     getcode(int, const struct codestring *);
281 static const char *     getevents(int);
282 static const char *     peer_st_flags(u_char pst);
283
284 /*
285  * getcode - return string corresponding to code
286  */
287 static const char *
288 getcode(
289         int                             code,
290         const struct codestring *       codetab
291         )
292 {
293         char *  buf;
294
295         while (codetab->code != -1) {
296                 if (codetab->code == code)
297                         return codetab->string1;
298                 codetab++;
299         }
300
301         LIB_GETBUF(buf);
302         snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string1, code);
303
304         return buf;
305 }
306
307 /*
308  * getevents - return a descriptive string for the event count
309  */
310 static const char *
311 getevents(
312         int cnt
313         )
314 {
315         char *  buf;
316
317         if (cnt == 0)
318                 return "no events";
319
320         LIB_GETBUF(buf);
321         snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt,
322                  (1 == cnt)
323                      ? ""
324                      : "s");
325
326         return buf;
327 }
328
329
330 /*
331  * decode_bitflags()
332  *
333  * returns a human-readable string with a keyword from tab for each bit
334  * set in bits, separating multiple entries with text of sep2.
335  */
336 static const char *
337 decode_bitflags(
338         int                             bits,
339         const char *                    sep2,
340         const struct codestring *       tab,
341         size_t                          tab_ct
342         )
343 {
344         const char *    sep;
345         char *          buf;
346         char *          pch;
347         char *          lim;
348         size_t          b;
349         int             rc;
350         int             saved_errno;    /* for use in DPRINTF with %m */
351
352         saved_errno = errno;
353         LIB_GETBUF(buf);
354         pch = buf;
355         lim = buf + LIB_BUFLENGTH;
356         sep = "";
357
358         for (b = 0; b < tab_ct; b++) {
359                 const char * flagstr;
360
361                 if (tab[b].code & bits) {
362                         flagstr = tab[b].string1;
363                 } else {
364                         flagstr = tab[b].string0;
365                 }
366
367                 if (flagstr) {
368                         size_t avail = lim - pch;
369                         rc = snprintf(pch, avail, "%s%s", sep,
370                                       flagstr);
371                         if ((size_t)rc >= avail)
372                                 goto toosmall;
373                         pch += rc;
374                         sep = sep2;
375                 }
376         }
377
378         return buf;
379
380     toosmall:
381         snprintf(buf, LIB_BUFLENGTH,
382                  "decode_bitflags(%s) can't decode 0x%x in %d bytes",
383                  (tab == peer_st_bits)
384                      ? "peer_st"
385                      : 
386 #ifdef KERNEL_PLL
387                        (tab == k_st_bits)
388                            ? "kern_st"
389                            :
390 #endif
391                              "",
392                  bits, (int)LIB_BUFLENGTH);
393         errno = saved_errno;
394
395         return buf;
396 }
397
398
399 static const char *
400 peer_st_flags(
401         u_char pst
402         )
403 {
404         return decode_bitflags(pst, ", ", peer_st_bits,
405                                COUNTOF(peer_st_bits));
406 }
407
408
409 const char *
410 res_match_flags(
411         u_short mf
412         )
413 {
414         return decode_bitflags(mf, " ", res_match_bits,
415                                COUNTOF(res_match_bits));
416 }
417
418
419 const char *
420 res_access_flags(
421         u_short af
422         )
423 {
424         return decode_bitflags(af, " ", res_access_bits,
425                                COUNTOF(res_access_bits));
426 }
427
428
429 #ifdef KERNEL_PLL
430 const char *
431 k_st_flags(
432         u_int32 st
433         )
434 {
435         return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits));
436 }
437 #endif  /* KERNEL_PLL */
438
439
440 /*
441  * statustoa - return a descriptive string for a peer status
442  */
443 char *
444 statustoa(
445         int type,
446         int st
447         )
448 {
449         char *  cb;
450         char *  cc;
451         u_char  pst;
452
453         LIB_GETBUF(cb);
454
455         switch (type) {
456
457         case TYPE_SYS:
458                 snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s",
459                          getcode(CTL_SYS_LI(st), leap_codes),
460                          getcode(CTL_SYS_SOURCE(st), sync_codes),
461                          getevents(CTL_SYS_NEVNT(st)),
462                          getcode(CTL_SYS_EVENT(st), sys_codes));
463                 break;
464         
465         case TYPE_PEER:
466                 pst = (u_char)CTL_PEER_STATVAL(st);
467                 snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s",
468                          peer_st_flags(pst),
469                          getcode(pst & 0x7, select_codes),
470                          getevents(CTL_PEER_NEVNT(st)));
471                 if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) {
472                         cc = cb + strlen(cb);
473                         snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s",
474                                  getcode(CTL_PEER_EVENT(st),
475                                          peer_codes));
476                 }
477                 break;
478         
479         case TYPE_CLOCK:
480                 snprintf(cb, LIB_BUFLENGTH, "%s, %s",
481                          getevents(CTL_SYS_NEVNT(st)),
482                          getcode((st) & 0xf, clock_codes));
483                 break;
484         }
485
486         return cb;
487 }
488
489 const char *
490 eventstr(
491         int num
492         )
493 {
494         if (num & PEER_EVENT)
495                 return (getcode(num & ~PEER_EVENT, peer_codes));
496 #ifdef AUTOKEY
497         else if (num & CRPT_EVENT)
498                 return (getcode(num & ~CRPT_EVENT, crypto_codes));
499 #endif  /* AUTOKEY */
500         else
501                 return (getcode(num, sys_codes));
502 }
503
504 const char *
505 ceventstr(
506         int num
507         )
508 {
509         return getcode(num, clock_codes);
510 }