xref: /freebsd/contrib/ntp/libntp/statestr.c (revision 2b15cb3d0922bd70ea592f0da9b4a5b167f4d53f)
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