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