Coverage Report

Created: 2026-02-26 06:20

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