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