xref: /freebsd/contrib/ntp/libntp/statestr.c (revision f0574f5cf69e168cc4ea71ebbe5fdec9ec9a3dfe)
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"
152b15cb3dSCy Schubert #ifdef KERNEL_PLL
162b15cb3dSCy Schubert # include "ntp_syscall.h"
172b15cb3dSCy Schubert #endif
182b15cb3dSCy 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;
252b15cb3dSCy Schubert 	const char * const string;
26c0b746e5SOllivier Robert };
27c0b746e5SOllivier Robert 
28c0b746e5SOllivier Robert /*
292b15cb3dSCy Schubert  * Leap status (leap)
30c0b746e5SOllivier Robert  */
312b15cb3dSCy 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" },
352b15cb3dSCy Schubert 	{ LEAP_NOTINSYNC,	"leap_alarm" },
36c0b746e5SOllivier Robert 	{ -1,			"leap" }
37c0b746e5SOllivier Robert };
38c0b746e5SOllivier Robert 
39c0b746e5SOllivier Robert /*
402b15cb3dSCy Schubert  * Clock source status (sync)
41c0b746e5SOllivier Robert  */
422b15cb3dSCy Schubert static const struct codestring sync_codes[] = {
43c0b746e5SOllivier Robert 	{ CTL_SST_TS_UNSPEC,	"sync_unspec" },
442b15cb3dSCy Schubert 	{ CTL_SST_TS_ATOM,	"sync_pps" },
452b15cb3dSCy Schubert 	{ CTL_SST_TS_LF,	"sync_lf_radio" },
462b15cb3dSCy Schubert 	{ CTL_SST_TS_HF,	"sync_hf_radio" },
472b15cb3dSCy Schubert 	{ CTL_SST_TS_UHF,	"sync_uhf_radio" },
482b15cb3dSCy Schubert 	{ CTL_SST_TS_LOCAL,	"sync_local" },
49c0b746e5SOllivier Robert 	{ CTL_SST_TS_NTP,	"sync_ntp" },
502b15cb3dSCy 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 /*
572b15cb3dSCy Schubert  * Peer selection status (sel)
58c0b746e5SOllivier Robert  */
592b15cb3dSCy Schubert static const struct codestring select_codes[] = {
602b15cb3dSCy Schubert 	{ CTL_PST_SEL_REJECT,	"sel_reject" },
61c0b746e5SOllivier Robert 	{ CTL_PST_SEL_SANE,	"sel_falsetick" },
62c0b746e5SOllivier Robert 	{ CTL_PST_SEL_CORRECT,	"sel_excess" },
639034852cSGleb Smirnoff 	{ CTL_PST_SEL_SELCAND,	"sel_outlier" },
642b15cb3dSCy Schubert 	{ CTL_PST_SEL_SYNCCAND,	"sel_candidate" },
652b15cb3dSCy 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 /*
722b15cb3dSCy Schubert  * Clock status (clk)
73c0b746e5SOllivier Robert  */
742b15cb3dSCy Schubert static const struct codestring clock_codes[] = {
752b15cb3dSCy Schubert 	{ CTL_CLK_OKAY,		"clk_unspec" },
762b15cb3dSCy Schubert 	{ CTL_CLK_NOREPLY,	"clk_no_reply" },
772b15cb3dSCy Schubert 	{ CTL_CLK_BADFORMAT,	"clk_bad_format" },
78c0b746e5SOllivier Robert 	{ CTL_CLK_FAULT,	"clk_fault" },
792b15cb3dSCy Schubert 	{ CTL_CLK_PROPAGATION,	"clk_bad_signal" },
802b15cb3dSCy Schubert 	{ CTL_CLK_BADDATE,	"clk_bad_date" },
812b15cb3dSCy Schubert 	{ CTL_CLK_BADTIME,	"clk_bad_time" },
82c0b746e5SOllivier Robert 	{ -1,			"clk" }
83c0b746e5SOllivier Robert };
84c0b746e5SOllivier Robert 
85c0b746e5SOllivier Robert 
862b15cb3dSCy Schubert #ifdef FLASH_CODES_UNUSED
87c0b746e5SOllivier Robert /*
882b15cb3dSCy Schubert  * Flash bits -- see ntpq.c tstflags & tstflagnames
89c0b746e5SOllivier Robert  */
902b15cb3dSCy Schubert static const struct codestring flash_codes[] = {
912b15cb3dSCy Schubert 	{ TEST1,		"pkt_dup" },
922b15cb3dSCy Schubert 	{ TEST2,		"pkt_bogus" },
932b15cb3dSCy Schubert 	{ TEST3,		"pkt_unsync" },
942b15cb3dSCy Schubert 	{ TEST4,		"pkt_denied" },
952b15cb3dSCy Schubert 	{ TEST5,		"pkt_auth" },
962b15cb3dSCy Schubert 	{ TEST6,		"pkt_stratum" },
972b15cb3dSCy Schubert 	{ TEST7,		"pkt_header" },
982b15cb3dSCy Schubert 	{ TEST8,		"pkt_autokey" },
992b15cb3dSCy Schubert 	{ TEST9,		"pkt_crypto" },
1002b15cb3dSCy Schubert 	{ TEST10,		"peer_stratum" },
1012b15cb3dSCy Schubert 	{ TEST11,		"peer_dist" },
1022b15cb3dSCy Schubert 	{ TEST12,		"peer_loop" },
1032b15cb3dSCy Schubert 	{ TEST13,		"peer_unreach" },
1042b15cb3dSCy Schubert 	{ -1,			"flash" }
105c0b746e5SOllivier Robert };
106c0b746e5SOllivier Robert #endif
1072b15cb3dSCy Schubert 
1082b15cb3dSCy Schubert 
1092b15cb3dSCy Schubert /*
1102b15cb3dSCy Schubert  * System events (sys)
1112b15cb3dSCy Schubert  */
1122b15cb3dSCy Schubert static const struct codestring sys_codes[] = {
1132b15cb3dSCy Schubert 	{ EVNT_UNSPEC,		"unspecified" },
1142b15cb3dSCy Schubert 	{ EVNT_NSET,		"freq_not_set" },
1152b15cb3dSCy Schubert 	{ EVNT_FSET,		"freq_set" },
1162b15cb3dSCy Schubert 	{ EVNT_SPIK,		"spike_detect" },
1172b15cb3dSCy Schubert 	{ EVNT_FREQ,		"freq_mode" },
1182b15cb3dSCy Schubert 	{ EVNT_SYNC,		"clock_sync" },
1192b15cb3dSCy Schubert 	{ EVNT_SYSRESTART,	"restart" },
1202b15cb3dSCy Schubert 	{ EVNT_SYSFAULT,	"panic_stop" },
1212b15cb3dSCy Schubert 	{ EVNT_NOPEER,		"no_sys_peer" },
1222b15cb3dSCy Schubert 	{ EVNT_ARMED,		"leap_armed" },
1232b15cb3dSCy Schubert 	{ EVNT_DISARMED,	"leap_disarmed" },
1242b15cb3dSCy Schubert 	{ EVNT_LEAP,		"leap_event" },
1252b15cb3dSCy Schubert 	{ EVNT_CLOCKRESET,	"clock_step" },
1262b15cb3dSCy Schubert 	{ EVNT_KERN,		"kern" },
1272b15cb3dSCy Schubert 	{ EVNT_TAI,		"TAI" },
1282b15cb3dSCy Schubert 	{ EVNT_LEAPVAL,		"stale_leapsecond_values" },
1292b15cb3dSCy Schubert 	{ -1,			"" }
130c0b746e5SOllivier Robert };
131c0b746e5SOllivier Robert 
1329c2daa00SOllivier Robert /*
1332b15cb3dSCy Schubert  * Peer events (peer)
1349c2daa00SOllivier Robert  */
1352b15cb3dSCy Schubert static const struct codestring peer_codes[] = {
1362b15cb3dSCy Schubert 	{ PEVNT_MOBIL & ~PEER_EVENT,	"mobilize" },
1372b15cb3dSCy Schubert 	{ PEVNT_DEMOBIL & ~PEER_EVENT,	"demobilize" },
1382b15cb3dSCy Schubert 	{ PEVNT_UNREACH & ~PEER_EVENT,	"unreachable" },
1392b15cb3dSCy Schubert 	{ PEVNT_REACH & ~PEER_EVENT,	"reachable" },
1402b15cb3dSCy Schubert 	{ PEVNT_RESTART & ~PEER_EVENT,	"restart" },
1412b15cb3dSCy Schubert 	{ PEVNT_REPLY & ~PEER_EVENT,	"no_reply" },
1422b15cb3dSCy Schubert 	{ PEVNT_RATE & ~PEER_EVENT,	"rate_exceeded" },
1432b15cb3dSCy Schubert 	{ PEVNT_DENY & ~PEER_EVENT,	"access_denied" },
1442b15cb3dSCy Schubert 	{ PEVNT_ARMED & ~PEER_EVENT,	"leap_armed" },
1452b15cb3dSCy Schubert 	{ PEVNT_NEWPEER & ~PEER_EVENT,	"sys_peer" },
1462b15cb3dSCy Schubert 	{ PEVNT_CLOCK & ~PEER_EVENT,	"clock_event" },
1472b15cb3dSCy Schubert 	{ PEVNT_AUTH & ~PEER_EVENT,	"bad_auth" },
1482b15cb3dSCy Schubert 	{ PEVNT_POPCORN & ~PEER_EVENT,	"popcorn" },
1492b15cb3dSCy Schubert 	{ PEVNT_XLEAVE & ~PEER_EVENT,	"interleave_mode" },
1502b15cb3dSCy Schubert 	{ PEVNT_XERR & ~PEER_EVENT,	"interleave_error" },
1512b15cb3dSCy Schubert 	{ -1,				"" }
1522b15cb3dSCy Schubert };
1532b15cb3dSCy Schubert 
1542b15cb3dSCy Schubert /*
1552b15cb3dSCy Schubert  * Peer status bits
1562b15cb3dSCy Schubert  */
1572b15cb3dSCy Schubert static const struct codestring peer_st_bits[] = {
1582b15cb3dSCy Schubert 	{ CTL_PST_CONFIG,		"conf" },
1592b15cb3dSCy Schubert 	{ CTL_PST_AUTHENABLE,		"authenb" },
1602b15cb3dSCy Schubert 	{ CTL_PST_AUTHENTIC,		"auth" },
1612b15cb3dSCy Schubert 	{ CTL_PST_REACH,		"reach" },
1622b15cb3dSCy Schubert 	{ CTL_PST_BCAST,		"bcast" },
1632b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
1642b15cb3dSCy Schubert };
1652b15cb3dSCy Schubert 
1662b15cb3dSCy Schubert /*
1672b15cb3dSCy Schubert  * Restriction match bits
1682b15cb3dSCy Schubert  */
1692b15cb3dSCy Schubert static const struct codestring res_match_bits[] = {
1702b15cb3dSCy Schubert 	{ RESM_NTPONLY,			"ntpport" },
1712b15cb3dSCy Schubert 	{ RESM_INTERFACE,		"interface" },
1722b15cb3dSCy Schubert 	{ RESM_SOURCE,			"source" },
1732b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
1742b15cb3dSCy Schubert };
1752b15cb3dSCy Schubert 
1762b15cb3dSCy Schubert /*
1772b15cb3dSCy Schubert  * Restriction access bits
1782b15cb3dSCy Schubert  */
1792b15cb3dSCy Schubert static const struct codestring res_access_bits[] = {
1802b15cb3dSCy Schubert 	{ RES_IGNORE,			"ignore" },
1812b15cb3dSCy Schubert 	{ RES_DONTSERVE,		"noserve" },
1822b15cb3dSCy Schubert 	{ RES_DONTTRUST,		"notrust" },
1832b15cb3dSCy Schubert 	{ RES_NOQUERY,			"noquery" },
1842b15cb3dSCy Schubert 	{ RES_NOMODIFY,			"nomodify" },
1852b15cb3dSCy Schubert 	{ RES_NOPEER,			"nopeer" },
1862b15cb3dSCy Schubert 	{ RES_NOTRAP,			"notrap" },
1872b15cb3dSCy Schubert 	{ RES_LPTRAP,			"lptrap" },
1882b15cb3dSCy Schubert 	{ RES_LIMITED,			"limited" },
1892b15cb3dSCy Schubert 	{ RES_VERSION,			"version" },
1902b15cb3dSCy Schubert 	{ RES_KOD,			"kod" },
1912b15cb3dSCy Schubert 	{ RES_FLAKE,			"flake" },
1922b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
1932b15cb3dSCy Schubert };
1942b15cb3dSCy Schubert 
1952b15cb3dSCy Schubert #ifdef AUTOKEY
1962b15cb3dSCy Schubert /*
1972b15cb3dSCy Schubert  * Crypto events (cryp)
1982b15cb3dSCy Schubert  */
1992b15cb3dSCy 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" },
2102b15cb3dSCy Schubert 	{ XEVNT_PER & ~CRPT_EVENT,	"host_certificate_expired" },
2119c2daa00SOllivier Robert 	{ XEVNT_CKY & ~CRPT_EVENT,	"bad_or_missing_cookie" },
2122b15cb3dSCy Schubert 	{ XEVNT_DAT & ~CRPT_EVENT,	"bad_or_missing_leapseconds" },
2139c2daa00SOllivier Robert 	{ XEVNT_CRT & ~CRPT_EVENT,	"bad_or_missing_certificate" },
2142b15cb3dSCy Schubert 	{ XEVNT_ID & ~CRPT_EVENT,	"bad_or_missing_group key" },
215ea906c41SOllivier Robert 	{ XEVNT_ERR & ~CRPT_EVENT,	"protocol_error" },
2162b15cb3dSCy Schubert 	{ -1,				"" }
2179c2daa00SOllivier Robert };
2182b15cb3dSCy Schubert #endif	/* AUTOKEY */
2192b15cb3dSCy Schubert 
2202b15cb3dSCy Schubert #ifdef KERNEL_PLL
2212b15cb3dSCy Schubert /*
2222b15cb3dSCy Schubert  * kernel discipline status bits
2232b15cb3dSCy Schubert  */
2242b15cb3dSCy Schubert static const struct codestring k_st_bits[] = {
2252b15cb3dSCy Schubert # ifdef STA_PLL
2262b15cb3dSCy Schubert 	{ STA_PLL,			"pll" },
2272b15cb3dSCy Schubert # endif
2282b15cb3dSCy Schubert # ifdef STA_PPSFREQ
2292b15cb3dSCy Schubert 	{ STA_PPSFREQ,			"ppsfreq" },
2302b15cb3dSCy Schubert # endif
2312b15cb3dSCy Schubert # ifdef STA_PPSTIME
2322b15cb3dSCy Schubert 	{ STA_PPSTIME,			"ppstime" },
2332b15cb3dSCy Schubert # endif
2342b15cb3dSCy Schubert # ifdef STA_FLL
2352b15cb3dSCy Schubert 	{ STA_FLL,			"fll" },
2362b15cb3dSCy Schubert # endif
2372b15cb3dSCy Schubert # ifdef STA_INS
2382b15cb3dSCy Schubert 	{ STA_INS,			"ins" },
2392b15cb3dSCy Schubert # endif
2402b15cb3dSCy Schubert # ifdef STA_DEL
2412b15cb3dSCy Schubert 	{ STA_DEL,			"del" },
2422b15cb3dSCy Schubert # endif
2432b15cb3dSCy Schubert # ifdef STA_UNSYNC
2442b15cb3dSCy Schubert 	{ STA_UNSYNC,			"unsync" },
2452b15cb3dSCy Schubert # endif
2462b15cb3dSCy Schubert # ifdef STA_FREQHOLD
2472b15cb3dSCy Schubert 	{ STA_FREQHOLD,			"freqhold" },
2482b15cb3dSCy Schubert # endif
2492b15cb3dSCy Schubert # ifdef STA_PPSSIGNAL
2502b15cb3dSCy Schubert 	{ STA_PPSSIGNAL,		"ppssignal" },
2512b15cb3dSCy Schubert # endif
2522b15cb3dSCy Schubert # ifdef STA_PPSJITTER
2532b15cb3dSCy Schubert 	{ STA_PPSJITTER,		"ppsjitter" },
2542b15cb3dSCy Schubert # endif
2552b15cb3dSCy Schubert # ifdef STA_PPSWANDER
2562b15cb3dSCy Schubert 	{ STA_PPSWANDER,		"ppswander" },
2572b15cb3dSCy Schubert # endif
2582b15cb3dSCy Schubert # ifdef STA_PPSERROR
2592b15cb3dSCy Schubert 	{ STA_PPSERROR,			"ppserror" },
2602b15cb3dSCy Schubert # endif
2612b15cb3dSCy Schubert # ifdef STA_CLOCKERR
2622b15cb3dSCy Schubert 	{ STA_CLOCKERR,			"clockerr" },
2632b15cb3dSCy Schubert # endif
2642b15cb3dSCy Schubert # ifdef STA_NANO
2652b15cb3dSCy Schubert 	{ STA_NANO,			"nano" },
2662b15cb3dSCy Schubert # endif
2672b15cb3dSCy Schubert # ifdef STA_MODE
2682b15cb3dSCy Schubert 	{ STA_MODE,			"mode=fll" },
2692b15cb3dSCy Schubert # endif
2702b15cb3dSCy Schubert # ifdef STA_CLK
2712b15cb3dSCy Schubert 	{ STA_CLK,			"src=B" },
2722b15cb3dSCy Schubert # endif
2732b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
2742b15cb3dSCy Schubert };
2752b15cb3dSCy Schubert #endif	/* KERNEL_PLL */
2769c2daa00SOllivier Robert 
277c0b746e5SOllivier Robert /* Forwards */
2782b15cb3dSCy Schubert static const char *	getcode(int, const struct codestring *);
2792b15cb3dSCy Schubert static const char *	getevents(int);
2802b15cb3dSCy 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,
2882b15cb3dSCy Schubert 	const struct codestring *	codetab
289c0b746e5SOllivier Robert 	)
290c0b746e5SOllivier Robert {
2912b15cb3dSCy 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 	}
2982b15cb3dSCy Schubert 
2992b15cb3dSCy Schubert 	LIB_GETBUF(buf);
3002b15cb3dSCy Schubert 	snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string, code);
3012b15cb3dSCy 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 {
3132b15cb3dSCy Schubert 	char *	buf;
314c0b746e5SOllivier Robert 
315c0b746e5SOllivier Robert 	if (cnt == 0)
316c0b746e5SOllivier Robert 		return "no events";
3172b15cb3dSCy Schubert 
3182b15cb3dSCy Schubert 	LIB_GETBUF(buf);
3192b15cb3dSCy Schubert 	snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt,
3202b15cb3dSCy Schubert 		 (1 == cnt)
3212b15cb3dSCy Schubert 		     ? ""
3222b15cb3dSCy Schubert 		     : "s");
3232b15cb3dSCy Schubert 
324c0b746e5SOllivier Robert 	return buf;
325c0b746e5SOllivier Robert }
326c0b746e5SOllivier Robert 
3272b15cb3dSCy Schubert 
3282b15cb3dSCy Schubert /*
3292b15cb3dSCy Schubert  * decode_bitflags()
3302b15cb3dSCy Schubert  *
3312b15cb3dSCy Schubert  * returns a human-readable string with a keyword from tab for each bit
3322b15cb3dSCy Schubert  * set in bits, separating multiple entries with text of sep2.
3332b15cb3dSCy Schubert  */
3342b15cb3dSCy Schubert static const char *
3352b15cb3dSCy Schubert decode_bitflags(
3362b15cb3dSCy Schubert 	int				bits,
3372b15cb3dSCy Schubert 	const char *			sep2,
3382b15cb3dSCy Schubert 	const struct codestring *	tab,
3392b15cb3dSCy Schubert 	size_t				tab_ct
3402b15cb3dSCy Schubert 	)
3412b15cb3dSCy Schubert {
3422b15cb3dSCy Schubert 	const char *	sep;
3432b15cb3dSCy Schubert 	char *		buf;
3442b15cb3dSCy Schubert 	char *		pch;
3452b15cb3dSCy Schubert 	char *		lim;
3462b15cb3dSCy Schubert 	size_t		b;
3472b15cb3dSCy Schubert 	int		rc;
3482b15cb3dSCy Schubert 	int		saved_errno;	/* for use in DPRINTF with %m */
3492b15cb3dSCy Schubert 
3502b15cb3dSCy Schubert 	saved_errno = errno;
3512b15cb3dSCy Schubert 	LIB_GETBUF(buf);
3522b15cb3dSCy Schubert 	pch = buf;
3532b15cb3dSCy Schubert 	lim = buf + LIB_BUFLENGTH;
3542b15cb3dSCy Schubert 	sep = "";
3552b15cb3dSCy Schubert 
3562b15cb3dSCy Schubert 	for (b = 0; b < tab_ct; b++) {
3572b15cb3dSCy Schubert 		if (tab[b].code & bits) {
358*f0574f5cSXin LI 			size_t avail = lim - pch;
359*f0574f5cSXin LI 			rc = snprintf(pch, avail, "%s%s", sep,
3602b15cb3dSCy Schubert 				      tab[b].string);
361*f0574f5cSXin LI 			if ((size_t)rc >= avail)
3622b15cb3dSCy Schubert 				goto toosmall;
363*f0574f5cSXin LI 			pch += rc;
3642b15cb3dSCy Schubert 			sep = sep2;
3652b15cb3dSCy Schubert 		}
3662b15cb3dSCy Schubert 	}
3672b15cb3dSCy Schubert 
3682b15cb3dSCy Schubert 	return buf;
3692b15cb3dSCy Schubert 
3702b15cb3dSCy Schubert     toosmall:
3712b15cb3dSCy Schubert 	snprintf(buf, LIB_BUFLENGTH,
3722b15cb3dSCy Schubert 		 "decode_bitflags(%s) can't decode 0x%x in %d bytes",
3732b15cb3dSCy Schubert 		 (tab == peer_st_bits)
3742b15cb3dSCy Schubert 		     ? "peer_st"
3752b15cb3dSCy Schubert 		     :
3762b15cb3dSCy Schubert #ifdef KERNEL_PLL
3772b15cb3dSCy Schubert 		       (tab == k_st_bits)
3782b15cb3dSCy Schubert 			   ? "kern_st"
3792b15cb3dSCy Schubert 			   :
3802b15cb3dSCy Schubert #endif
3812b15cb3dSCy Schubert 			     "",
3822b15cb3dSCy Schubert 		 bits, (int)LIB_BUFLENGTH);
3832b15cb3dSCy Schubert 	errno = saved_errno;
3842b15cb3dSCy Schubert 
3852b15cb3dSCy Schubert 	return buf;
3862b15cb3dSCy Schubert }
3872b15cb3dSCy Schubert 
3882b15cb3dSCy Schubert 
3892b15cb3dSCy Schubert static const char *
3902b15cb3dSCy Schubert peer_st_flags(
3912b15cb3dSCy Schubert 	u_char pst
3922b15cb3dSCy Schubert 	)
3932b15cb3dSCy Schubert {
3942b15cb3dSCy Schubert 	return decode_bitflags(pst, ", ", peer_st_bits,
3952b15cb3dSCy Schubert 			       COUNTOF(peer_st_bits));
3962b15cb3dSCy Schubert }
3972b15cb3dSCy Schubert 
3982b15cb3dSCy Schubert 
3992b15cb3dSCy Schubert const char *
4002b15cb3dSCy Schubert res_match_flags(
4012b15cb3dSCy Schubert 	u_short mf
4022b15cb3dSCy Schubert 	)
4032b15cb3dSCy Schubert {
4042b15cb3dSCy Schubert 	return decode_bitflags(mf, " ", res_match_bits,
4052b15cb3dSCy Schubert 			       COUNTOF(res_match_bits));
4062b15cb3dSCy Schubert }
4072b15cb3dSCy Schubert 
4082b15cb3dSCy Schubert 
4092b15cb3dSCy Schubert const char *
4102b15cb3dSCy Schubert res_access_flags(
4112b15cb3dSCy Schubert 	u_short af
4122b15cb3dSCy Schubert 	)
4132b15cb3dSCy Schubert {
4142b15cb3dSCy Schubert 	return decode_bitflags(af, " ", res_access_bits,
4152b15cb3dSCy Schubert 			       COUNTOF(res_access_bits));
4162b15cb3dSCy Schubert }
4172b15cb3dSCy Schubert 
4182b15cb3dSCy Schubert 
4192b15cb3dSCy Schubert #ifdef KERNEL_PLL
4202b15cb3dSCy Schubert const char *
4212b15cb3dSCy Schubert k_st_flags(
4222b15cb3dSCy Schubert 	u_int32 st
4232b15cb3dSCy Schubert 	)
4242b15cb3dSCy Schubert {
4252b15cb3dSCy Schubert 	return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits));
4262b15cb3dSCy Schubert }
4272b15cb3dSCy Schubert #endif	/* KERNEL_PLL */
4282b15cb3dSCy Schubert 
4292b15cb3dSCy Schubert 
430c0b746e5SOllivier Robert /*
431c0b746e5SOllivier Robert  * statustoa - return a descriptive string for a peer status
432c0b746e5SOllivier Robert  */
433c0b746e5SOllivier Robert char *
434c0b746e5SOllivier Robert statustoa(
435c0b746e5SOllivier Robert 	int type,
436c0b746e5SOllivier Robert 	int st
437c0b746e5SOllivier Robert 	)
438c0b746e5SOllivier Robert {
439c0b746e5SOllivier Robert 	char *	cb;
4402b15cb3dSCy Schubert 	char *	cc;
441c0b746e5SOllivier Robert 	u_char	pst;
442c0b746e5SOllivier Robert 
443c0b746e5SOllivier Robert 	LIB_GETBUF(cb);
444c0b746e5SOllivier Robert 
445c0b746e5SOllivier Robert 	switch (type) {
4462b15cb3dSCy Schubert 
447c0b746e5SOllivier Robert 	case TYPE_SYS:
4482b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s",
4492b15cb3dSCy Schubert 			 getcode(CTL_SYS_LI(st), leap_codes),
4502b15cb3dSCy Schubert 			 getcode(CTL_SYS_SOURCE(st), sync_codes),
4512b15cb3dSCy Schubert 			 getevents(CTL_SYS_NEVNT(st)),
4522b15cb3dSCy Schubert 			 getcode(CTL_SYS_EVENT(st), sys_codes));
453c0b746e5SOllivier Robert 		break;
454c0b746e5SOllivier Robert 
455c0b746e5SOllivier Robert 	case TYPE_PEER:
456c0b746e5SOllivier Robert 		pst = (u_char)CTL_PEER_STATVAL(st);
4572b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s",
4582b15cb3dSCy Schubert 			 peer_st_flags(pst),
4592b15cb3dSCy Schubert 			 getcode(pst & 0x7, select_codes),
4602b15cb3dSCy Schubert 			 getevents(CTL_PEER_NEVNT(st)));
461c0b746e5SOllivier Robert 		if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) {
4622b15cb3dSCy Schubert 			cc = cb + strlen(cb);
4632b15cb3dSCy Schubert 			snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s",
4642b15cb3dSCy Schubert 				 getcode(CTL_PEER_EVENT(st),
465c0b746e5SOllivier Robert 					 peer_codes));
466c0b746e5SOllivier Robert 		}
467c0b746e5SOllivier Robert 		break;
468c0b746e5SOllivier Robert 
469c0b746e5SOllivier Robert 	case TYPE_CLOCK:
4702b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s",
4712b15cb3dSCy Schubert 			 getevents(CTL_SYS_NEVNT(st)),
4722b15cb3dSCy Schubert 			 getcode((st) & 0xf, clock_codes));
473c0b746e5SOllivier Robert 		break;
474c0b746e5SOllivier Robert 	}
4752b15cb3dSCy Schubert 
476c0b746e5SOllivier Robert 	return cb;
477c0b746e5SOllivier Robert }
478c0b746e5SOllivier Robert 
479c0b746e5SOllivier Robert const char *
480c0b746e5SOllivier Robert eventstr(
481c0b746e5SOllivier Robert 	int num
482c0b746e5SOllivier Robert 	)
483c0b746e5SOllivier Robert {
4849c2daa00SOllivier Robert 	if (num & PEER_EVENT)
4859c2daa00SOllivier Robert 		return (getcode(num & ~PEER_EVENT, peer_codes));
4862b15cb3dSCy Schubert #ifdef AUTOKEY
4879c2daa00SOllivier Robert 	else if (num & CRPT_EVENT)
4889c2daa00SOllivier Robert 		return (getcode(num & ~CRPT_EVENT, crypto_codes));
4892b15cb3dSCy Schubert #endif	/* AUTOKEY */
4909c2daa00SOllivier Robert 	else
4919c2daa00SOllivier Robert 		return (getcode(num, sys_codes));
492c0b746e5SOllivier Robert }
493c0b746e5SOllivier Robert 
494c0b746e5SOllivier Robert const char *
495c0b746e5SOllivier Robert ceventstr(
496c0b746e5SOllivier Robert 	int num
497c0b746e5SOllivier Robert 	)
498c0b746e5SOllivier Robert {
499c0b746e5SOllivier Robert 	return getcode(num, clock_codes);
500c0b746e5SOllivier Robert }
501