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