1 | /* |
---|
2 | * ntp_fp.h - definitions for NTP fixed point arithmetic |
---|
3 | */ |
---|
4 | |
---|
5 | #include <sys/types.h> |
---|
6 | #include <sys/socket.h> |
---|
7 | #include <netinet/in.h> |
---|
8 | |
---|
9 | #include "ntp_types.h" |
---|
10 | |
---|
11 | /* |
---|
12 | * NTP uses two fixed point formats. The first (l_fp) is the "long" format |
---|
13 | * and is 64 bits long with the decimal between bits 31 and 32. This |
---|
14 | * is used for time stamps in the NTP packet header (in network byte |
---|
15 | * order) and for internal computations of offsets (in local host byte |
---|
16 | * order). We use the same structure for both signed and unsigned values, |
---|
17 | * which is a big hack but saves rewriting all the operators twice. Just |
---|
18 | * to confuse this, we also sometimes just carry the fractional part in |
---|
19 | * calculations, in both signed and unsigned forms. Anyway, an l_fp looks |
---|
20 | * like: |
---|
21 | * |
---|
22 | * 0 1 2 3 |
---|
23 | * 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 |
---|
24 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
---|
25 | * | Integral Part | |
---|
26 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
---|
27 | * | Fractional Part | |
---|
28 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
---|
29 | * |
---|
30 | */ |
---|
31 | typedef struct { |
---|
32 | union { |
---|
33 | u_int32 Xl_ui; |
---|
34 | int32 Xl_i; |
---|
35 | } Ul_i; |
---|
36 | union { |
---|
37 | u_int32 Xl_uf; |
---|
38 | int32 Xl_f; |
---|
39 | } Ul_f; |
---|
40 | } l_fp; |
---|
41 | |
---|
42 | #define l_ui Ul_i.Xl_ui /* unsigned integral part */ |
---|
43 | #define l_i Ul_i.Xl_i /* signed integral part */ |
---|
44 | #define l_uf Ul_f.Xl_uf /* unsigned fractional part */ |
---|
45 | #define l_f Ul_f.Xl_f /* signed fractional part */ |
---|
46 | |
---|
47 | /* |
---|
48 | * Fractional precision (of an l_fp) is actually the number of |
---|
49 | * bits in a long. |
---|
50 | */ |
---|
51 | #define FRACTION_PREC (32) |
---|
52 | |
---|
53 | |
---|
54 | /* |
---|
55 | * The second fixed point format is 32 bits, with the decimal between |
---|
56 | * bits 15 and 16. There is a signed version (s_fp) and an unsigned |
---|
57 | * version (u_fp). This is used to represent synchronizing distance |
---|
58 | * and synchronizing dispersion in the NTP packet header (again, in |
---|
59 | * network byte order) and internally to hold both distance and |
---|
60 | * dispersion values (in local byte order). In network byte order |
---|
61 | * it looks like: |
---|
62 | * |
---|
63 | * 0 1 2 3 |
---|
64 | * 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 |
---|
65 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
---|
66 | * | Integer Part | Fraction Part | |
---|
67 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
---|
68 | * |
---|
69 | */ |
---|
70 | typedef int32 s_fp; |
---|
71 | typedef u_int32 u_fp; |
---|
72 | |
---|
73 | /* |
---|
74 | * A unit second in fp format. Actually 2**(half_the_bits_in_a_long) |
---|
75 | */ |
---|
76 | #define FP_SECOND (0x10000) |
---|
77 | |
---|
78 | /* |
---|
79 | * Byte order conversions |
---|
80 | */ |
---|
81 | #define HTONS_FP(x) (htonl(x)) |
---|
82 | #define HTONL_FP(h, n) do { (n)->l_ui = htonl((h)->l_ui); \ |
---|
83 | (n)->l_uf = htonl((h)->l_uf); } while (0) |
---|
84 | #define NTOHS_FP(x) (ntohl(x)) |
---|
85 | #define NTOHL_FP(n, h) do { (h)->l_ui = ntohl((n)->l_ui); \ |
---|
86 | (h)->l_uf = ntohl((n)->l_uf); } while (0) |
---|
87 | #define NTOHL_MFP(ni, nf, hi, hf) \ |
---|
88 | do { (hi) = ntohl(ni); (hf) = ntohl(nf); } while (0) |
---|
89 | #define HTONL_MFP(hi, hf, ni, nf) \ |
---|
90 | do { (ni) = ntohl(hi); (nf) = ntohl(hf); } while (0) |
---|
91 | |
---|
92 | /* funny ones. Converts ts fractions to net order ts */ |
---|
93 | #define HTONL_UF(uf, nts) \ |
---|
94 | do { (nts)->l_ui = 0; (nts)->l_uf = htonl(uf); } while (0) |
---|
95 | #define HTONL_F(f, nts) do { (nts)->l_uf = htonl(f); \ |
---|
96 | if ((f) & 0x80000000) \ |
---|
97 | (nts)->l_i = -1; \ |
---|
98 | else \ |
---|
99 | (nts)->l_i = 0; \ |
---|
100 | } while (0) |
---|
101 | |
---|
102 | /* |
---|
103 | * Conversions between the two fixed point types |
---|
104 | */ |
---|
105 | #define MFPTOFP(x_i, x_f) (((x_i) >= 0x00010000) ? 0x7fffffff : \ |
---|
106 | (((x_i) <= -0x00010000) ? 0x80000000 : \ |
---|
107 | (((x_i)<<16) | (((x_f)>>16)&0xffff)))) |
---|
108 | #define LFPTOFP(v) MFPTOFP((v)->l_i, (v)->l_f) |
---|
109 | |
---|
110 | #define UFPTOLFP(x, v) ((v)->l_ui = (u_fp)(x)>>16, (v)->l_uf = (x)<<16) |
---|
111 | #define FPTOLFP(x, v) (UFPTOLFP((x), (v)), (x) < 0 ? (v)->l_ui -= 0x10000 : 0) |
---|
112 | |
---|
113 | #define MAXLFP(v) ((v)->l_ui = 0x7fffffff, (v)->l_uf = 0xffffffff) |
---|
114 | #define MINLFP(v) ((v)->l_ui = 0x80000000, (v)->l_uf = 0) |
---|
115 | |
---|
116 | /* |
---|
117 | * Primitive operations on long fixed point values. If these are |
---|
118 | * reminiscent of assembler op codes it's only because some may |
---|
119 | * be replaced by inline assembler for particular machines someday. |
---|
120 | * These are the (kind of inefficient) run-anywhere versions. |
---|
121 | */ |
---|
122 | #define M_NEG(v_i, v_f) /* v = -v */ \ |
---|
123 | do { \ |
---|
124 | if ((v_f) == 0) \ |
---|
125 | (v_i) = -((s_fp)(v_i)); \ |
---|
126 | else { \ |
---|
127 | (v_f) = -((s_fp)(v_f)); \ |
---|
128 | (v_i) = ~(v_i); \ |
---|
129 | } \ |
---|
130 | } while(0) |
---|
131 | |
---|
132 | #define M_NEGM(r_i, r_f, a_i, a_f) /* r = -a */ \ |
---|
133 | do { \ |
---|
134 | if ((a_f) == 0) { \ |
---|
135 | (r_f) = 0; \ |
---|
136 | (r_i) = -(a_i); \ |
---|
137 | } else { \ |
---|
138 | (r_f) = -(a_f); \ |
---|
139 | (r_i) = ~(a_i); \ |
---|
140 | } \ |
---|
141 | } while(0) |
---|
142 | |
---|
143 | #define M_ADD(r_i, r_f, a_i, a_f) /* r += a */ \ |
---|
144 | do { \ |
---|
145 | register u_int32 lo_tmp; \ |
---|
146 | register u_int32 hi_tmp; \ |
---|
147 | \ |
---|
148 | lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \ |
---|
149 | hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \ |
---|
150 | if (lo_tmp & 0x10000) \ |
---|
151 | hi_tmp++; \ |
---|
152 | (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \ |
---|
153 | \ |
---|
154 | (r_i) += (a_i); \ |
---|
155 | if (hi_tmp & 0x10000) \ |
---|
156 | (r_i)++; \ |
---|
157 | } while (0) |
---|
158 | |
---|
159 | #define M_ADD3(r_ovr, r_i, r_f, a_ovr, a_i, a_f) /* r += a, three word */ \ |
---|
160 | do { \ |
---|
161 | register u_int32 lo_tmp; \ |
---|
162 | register u_int32 hi_tmp; \ |
---|
163 | \ |
---|
164 | lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \ |
---|
165 | hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \ |
---|
166 | if (lo_tmp & 0x10000) \ |
---|
167 | hi_tmp++; \ |
---|
168 | (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \ |
---|
169 | \ |
---|
170 | lo_tmp = ((r_i) & 0xffff) + ((a_i) & 0xffff); \ |
---|
171 | if (hi_tmp & 0x10000) \ |
---|
172 | lo_tmp++; \ |
---|
173 | hi_tmp = (((r_i) >> 16) & 0xffff) + (((a_i) >> 16) & 0xffff); \ |
---|
174 | if (lo_tmp & 0x10000) \ |
---|
175 | hi_tmp++; \ |
---|
176 | (r_i) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \ |
---|
177 | \ |
---|
178 | (r_ovr) += (a_ovr); \ |
---|
179 | if (hi_tmp & 0x10000) \ |
---|
180 | (r_ovr)++; \ |
---|
181 | } while (0) |
---|
182 | |
---|
183 | #define M_SUB(r_i, r_f, a_i, a_f) /* r -= a */ \ |
---|
184 | do { \ |
---|
185 | register u_int32 lo_tmp; \ |
---|
186 | register u_int32 hi_tmp; \ |
---|
187 | \ |
---|
188 | if ((a_f) == 0) { \ |
---|
189 | (r_i) -= (a_i); \ |
---|
190 | } else { \ |
---|
191 | lo_tmp = ((r_f) & 0xffff) + ((-((s_fp)(a_f))) & 0xffff); \ |
---|
192 | hi_tmp = (((r_f) >> 16) & 0xffff) \ |
---|
193 | + (((-((s_fp)(a_f))) >> 16) & 0xffff); \ |
---|
194 | if (lo_tmp & 0x10000) \ |
---|
195 | hi_tmp++; \ |
---|
196 | (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \ |
---|
197 | \ |
---|
198 | (r_i) += ~(a_i); \ |
---|
199 | if (hi_tmp & 0x10000) \ |
---|
200 | (r_i)++; \ |
---|
201 | } \ |
---|
202 | } while (0) |
---|
203 | |
---|
204 | #define M_RSHIFTU(v_i, v_f) /* v >>= 1, v is unsigned */ \ |
---|
205 | do { \ |
---|
206 | (v_f) = (u_int32)(v_f) >> 1; \ |
---|
207 | if ((v_i) & 01) \ |
---|
208 | (v_f) |= 0x80000000; \ |
---|
209 | (v_i) = (u_int32)(v_i) >> 1; \ |
---|
210 | } while (0) |
---|
211 | |
---|
212 | #define M_RSHIFT(v_i, v_f) /* v >>= 1, v is signed */ \ |
---|
213 | do { \ |
---|
214 | (v_f) = (u_int32)(v_f) >> 1; \ |
---|
215 | if ((v_i) & 01) \ |
---|
216 | (v_f) |= 0x80000000; \ |
---|
217 | if ((v_i) & 0x80000000) \ |
---|
218 | (v_i) = ((v_i) >> 1) | 0x80000000; \ |
---|
219 | else \ |
---|
220 | (v_i) = (v_i) >> 1; \ |
---|
221 | } while (0) |
---|
222 | |
---|
223 | #define M_LSHIFT(v_i, v_f) /* v <<= 1 */ \ |
---|
224 | do { \ |
---|
225 | (v_i) <<= 1; \ |
---|
226 | if ((v_f) & 0x80000000) \ |
---|
227 | (v_i) |= 0x1; \ |
---|
228 | (v_f) <<= 1; \ |
---|
229 | } while (0) |
---|
230 | |
---|
231 | #define M_LSHIFT3(v_ovr, v_i, v_f) /* v <<= 1, with overflow */ \ |
---|
232 | do { \ |
---|
233 | (v_ovr) <<= 1; \ |
---|
234 | if ((v_i) & 0x80000000) \ |
---|
235 | (v_ovr) |= 0x1; \ |
---|
236 | (v_i) <<= 1; \ |
---|
237 | if ((v_f) & 0x80000000) \ |
---|
238 | (v_i) |= 0x1; \ |
---|
239 | (v_f) <<= 1; \ |
---|
240 | } while (0) |
---|
241 | |
---|
242 | #define M_ADDUF(r_i, r_f, uf) /* r += uf, uf is u_int32 fraction */ \ |
---|
243 | M_ADD((r_i), (r_f), 0, (uf)) /* let optimizer worry about it */ |
---|
244 | |
---|
245 | #define M_SUBUF(r_i, r_f, uf) /* r -= uf, uf is u_int32 fraction */ \ |
---|
246 | M_SUB((r_i), (r_f), 0, (uf)) /* let optimizer worry about it */ |
---|
247 | |
---|
248 | #define M_ADDF(r_i, r_f, f) /* r += f, f is a int32 fraction */ \ |
---|
249 | do { \ |
---|
250 | if ((f) > 0) \ |
---|
251 | M_ADD((r_i), (r_f), 0, (f)); \ |
---|
252 | else if ((f) < 0) \ |
---|
253 | M_ADD((r_i), (r_f), (-1), (f));\ |
---|
254 | } while(0) |
---|
255 | |
---|
256 | #define M_ISNEG(v_i, v_f) /* v < 0 */ \ |
---|
257 | (((v_i) & 0x80000000) != 0) |
---|
258 | |
---|
259 | #define M_ISHIS(a_i, a_f, b_i, b_f) /* a >= b unsigned */ \ |
---|
260 | (((u_int32)(a_i)) > ((u_int32)(b_i)) || \ |
---|
261 | ((a_i) == (b_i) && ((u_int32)(a_f)) >= ((u_int32)(b_f)))) |
---|
262 | |
---|
263 | #define M_ISGEQ(a_i, a_f, b_i, b_f) /* a >= b signed */ \ |
---|
264 | (((int32)(a_i)) > ((int32)(b_i)) || \ |
---|
265 | ((a_i) == (b_i) && ((u_int32)(a_f)) >= ((u_int32)(b_f)))) |
---|
266 | |
---|
267 | #define M_ISEQU(a_i, a_f, b_i, b_f) /* a == b unsigned */ \ |
---|
268 | ((a_i) == (b_i) && (a_f) == (b_f)) |
---|
269 | |
---|
270 | /* |
---|
271 | * Operations on the long fp format |
---|
272 | */ |
---|
273 | #define L_ADD(r, a) M_ADD((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf) |
---|
274 | #define L_SUB(r, a) M_SUB((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf) |
---|
275 | #define L_NEG(v) M_NEG((v)->l_ui, (v)->l_uf) |
---|
276 | #define L_ADDUF(r, uf) M_ADDUF((r)->l_ui, (r)->l_uf, (uf)) |
---|
277 | #define L_SUBUF(r, uf) M_SUBUF((r)->l_ui, (r)->l_uf, (uf)) |
---|
278 | #define L_ADDF(r, f) M_ADDF((r)->l_ui, (r)->l_uf, (f)) |
---|
279 | #define L_RSHIFT(v) M_RSHIFT((v)->l_i, (v)->l_uf) |
---|
280 | #define L_RSHIFTU(v) M_RSHIFT((v)->l_ui, (v)->l_uf) |
---|
281 | #define L_LSHIFT(v) M_LSHIFT((v)->l_ui, (v)->l_uf) |
---|
282 | #define L_CLR(v) ((v)->l_ui = (v)->l_uf = 0) |
---|
283 | |
---|
284 | #define L_ISNEG(v) (((v)->l_ui & 0x80000000) != 0) |
---|
285 | #define L_ISZERO(v) ((v)->l_ui == 0 && (v)->l_uf == 0) |
---|
286 | #define L_ISHIS(a, b) ((a)->l_ui > (b)->l_ui || \ |
---|
287 | ((a)->l_ui == (b)->l_ui && (a)->l_uf >= (b)->l_uf)) |
---|
288 | #define L_ISGEQ(a, b) ((a)->l_i > (b)->l_i || \ |
---|
289 | ((a)->l_i == (b)->l_i && (a)->l_uf >= (b)->l_uf)) |
---|
290 | #define L_ISEQU(a, b) M_ISEQU((a)->l_ui, (a)->l_uf, (b)->l_ui, (b)->l_uf) |
---|
291 | |
---|
292 | extern char * dofptoa P((u_fp, int, int, int)); |
---|
293 | extern char * dolfptoa P((u_long, u_long, int, int, int)); |
---|
294 | |
---|
295 | extern int atolfp P((const char *, l_fp *)); |
---|
296 | extern int buftvtots P((const char *, l_fp *)); |
---|
297 | extern char * fptoa P((s_fp, int)); |
---|
298 | extern char * fptoms P((s_fp, int)); |
---|
299 | extern char * fptoms P((s_fp, int)); |
---|
300 | extern int hextolfp P((const char *, l_fp *)); |
---|
301 | extern int mstolfp P((const char *, l_fp *)); |
---|
302 | extern char * prettydate P((l_fp *)); |
---|
303 | extern char * uglydate P((l_fp *)); |
---|
304 | |
---|
305 | extern void get_systime P((l_fp *)); |
---|
306 | extern int step_systime P((l_fp *)); |
---|
307 | extern int step_systime_real P((l_fp *)); |
---|
308 | extern int adj_systime P((l_fp *)); |
---|
309 | |
---|
310 | #define lfptoa(_fpv, _ndec) mfptoa((_fpv)->l_ui, (_fpv)->l_uf, (_ndec)) |
---|
311 | #define lfptoms(_fpv, _ndec) mfptoms((_fpv)->l_ui, (_fpv)->l_uf, (_ndec)) |
---|
312 | |
---|
313 | #define ntoa(_sin) numtoa((_sin)->sin_addr.s_addr) |
---|
314 | #define ntohost(_sin) numtohost((_sin)->sin_addr.s_addr) |
---|
315 | |
---|
316 | #define ufptoa(_fpv, _ndec) dofptoa((_fpv), 0, (_ndec), 0) |
---|
317 | #define ufptoms(_fpv, _ndec) dofptoa((_fpv), 0, (_ndec), 1) |
---|
318 | #define ulfptoa(_fpv, _ndec) dolfptoa((_fpv)->l_ui, (_fpv)->l_uf, 0, (_ndec), 0) |
---|
319 | #define ulfptoms(_fpv, _ndec) dolfptoa((_fpv)->l_ui, (_fpv)->l_uf, 0, (_ndec), 1) |
---|
320 | #define umfptoa(_fpi, _fpf, _ndec) dolfptoa((_fpi), (_fpf), 0, (_ndec), 0) |
---|