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