xref: /freebsd/contrib/ntp/libntp/statestr.c (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
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 "ntp_refclock.h"
12c0b746e5SOllivier Robert #include "ntp_control.h"
13c0b746e5SOllivier Robert #include "ntp_string.h"
142b15cb3dSCy Schubert #ifdef KERNEL_PLL
152b15cb3dSCy Schubert # include "ntp_syscall.h"
162b15cb3dSCy Schubert #endif
172b15cb3dSCy Schubert 
18c0b746e5SOllivier Robert 
19c0b746e5SOllivier Robert /*
20c0b746e5SOllivier Robert  * Structure for turning various constants into a readable string.
21c0b746e5SOllivier Robert  */
22c0b746e5SOllivier Robert struct codestring {
23c0b746e5SOllivier Robert 	int code;
2409100258SXin LI 	const char * const string1;
2509100258SXin LI 	const char * const string0;
26c0b746e5SOllivier Robert };
27c0b746e5SOllivier Robert 
28c0b746e5SOllivier Robert /*
292b15cb3dSCy Schubert  * Leap status (leap)
30c0b746e5SOllivier Robert  */
312b15cb3dSCy Schubert static const struct codestring leap_codes[] = {
3209100258SXin LI 	{ LEAP_NOWARNING,	"leap_none",	0 },
3309100258SXin LI 	{ LEAP_ADDSECOND,	"leap_add_sec",	0 },
3409100258SXin LI 	{ LEAP_DELSECOND,	"leap_del_sec",	0 },
3509100258SXin LI 	{ LEAP_NOTINSYNC,	"leap_alarm",	0 },
3609100258SXin LI 	{ -1,			"leap",		0 }
37c0b746e5SOllivier Robert };
38c0b746e5SOllivier Robert 
39c0b746e5SOllivier Robert /*
402b15cb3dSCy Schubert  * Clock source status (sync)
41c0b746e5SOllivier Robert  */
422b15cb3dSCy Schubert static const struct codestring sync_codes[] = {
4309100258SXin LI 	{ CTL_SST_TS_UNSPEC,	"sync_unspec",		0 },
4409100258SXin LI 	{ CTL_SST_TS_ATOM,	"sync_pps",		0 },
4509100258SXin LI 	{ CTL_SST_TS_LF,	"sync_lf_radio",	0 },
4609100258SXin LI 	{ CTL_SST_TS_HF,	"sync_hf_radio",	0 },
4709100258SXin LI 	{ CTL_SST_TS_UHF,	"sync_uhf_radio",	0 },
4809100258SXin LI 	{ CTL_SST_TS_LOCAL,	"sync_local",		0 },
4909100258SXin LI 	{ CTL_SST_TS_NTP,	"sync_ntp",		0 },
5009100258SXin LI 	{ CTL_SST_TS_UDPTIME,	"sync_other",		0 },
5109100258SXin LI 	{ CTL_SST_TS_WRSTWTCH,	"sync_wristwatch",	0 },
5209100258SXin LI 	{ CTL_SST_TS_TELEPHONE,	"sync_telephone",	0 },
5309100258SXin LI 	{ -1,			"sync",			0 }
54c0b746e5SOllivier Robert };
55c0b746e5SOllivier Robert 
56c0b746e5SOllivier Robert /*
572b15cb3dSCy Schubert  * Peer selection status (sel)
58c0b746e5SOllivier Robert  */
592b15cb3dSCy Schubert static const struct codestring select_codes[] = {
6009100258SXin LI 	{ CTL_PST_SEL_REJECT,	"sel_reject",		0 },
6109100258SXin LI 	{ CTL_PST_SEL_SANE,	"sel_falsetick",	0 },
6209100258SXin LI 	{ CTL_PST_SEL_CORRECT,	"sel_excess",		0 },
6309100258SXin LI 	{ CTL_PST_SEL_SELCAND,	"sel_outlier",		0 },
6409100258SXin LI 	{ CTL_PST_SEL_SYNCCAND,	"sel_candidate",	0 },
6509100258SXin LI 	{ CTL_PST_SEL_EXCESS,	"sel_backup",		0 },
6609100258SXin LI 	{ CTL_PST_SEL_SYSPEER,	"sel_sys.peer",		0 },
6709100258SXin LI 	{ CTL_PST_SEL_PPS,	"sel_pps.peer",		0 },
6809100258SXin LI 	{ -1,			"sel",			0 }
69c0b746e5SOllivier Robert };
70c0b746e5SOllivier Robert 
71c0b746e5SOllivier Robert /*
722b15cb3dSCy Schubert  * Clock status (clk)
73c0b746e5SOllivier Robert  */
742b15cb3dSCy Schubert static const struct codestring clock_codes[] = {
7509100258SXin LI 	{ CTL_CLK_OKAY,		"clk_unspec",		0 },
7609100258SXin LI 	{ CTL_CLK_NOREPLY,	"clk_no_reply",		0 },
7709100258SXin LI 	{ CTL_CLK_BADFORMAT,	"clk_bad_format",	0 },
7809100258SXin LI 	{ CTL_CLK_FAULT,	"clk_fault",		0 },
7909100258SXin LI 	{ CTL_CLK_PROPAGATION,	"clk_bad_signal",	0 },
8009100258SXin LI 	{ CTL_CLK_BADDATE,	"clk_bad_date",		0 },
8109100258SXin LI 	{ CTL_CLK_BADTIME,	"clk_bad_time",		0 },
8209100258SXin LI 	{ -1,			"clk",			0 }
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[] = {
9109100258SXin LI 	{ TEST1,		"pkt_dup",	0 },
9209100258SXin LI 	{ TEST2,		"pkt_bogus",	0 },
9309100258SXin LI 	{ TEST3,		"pkt_unsync",	0 },
9409100258SXin LI 	{ TEST4,		"pkt_denied",	0 },
9509100258SXin LI 	{ TEST5,		"pkt_auth",	0 },
9609100258SXin LI 	{ TEST6,		"pkt_stratum",	0 },
9709100258SXin LI 	{ TEST7,		"pkt_header",	0 },
9809100258SXin LI 	{ TEST8,		"pkt_autokey",	0 },
9909100258SXin LI 	{ TEST9,		"pkt_crypto",	0 },
10009100258SXin LI 	{ TEST10,		"peer_stratum",	0 },
10109100258SXin LI 	{ TEST11,		"peer_dist",	0 },
10209100258SXin LI 	{ TEST12,		"peer_loop",	0 },
10309100258SXin LI 	{ TEST13,		"peer_unreach",	0 },
10409100258SXin LI 	{ -1,			"flash",	0 }
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[] = {
11309100258SXin LI 	{ EVNT_UNSPEC,		"unspecified",			0 },
11409100258SXin LI 	{ EVNT_NSET,		"freq_not_set",			0 },
11509100258SXin LI 	{ EVNT_FSET,		"freq_set",			0 },
11609100258SXin LI 	{ EVNT_SPIK,		"spike_detect",			0 },
11709100258SXin LI 	{ EVNT_FREQ,		"freq_mode",			0 },
11809100258SXin LI 	{ EVNT_SYNC,		"clock_sync",			0 },
11909100258SXin LI 	{ EVNT_SYSRESTART,	"restart",			0 },
12009100258SXin LI 	{ EVNT_SYSFAULT,	"panic_stop",			0 },
12109100258SXin LI 	{ EVNT_NOPEER,		"no_sys_peer",			0 },
12209100258SXin LI 	{ EVNT_ARMED,		"leap_armed",			0 },
12309100258SXin LI 	{ EVNT_DISARMED,	"leap_disarmed",		0 },
12409100258SXin LI 	{ EVNT_LEAP,		"leap_event",			0 },
12509100258SXin LI 	{ EVNT_CLOCKRESET,	"clock_step",			0 },
12609100258SXin LI 	{ EVNT_KERN,		"kern",				0 },
12709100258SXin LI 	{ EVNT_TAI,		"TAI",				0 },
12809100258SXin LI 	{ EVNT_LEAPVAL,		"stale_leapsecond_values",	0 },
12909100258SXin LI 	{ -1,			"",				0 }
130c0b746e5SOllivier Robert };
131c0b746e5SOllivier Robert 
1329c2daa00SOllivier Robert /*
1332b15cb3dSCy Schubert  * Peer events (peer)
1349c2daa00SOllivier Robert  */
1352b15cb3dSCy Schubert static const struct codestring peer_codes[] = {
13609100258SXin LI 	{ PEVNT_MOBIL & ~PEER_EVENT,	"mobilize",		0 },
13709100258SXin LI 	{ PEVNT_DEMOBIL & ~PEER_EVENT,	"demobilize",		0 },
13809100258SXin LI 	{ PEVNT_UNREACH & ~PEER_EVENT,	"unreachable",		0 },
13909100258SXin LI 	{ PEVNT_REACH & ~PEER_EVENT,	"reachable",		0 },
14009100258SXin LI 	{ PEVNT_RESTART & ~PEER_EVENT,	"restart",		0 },
14109100258SXin LI 	{ PEVNT_REPLY & ~PEER_EVENT,	"no_reply",		0 },
14209100258SXin LI 	{ PEVNT_RATE & ~PEER_EVENT,	"rate_exceeded",	0 },
14309100258SXin LI 	{ PEVNT_DENY & ~PEER_EVENT,	"access_denied",	0 },
14409100258SXin LI 	{ PEVNT_ARMED & ~PEER_EVENT,	"leap_armed",		0 },
14509100258SXin LI 	{ PEVNT_NEWPEER & ~PEER_EVENT,	"sys_peer",		0 },
14609100258SXin LI 	{ PEVNT_CLOCK & ~PEER_EVENT,	"clock_event",		0 },
14709100258SXin LI 	{ PEVNT_AUTH & ~PEER_EVENT,	"bad_auth",		0 },
14809100258SXin LI 	{ PEVNT_POPCORN & ~PEER_EVENT,	"popcorn",		0 },
14909100258SXin LI 	{ PEVNT_XLEAVE & ~PEER_EVENT,	"interleave_mode",	0 },
15009100258SXin LI 	{ PEVNT_XERR & ~PEER_EVENT,	"interleave_error",	0 },
15109100258SXin LI 	{ -1,				"",			0 }
1522b15cb3dSCy Schubert };
1532b15cb3dSCy Schubert 
1542b15cb3dSCy Schubert /*
1552b15cb3dSCy Schubert  * Peer status bits
1562b15cb3dSCy Schubert  */
1572b15cb3dSCy Schubert static const struct codestring peer_st_bits[] = {
15809100258SXin LI 	{ CTL_PST_CONFIG,		"conf",		0 },
15909100258SXin LI 	{ CTL_PST_AUTHENABLE,		"authenb",	0 },
16009100258SXin LI 	{ CTL_PST_AUTHENTIC,		"auth",		0 },
16109100258SXin LI 	{ CTL_PST_REACH,		"reach",	0 },
16209100258SXin LI 	{ CTL_PST_BCAST,		"bcast",	0 },
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[] = {
17009100258SXin LI 	{ RESM_NTPONLY,			"ntpport",	0 },
17109100258SXin LI 	{ RESM_INTERFACE,		"interface",	0 },
17209100258SXin LI 	{ RESM_SOURCE,			"source",	0 },
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[] = {
18009100258SXin LI 	{ RES_IGNORE,			"ignore",	0 },
18109100258SXin LI 	{ RES_DONTSERVE,		"noserve",	"serve" },
18209100258SXin LI 	{ RES_DONTTRUST,		"notrust",	"trust" },
183*2d4e511cSCy Schubert 	{ RES_VERSION,			"version",	0 },
18409100258SXin LI 	{ RES_NOPEER,			"nopeer",	"peer" },
18509100258SXin LI 	{ RES_NOEPEER,			"noepeer",	"epeer" },
186*2d4e511cSCy Schubert 	{ RES_LIMITED,			"limited",	0 },
187*2d4e511cSCy Schubert 
188*2d4e511cSCy Schubert 	{ RES_NOQUERY,			"noquery",	"query" },
189*2d4e511cSCy Schubert 	{ RES_NOMODIFY,			"nomodify",	0 },
19009100258SXin LI 	{ RES_NOTRAP,			"notrap",	"trap" },
19109100258SXin LI 	{ RES_LPTRAP,			"lptrap",	0 },
192*2d4e511cSCy Schubert 
19309100258SXin LI 	{ RES_KOD,			"kod",		0 },
194*2d4e511cSCy Schubert 	{ RES_MSSNTP,			"mssntp",	0 },
19509100258SXin LI 	{ RES_FLAKE,			"flake",	0 },
196*2d4e511cSCy Schubert 	{ RES_NOMRULIST,		"nomrulist",	0 },
197*2d4e511cSCy Schubert 
198*2d4e511cSCy Schubert 	{ RES_SRVRSPFUZ,		"serverresponse fuzz",	0 },
199*2d4e511cSCy Schubert 
2002b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
2012b15cb3dSCy Schubert };
2022b15cb3dSCy Schubert 
2032b15cb3dSCy Schubert #ifdef AUTOKEY
2042b15cb3dSCy Schubert /*
2052b15cb3dSCy Schubert  * Crypto events (cryp)
2062b15cb3dSCy Schubert  */
2072b15cb3dSCy Schubert static const struct codestring crypto_codes[] = {
20809100258SXin LI 	{ XEVNT_OK & ~CRPT_EVENT,	"success",			0 },
20909100258SXin LI 	{ XEVNT_LEN & ~CRPT_EVENT,	"bad_field_format_or_length",	0 },
21009100258SXin LI 	{ XEVNT_TSP & ~CRPT_EVENT,	"bad_timestamp",		0 },
21109100258SXin LI 	{ XEVNT_FSP & ~CRPT_EVENT,	"bad_filestamp",		0 },
21209100258SXin LI 	{ XEVNT_PUB & ~CRPT_EVENT,	"bad_or_missing_public_key",	0 },
21309100258SXin LI 	{ XEVNT_MD & ~CRPT_EVENT,	"unsupported_digest_type",	0 },
21409100258SXin LI 	{ XEVNT_KEY & ~CRPT_EVENT,	"unsupported_identity_type",	0 },
21509100258SXin LI 	{ XEVNT_SGL & ~CRPT_EVENT,	"bad_signature_length",		0 },
21609100258SXin LI 	{ XEVNT_SIG & ~CRPT_EVENT,	"signature_not_verified",	0 },
21709100258SXin LI 	{ XEVNT_VFY & ~CRPT_EVENT,	"certificate_not_verified",	0 },
21809100258SXin LI 	{ XEVNT_PER & ~CRPT_EVENT,	"host_certificate_expired",	0 },
21909100258SXin LI 	{ XEVNT_CKY & ~CRPT_EVENT,	"bad_or_missing_cookie",	0 },
22009100258SXin LI 	{ XEVNT_DAT & ~CRPT_EVENT,	"bad_or_missing_leapseconds",	0 },
22109100258SXin LI 	{ XEVNT_CRT & ~CRPT_EVENT,	"bad_or_missing_certificate",	0 },
22209100258SXin LI 	{ XEVNT_ID & ~CRPT_EVENT,	"bad_or_missing_group key",	0 },
22309100258SXin LI 	{ XEVNT_ERR & ~CRPT_EVENT,	"protocol_error",		0 },
22409100258SXin LI 	{ -1,				"",				0 }
2259c2daa00SOllivier Robert };
2262b15cb3dSCy Schubert #endif	/* AUTOKEY */
2272b15cb3dSCy Schubert 
2282b15cb3dSCy Schubert #ifdef KERNEL_PLL
2292b15cb3dSCy Schubert /*
2302b15cb3dSCy Schubert  * kernel discipline status bits
2312b15cb3dSCy Schubert  */
2322b15cb3dSCy Schubert static const struct codestring k_st_bits[] = {
2332b15cb3dSCy Schubert # ifdef STA_PLL
23409100258SXin LI 	{ STA_PLL,			"pll",		0 },
2352b15cb3dSCy Schubert # endif
2362b15cb3dSCy Schubert # ifdef STA_PPSFREQ
23709100258SXin LI 	{ STA_PPSFREQ,			"ppsfreq",	0 },
2382b15cb3dSCy Schubert # endif
2392b15cb3dSCy Schubert # ifdef STA_PPSTIME
24009100258SXin LI 	{ STA_PPSTIME,			"ppstime",	0 },
2412b15cb3dSCy Schubert # endif
2422b15cb3dSCy Schubert # ifdef STA_FLL
24309100258SXin LI 	{ STA_FLL,			"fll",		0 },
2442b15cb3dSCy Schubert # endif
2452b15cb3dSCy Schubert # ifdef STA_INS
24609100258SXin LI 	{ STA_INS,			"ins",		0 },
2472b15cb3dSCy Schubert # endif
2482b15cb3dSCy Schubert # ifdef STA_DEL
24909100258SXin LI 	{ STA_DEL,			"del",		0 },
2502b15cb3dSCy Schubert # endif
2512b15cb3dSCy Schubert # ifdef STA_UNSYNC
25209100258SXin LI 	{ STA_UNSYNC,			"unsync",	0 },
2532b15cb3dSCy Schubert # endif
2542b15cb3dSCy Schubert # ifdef STA_FREQHOLD
25509100258SXin LI 	{ STA_FREQHOLD,			"freqhold",	0 },
2562b15cb3dSCy Schubert # endif
2572b15cb3dSCy Schubert # ifdef STA_PPSSIGNAL
25809100258SXin LI 	{ STA_PPSSIGNAL,		"ppssignal",	0 },
2592b15cb3dSCy Schubert # endif
2602b15cb3dSCy Schubert # ifdef STA_PPSJITTER
26109100258SXin LI 	{ STA_PPSJITTER,		"ppsjitter",	0 },
2622b15cb3dSCy Schubert # endif
2632b15cb3dSCy Schubert # ifdef STA_PPSWANDER
26409100258SXin LI 	{ STA_PPSWANDER,		"ppswander",	0 },
2652b15cb3dSCy Schubert # endif
2662b15cb3dSCy Schubert # ifdef STA_PPSERROR
26709100258SXin LI 	{ STA_PPSERROR,			"ppserror",	0 },
2682b15cb3dSCy Schubert # endif
2692b15cb3dSCy Schubert # ifdef STA_CLOCKERR
27009100258SXin LI 	{ STA_CLOCKERR,			"clockerr",	0 },
2712b15cb3dSCy Schubert # endif
2722b15cb3dSCy Schubert # ifdef STA_NANO
27309100258SXin LI 	{ STA_NANO,			"nano",		0 },
2742b15cb3dSCy Schubert # endif
2752b15cb3dSCy Schubert # ifdef STA_MODE
27609100258SXin LI 	{ STA_MODE,			"mode=fll",	0 },
2772b15cb3dSCy Schubert # endif
2782b15cb3dSCy Schubert # ifdef STA_CLK
27909100258SXin LI 	{ STA_CLK,			"src=B",	0 },
2802b15cb3dSCy Schubert # endif
2812b15cb3dSCy Schubert 	/* not used with getcode(), no terminating entry needed */
2822b15cb3dSCy Schubert };
2832b15cb3dSCy Schubert #endif	/* KERNEL_PLL */
2849c2daa00SOllivier Robert 
285c0b746e5SOllivier Robert /* Forwards */
2862b15cb3dSCy Schubert static const char *	getcode(int, const struct codestring *);
2872b15cb3dSCy Schubert static const char *	getevents(int);
2882b15cb3dSCy Schubert static const char *	peer_st_flags(u_char pst);
289c0b746e5SOllivier Robert 
290c0b746e5SOllivier Robert /*
291c0b746e5SOllivier Robert  * getcode - return string corresponding to code
292c0b746e5SOllivier Robert  */
293c0b746e5SOllivier Robert static const char *
294c0b746e5SOllivier Robert getcode(
295c0b746e5SOllivier Robert 	int				code,
2962b15cb3dSCy Schubert 	const struct codestring *	codetab
297c0b746e5SOllivier Robert 	)
298c0b746e5SOllivier Robert {
2992b15cb3dSCy Schubert 	char *	buf;
300c0b746e5SOllivier Robert 
301c0b746e5SOllivier Robert 	while (codetab->code != -1) {
302c0b746e5SOllivier Robert 		if (codetab->code == code)
30309100258SXin LI 			return codetab->string1;
304c0b746e5SOllivier Robert 		codetab++;
305c0b746e5SOllivier Robert 	}
3062b15cb3dSCy Schubert 
3072b15cb3dSCy Schubert 	LIB_GETBUF(buf);
30809100258SXin LI 	snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string1, code);
3092b15cb3dSCy Schubert 
310c0b746e5SOllivier Robert 	return buf;
311c0b746e5SOllivier Robert }
312c0b746e5SOllivier Robert 
313c0b746e5SOllivier Robert /*
314c0b746e5SOllivier Robert  * getevents - return a descriptive string for the event count
315c0b746e5SOllivier Robert  */
316c0b746e5SOllivier Robert static const char *
317c0b746e5SOllivier Robert getevents(
318c0b746e5SOllivier Robert 	int cnt
319c0b746e5SOllivier Robert 	)
320c0b746e5SOllivier Robert {
3212b15cb3dSCy Schubert 	char *	buf;
322c0b746e5SOllivier Robert 
323c0b746e5SOllivier Robert 	if (cnt == 0)
324c0b746e5SOllivier Robert 		return "no events";
3252b15cb3dSCy Schubert 
3262b15cb3dSCy Schubert 	LIB_GETBUF(buf);
3272b15cb3dSCy Schubert 	snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt,
3282b15cb3dSCy Schubert 		 (1 == cnt)
3292b15cb3dSCy Schubert 		     ? ""
3302b15cb3dSCy Schubert 		     : "s");
3312b15cb3dSCy Schubert 
332c0b746e5SOllivier Robert 	return buf;
333c0b746e5SOllivier Robert }
334c0b746e5SOllivier Robert 
3352b15cb3dSCy Schubert 
3362b15cb3dSCy Schubert /*
3372b15cb3dSCy Schubert  * decode_bitflags()
3382b15cb3dSCy Schubert  *
3392b15cb3dSCy Schubert  * returns a human-readable string with a keyword from tab for each bit
3402b15cb3dSCy Schubert  * set in bits, separating multiple entries with text of sep2.
3412b15cb3dSCy Schubert  */
3422b15cb3dSCy Schubert static const char *
3432b15cb3dSCy Schubert decode_bitflags(
3442b15cb3dSCy Schubert 	int				bits,
3452b15cb3dSCy Schubert 	const char *			sep2,
3462b15cb3dSCy Schubert 	const struct codestring *	tab,
3472b15cb3dSCy Schubert 	size_t				tab_ct
3482b15cb3dSCy Schubert 	)
3492b15cb3dSCy Schubert {
3502b15cb3dSCy Schubert 	const char *	sep;
3512b15cb3dSCy Schubert 	char *		buf;
3522b15cb3dSCy Schubert 	char *		pch;
3532b15cb3dSCy Schubert 	char *		lim;
3542b15cb3dSCy Schubert 	size_t		b;
3552b15cb3dSCy Schubert 	int		rc;
3562b15cb3dSCy Schubert 	int		saved_errno;	/* for use in DPRINTF with %m */
3572b15cb3dSCy Schubert 
3582b15cb3dSCy Schubert 	saved_errno = errno;
3592b15cb3dSCy Schubert 	LIB_GETBUF(buf);
3602b15cb3dSCy Schubert 	pch = buf;
3612b15cb3dSCy Schubert 	lim = buf + LIB_BUFLENGTH;
3622b15cb3dSCy Schubert 	sep = "";
3632b15cb3dSCy Schubert 
3642b15cb3dSCy Schubert 	for (b = 0; b < tab_ct; b++) {
36509100258SXin LI 		const char * flagstr;
36609100258SXin LI 
3672b15cb3dSCy Schubert 		if (tab[b].code & bits) {
36809100258SXin LI 			flagstr = tab[b].string1;
36909100258SXin LI 		} else {
37009100258SXin LI 			flagstr = tab[b].string0;
37109100258SXin LI 		}
37209100258SXin LI 
37309100258SXin LI 		if (flagstr) {
374f0574f5cSXin LI 			size_t avail = lim - pch;
375f0574f5cSXin LI 			rc = snprintf(pch, avail, "%s%s", sep,
37609100258SXin LI 				      flagstr);
377f0574f5cSXin LI 			if ((size_t)rc >= avail)
3782b15cb3dSCy Schubert 				goto toosmall;
379f0574f5cSXin LI 			pch += rc;
3802b15cb3dSCy Schubert 			sep = sep2;
3812b15cb3dSCy Schubert 		}
3822b15cb3dSCy Schubert 	}
3832b15cb3dSCy Schubert 
3842b15cb3dSCy Schubert 	return buf;
3852b15cb3dSCy Schubert 
3862b15cb3dSCy Schubert     toosmall:
3872b15cb3dSCy Schubert 	snprintf(buf, LIB_BUFLENGTH,
3882b15cb3dSCy Schubert 		 "decode_bitflags(%s) can't decode 0x%x in %d bytes",
3892b15cb3dSCy Schubert 		 (tab == peer_st_bits)
3902b15cb3dSCy Schubert 		     ? "peer_st"
3912b15cb3dSCy Schubert 		     :
3922b15cb3dSCy Schubert #ifdef KERNEL_PLL
3932b15cb3dSCy Schubert 		       (tab == k_st_bits)
3942b15cb3dSCy Schubert 			   ? "kern_st"
3952b15cb3dSCy Schubert 			   :
3962b15cb3dSCy Schubert #endif
3972b15cb3dSCy Schubert 			     "",
3982b15cb3dSCy Schubert 		 bits, (int)LIB_BUFLENGTH);
3992b15cb3dSCy Schubert 	errno = saved_errno;
4002b15cb3dSCy Schubert 
4012b15cb3dSCy Schubert 	return buf;
4022b15cb3dSCy Schubert }
4032b15cb3dSCy Schubert 
4042b15cb3dSCy Schubert 
4052b15cb3dSCy Schubert static const char *
4062b15cb3dSCy Schubert peer_st_flags(
4072b15cb3dSCy Schubert 	u_char pst
4082b15cb3dSCy Schubert 	)
4092b15cb3dSCy Schubert {
4102b15cb3dSCy Schubert 	return decode_bitflags(pst, ", ", peer_st_bits,
4112b15cb3dSCy Schubert 			       COUNTOF(peer_st_bits));
4122b15cb3dSCy Schubert }
4132b15cb3dSCy Schubert 
4142b15cb3dSCy Schubert 
4152b15cb3dSCy Schubert const char *
4162b15cb3dSCy Schubert res_match_flags(
4172b15cb3dSCy Schubert 	u_short mf
4182b15cb3dSCy Schubert 	)
4192b15cb3dSCy Schubert {
4202b15cb3dSCy Schubert 	return decode_bitflags(mf, " ", res_match_bits,
4212b15cb3dSCy Schubert 			       COUNTOF(res_match_bits));
4222b15cb3dSCy Schubert }
4232b15cb3dSCy Schubert 
4242b15cb3dSCy Schubert 
4252b15cb3dSCy Schubert const char *
4262b15cb3dSCy Schubert res_access_flags(
427*2d4e511cSCy Schubert 	u_int32 af
4282b15cb3dSCy Schubert 	)
4292b15cb3dSCy Schubert {
4302b15cb3dSCy Schubert 	return decode_bitflags(af, " ", res_access_bits,
4312b15cb3dSCy Schubert 			       COUNTOF(res_access_bits));
4322b15cb3dSCy Schubert }
4332b15cb3dSCy Schubert 
4342b15cb3dSCy Schubert 
4352b15cb3dSCy Schubert #ifdef KERNEL_PLL
4362b15cb3dSCy Schubert const char *
4372b15cb3dSCy Schubert k_st_flags(
4382b15cb3dSCy Schubert 	u_int32 st
4392b15cb3dSCy Schubert 	)
4402b15cb3dSCy Schubert {
4412b15cb3dSCy Schubert 	return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits));
4422b15cb3dSCy Schubert }
4432b15cb3dSCy Schubert #endif	/* KERNEL_PLL */
4442b15cb3dSCy Schubert 
4452b15cb3dSCy Schubert 
446c0b746e5SOllivier Robert /*
447c0b746e5SOllivier Robert  * statustoa - return a descriptive string for a peer status
448c0b746e5SOllivier Robert  */
449c0b746e5SOllivier Robert char *
450c0b746e5SOllivier Robert statustoa(
451c0b746e5SOllivier Robert 	int type,
452c0b746e5SOllivier Robert 	int st
453c0b746e5SOllivier Robert 	)
454c0b746e5SOllivier Robert {
455c0b746e5SOllivier Robert 	char *	cb;
4562b15cb3dSCy Schubert 	char *	cc;
457c0b746e5SOllivier Robert 	u_char	pst;
458c0b746e5SOllivier Robert 
459c0b746e5SOllivier Robert 	LIB_GETBUF(cb);
460c0b746e5SOllivier Robert 
461c0b746e5SOllivier Robert 	switch (type) {
4622b15cb3dSCy Schubert 
463c0b746e5SOllivier Robert 	case TYPE_SYS:
4642b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s",
4652b15cb3dSCy Schubert 			 getcode(CTL_SYS_LI(st), leap_codes),
4662b15cb3dSCy Schubert 			 getcode(CTL_SYS_SOURCE(st), sync_codes),
4672b15cb3dSCy Schubert 			 getevents(CTL_SYS_NEVNT(st)),
4682b15cb3dSCy Schubert 			 getcode(CTL_SYS_EVENT(st), sys_codes));
469c0b746e5SOllivier Robert 		break;
470c0b746e5SOllivier Robert 
471c0b746e5SOllivier Robert 	case TYPE_PEER:
472c0b746e5SOllivier Robert 		pst = (u_char)CTL_PEER_STATVAL(st);
4732b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s",
4742b15cb3dSCy Schubert 			 peer_st_flags(pst),
4752b15cb3dSCy Schubert 			 getcode(pst & 0x7, select_codes),
4762b15cb3dSCy Schubert 			 getevents(CTL_PEER_NEVNT(st)));
477c0b746e5SOllivier Robert 		if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) {
4782b15cb3dSCy Schubert 			cc = cb + strlen(cb);
4792b15cb3dSCy Schubert 			snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s",
4802b15cb3dSCy Schubert 				 getcode(CTL_PEER_EVENT(st),
481c0b746e5SOllivier Robert 					 peer_codes));
482c0b746e5SOllivier Robert 		}
483c0b746e5SOllivier Robert 		break;
484c0b746e5SOllivier Robert 
485c0b746e5SOllivier Robert 	case TYPE_CLOCK:
4862b15cb3dSCy Schubert 		snprintf(cb, LIB_BUFLENGTH, "%s, %s",
4872b15cb3dSCy Schubert 			 getevents(CTL_SYS_NEVNT(st)),
4882b15cb3dSCy Schubert 			 getcode((st) & 0xf, clock_codes));
489c0b746e5SOllivier Robert 		break;
490c0b746e5SOllivier Robert 	}
4912b15cb3dSCy Schubert 
492c0b746e5SOllivier Robert 	return cb;
493c0b746e5SOllivier Robert }
494c0b746e5SOllivier Robert 
495c0b746e5SOllivier Robert const char *
496c0b746e5SOllivier Robert eventstr(
497c0b746e5SOllivier Robert 	int num
498c0b746e5SOllivier Robert 	)
499c0b746e5SOllivier Robert {
5009c2daa00SOllivier Robert 	if (num & PEER_EVENT)
5019c2daa00SOllivier Robert 		return (getcode(num & ~PEER_EVENT, peer_codes));
5022b15cb3dSCy Schubert #ifdef AUTOKEY
5039c2daa00SOllivier Robert 	else if (num & CRPT_EVENT)
5049c2daa00SOllivier Robert 		return (getcode(num & ~CRPT_EVENT, crypto_codes));
5052b15cb3dSCy Schubert #endif	/* AUTOKEY */
5069c2daa00SOllivier Robert 	else
5079c2daa00SOllivier Robert 		return (getcode(num, sys_codes));
508c0b746e5SOllivier Robert }
509c0b746e5SOllivier Robert 
510c0b746e5SOllivier Robert const char *
511c0b746e5SOllivier Robert ceventstr(
512c0b746e5SOllivier Robert 	int num
513c0b746e5SOllivier Robert 	)
514c0b746e5SOllivier Robert {
515c0b746e5SOllivier Robert 	return getcode(num, clock_codes);
516c0b746e5SOllivier Robert }
517