Coverage Report

Created: 2025-07-18 06:53

/src/ntpsec/include/ntp_fp.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ntp_fp.h - definitions for NTP fixed/floating-point arithmetic
3
 */
4
5
#ifndef GUARD_NTP_FP_H
6
#define GUARD_NTP_FP_H
7
8
#include <arpa/inet.h>
9
10
#include "ntp_types.h"
11
12
/*
13
 * NTP uses two fixed point formats.
14
 *
15
 * The first (l_fp) is the "long" format and is 64 bits wide in units
16
 * of 1/2^32 seconds (which is between 232 and 233 decimal
17
 * picoseconds).  The zero value signifies the zero date of the
18
 * current NTP era; era zero began on the date 1900-00-00T00:00:00 in
19
 * proleptic UTC (leap second correction was not introduced until
20
 * 1972).
21
 *
22
 * The long format is used for timestamps in the NTP packet header (in
23
 * network byte order).  It is defined in RFC 5905 in Section 6 (Data
24
 * Types). In the on-the-wire context, it is always unsigned.
25
 *
26
 * When it is convenient to compute in seconds, this type can
27
 * be interpreted as a fixed-point float with the radix point between
28
 * bits 31 and 32. This is why there are macros to extract the low and
29
 * high halves.
30
 *
31
 * Internally, this type is sometimes used for time offsets.  In that
32
 * context it is interpreted as signed and can only express offsets
33
 * up to a half cycle. Offsets are normally much, much smaller than that;
34
 * for an offset to have a value even as large as 1 second would be
35
 * highly unusual after ntpd initialization.
36
 *
37
 * Anyway, an l_fp looks like:
38
 *
39
 *    0       1         2       3
40
 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
 *   |             Integral Part           |
43
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
 *   |             Fractional Part           |
45
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
 *
47
 * NTP time stamps will overflow in 2036.  Until then we are in
48
 * NTP Epoch 0.  After that NTP timestamps will be in Epoch 1.  Negative
49
 * epochs can be used to represent time before Jan 1900.
50
 *
51
 * The epoch number is not explicit on the wire. It will seldom be an
52
 * issue: timestamp differences between two adjacent epochs are still
53
 * valid as long as the true time difference is less than half an
54
 * epoch.  In other words, you don't have to explicitly check for the
55
 * epoch of either timestamp if you assume that these are less than 68
56
 * years apart.
57
 */
58
typedef uint64_t l_fp;
59
0
#define lfpfrac(n)    ((uint32_t)(n))
60
0
#define lfptouint(n)          ((uint64_t)((uint64_t)(n) << 32))
61
0
#define lfpsint(n)    (( int32_t)((n) >> 32))
62
0
#define lfpuint(n)    ((uint32_t)((n) >> 32))
63
#define bumplfpsint(n, i)       ((n) += lfptouint(i))
64
0
#define bumplfpuint(n, i)       ((n) += lfptouint(i))
65
#define setlfpfrac(n, v)        ((n)  = (lfptouint(lfpuint(n)) | lfpfrac(v)))
66
#define setlfpuint(n, v)        ((n)  = (lfptouint(v) | lfpfrac(n)))
67
68
0
static inline l_fp lfpinit(int32_t sec, uint32_t frac) {
69
0
  l_fp tmp = lfptouint(sec) | lfpfrac(frac);
70
0
  return tmp;
71
0
}
Unexecuted instantiation: FuzzExtens.c:lfpinit
Unexecuted instantiation: nts_extens.c:lfpinit
Unexecuted instantiation: nts.c:lfpinit
Unexecuted instantiation: nts_server.c:lfpinit
Unexecuted instantiation: nts_client.c:lfpinit
Unexecuted instantiation: nts_cookie.c:lfpinit
Unexecuted instantiation: socktoa.c:lfpinit
Unexecuted instantiation: assert.c:lfpinit
Unexecuted instantiation: lib_strbuf.c:lfpinit
Unexecuted instantiation: msyslog.c:lfpinit
Unexecuted instantiation: ntp_random.c:lfpinit
Unexecuted instantiation: timespecops.c:lfpinit
Unexecuted instantiation: ntp_calendar.c:lfpinit
Unexecuted instantiation: setup.c:lfpinit
Unexecuted instantiation: FuzzServer.c:lfpinit
Unexecuted instantiation: FuzzClient.c:lfpinit
72
73
0
static inline l_fp lfpinit_u(uint32_t sec, uint32_t frac) {
74
0
  l_fp tmp = lfptouint(sec) | lfpfrac(frac);
75
0
  return tmp;
76
0
}
Unexecuted instantiation: FuzzExtens.c:lfpinit_u
Unexecuted instantiation: nts_extens.c:lfpinit_u
Unexecuted instantiation: nts.c:lfpinit_u
Unexecuted instantiation: nts_server.c:lfpinit_u
Unexecuted instantiation: nts_client.c:lfpinit_u
Unexecuted instantiation: nts_cookie.c:lfpinit_u
Unexecuted instantiation: socktoa.c:lfpinit_u
Unexecuted instantiation: assert.c:lfpinit_u
Unexecuted instantiation: lib_strbuf.c:lfpinit_u
Unexecuted instantiation: msyslog.c:lfpinit_u
Unexecuted instantiation: ntp_random.c:lfpinit_u
Unexecuted instantiation: timespecops.c:lfpinit_u
Unexecuted instantiation: ntp_calendar.c:lfpinit_u
Unexecuted instantiation: setup.c:lfpinit_u
Unexecuted instantiation: FuzzServer.c:lfpinit_u
Unexecuted instantiation: FuzzClient.c:lfpinit_u
77
78
/*
79
 * The second fixed point format is 32 bits, with the decimal between
80
 * bits 15 and 16.  There is a signed version (s_fp) and an unsigned
81
 * version (u_fp).  This is used to represent synchronizing distance
82
 * and synchronizing dispersion in the NTP packet header (again, in
83
 * network byte order) and internally to hold both distance and
84
 * dispersion values (in local byte order).  In network byte order
85
 * it looks like:
86
 *
87
 *    0                   1                   2                   3
88
 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
89
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90
 *   |      Integer Part       |     Fraction Part       |
91
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92
 *
93
 */
94
typedef uint32_t u_fp;
95
96
97
typedef struct {
98
         uint32_t        l_ui;
99
         uint32_t        l_uf;
100
} l_fp_w;
101
102
#define M_ISNEG(v_i)      /* v < 0 */ \
103
0
  (((v_i) & 0x80000000) != 0)
104
105
/*
106
 * Operations on the long fp format.  The only reason these aren't
107
 * native operations is to be independent of whether the l_fp
108
 * type is signed or unsigned.
109
 * Can l_fp ever be signed??
110
 */
111
0
#define L_NEG(v)  (v) = -(v)
112
0
#define L_ISNEG(v)  M_ISNEG(lfpuint(v))
113
#define L_ISGT(a, b)  ((int64_t)(a) > (int64_t)(b))
114
#define L_ISGTU(a, b) ((a) > (b))
115
116
/*
117
 * scaling to 32bit FP format
118
 * double to u_fp conversion
119
 */
120
#define FP_SCALE(r) (ldexp((double)(r),  16))
121
#define FP_UNSCALE(r) (ldexp((double)(r), -16))
122
#define DTOUFP(r) ((u_fp)FP_SCALE(r))
123
124
/*
125
 * l_fp/double conversions
126
 */
127
#define FRAC    4294967296.0    /* 2^32 as a double */
128
129
#include <math.h> /* ldexpl() */
130
131
0
static inline l_fp dtolfp(doubletime_t d) {
132
0
/* long double to l_fp
133
0
 * assumes signed l_fp, i.e. a time offset
134
0
 * undefined return if d in NaN
135
0
 */
136
0
  return (l_fp)(int64_t)(ldexpl(d, 32));
137
0
}
Unexecuted instantiation: FuzzExtens.c:dtolfp
Unexecuted instantiation: nts_extens.c:dtolfp
Unexecuted instantiation: nts.c:dtolfp
Unexecuted instantiation: nts_server.c:dtolfp
Unexecuted instantiation: nts_client.c:dtolfp
Unexecuted instantiation: nts_cookie.c:dtolfp
Unexecuted instantiation: socktoa.c:dtolfp
Unexecuted instantiation: assert.c:dtolfp
Unexecuted instantiation: lib_strbuf.c:dtolfp
Unexecuted instantiation: msyslog.c:dtolfp
Unexecuted instantiation: ntp_random.c:dtolfp
Unexecuted instantiation: timespecops.c:dtolfp
Unexecuted instantiation: ntp_calendar.c:dtolfp
Unexecuted instantiation: setup.c:dtolfp
Unexecuted instantiation: FuzzServer.c:dtolfp
Unexecuted instantiation: FuzzClient.c:dtolfp
138
139
0
static inline doubletime_t lfptod(l_fp r) {
140
0
/* l_fp to long double
141
0
 * assumes signed l_fp, i.e. a time offset
142
0
 */
143
0
  return ldexpl((double)((int64_t)r), -32);
144
0
}
Unexecuted instantiation: FuzzExtens.c:lfptod
Unexecuted instantiation: nts_extens.c:lfptod
Unexecuted instantiation: nts.c:lfptod
Unexecuted instantiation: nts_server.c:lfptod
Unexecuted instantiation: nts_client.c:lfptod
Unexecuted instantiation: nts_cookie.c:lfptod
Unexecuted instantiation: socktoa.c:lfptod
Unexecuted instantiation: assert.c:lfptod
Unexecuted instantiation: lib_strbuf.c:lfptod
Unexecuted instantiation: msyslog.c:lfptod
Unexecuted instantiation: ntp_random.c:lfptod
Unexecuted instantiation: timespecops.c:lfptod
Unexecuted instantiation: ntp_calendar.c:lfptod
Unexecuted instantiation: setup.c:lfptod
Unexecuted instantiation: FuzzServer.c:lfptod
Unexecuted instantiation: FuzzClient.c:lfptod
145
146
/*
147
 * Prototypes
148
 */
149
extern  char *  dolfptoa  (l_fp, bool, short, bool);
150
extern  char *  mfptoa    (l_fp, short);
151
extern  char *  mfptoms   (l_fp, short);
152
153
extern  bool  hextolfp  (const char *, l_fp *);
154
extern  char *  prettydate  (const l_fp);
155
extern  char *  rfc3339date (const l_fp);
156
extern  char *  rfc3339time     (time_t);
157
158
extern  void  get_systime (l_fp *);
159
extern  bool  step_systime  (doubletime_t);
160
extern  bool  adj_systime (double, int (*adjtime)(const struct timeval *, struct timeval *));
161
162
#define lfptoa(fpv, ndec) mfptoa((fpv), (ndec))
163
#define lfptoms(fpv, ndec)  mfptoms((fpv), (ndec))
164
165
#define ulfptoa(fpv, ndec)  dolfptoa((fpv), false, (ndec), false)
166
#define ulfptoms(fpv, ndec) dolfptoa((fpv), false, (ndec), true)
167
#define umfptoa(lfp, ndec)  dolfptoa((lfp), false, (ndec), false)
168
169
/*
170
 * Optional callback from libntp step_systime() to ntpd.  Optional
171
*  because other libntp clients like ntpdate don't use it.
172
 */
173
typedef void (*time_stepped_callback)(void);
174
extern time_stepped_callback  step_callback;
175
176
extern uint32_t convertLFPToRefID(l_fp num) __attribute__((const));
177
178
#endif /* GUARD_NTP_FP_H */