]>
Commit | Line | Data |
---|---|---|
88840341 | 1 | /* |
88840341 RC |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. |
3 | ||
4 | ********************************************************************** | |
6672f045 | 5 | * Copyright (C) Richard P. Curnow 1997-2003 |
3916c336 | 6 | * Copyright (C) Miroslav Lichvar 2009-2020 |
88840341 RC |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of version 2 of the GNU General Public License as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
8e23110a | 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
88840341 RC |
20 | * |
21 | ********************************************************************** | |
22 | ||
23 | ======================================================================= | |
24 | ||
25 | Core NTP protocol engine | |
26 | */ | |
27 | ||
da2c8d90 ML |
28 | #include "config.h" |
29 | ||
88840341 RC |
30 | #include "sysincl.h" |
31 | ||
a78bf0c3 | 32 | #include "array.h" |
ca28dbd2 | 33 | #include "ntp_auth.h" |
88840341 RC |
34 | #include "ntp_core.h" |
35 | #include "ntp_io.h" | |
36 | #include "memory.h" | |
37 | #include "sched.h" | |
38 | #include "reference.h" | |
39 | #include "local.h" | |
189aafde | 40 | #include "samplefilt.h" |
7f45eb79 | 41 | #include "smooth.h" |
88840341 RC |
42 | #include "sources.h" |
43 | #include "util.h" | |
44 | #include "conf.h" | |
45 | #include "logging.h" | |
88840341 | 46 | #include "addrfilt.h" |
88840341 RC |
47 | #include "clientlog.h" |
48 | ||
49 | /* ================================================== */ | |
88840341 | 50 | |
e78e65ef | 51 | static LOG_FileID logfileid; |
0a0aff14 | 52 | static int log_raw_measurements; |
88840341 | 53 | |
88840341 RC |
54 | /* ================================================== */ |
55 | /* Enumeration used for remembering the operating mode of one of the | |
56 | sources */ | |
57 | ||
58 | typedef enum { | |
59 | MD_OFFLINE, /* No sampling at all */ | |
60 | MD_ONLINE, /* Normal sampling based on sampling interval */ | |
61 | MD_BURST_WAS_OFFLINE, /* Burst sampling, return to offline afterwards */ | |
62 | MD_BURST_WAS_ONLINE, /* Burst sampling, return to online afterwards */ | |
63 | } OperatingMode; | |
64 | ||
65 | /* ================================================== */ | |
66 | /* Structure used for holding a single peer/server's | |
67 | protocol machine */ | |
68 | ||
69 | struct NCR_Instance_Record { | |
70 | NTP_Remote_Address remote_addr; /* Needed for routing transmit packets */ | |
9a657cd4 | 71 | NTP_Local_Address local_addr; /* Local address/socket used to send packets */ |
88840341 RC |
72 | NTP_Mode mode; /* The source's NTP mode |
73 | (client/server or symmetric active peer) */ | |
90b25f5b | 74 | int interleaved; /* Boolean enabling interleaved NTP mode */ |
88840341 RC |
75 | OperatingMode opmode; /* Whether we are sampling this source |
76 | or not and in what way */ | |
cbd77c97 ML |
77 | SCH_TimeoutID rx_timeout_id; /* Timeout ID for latest received response */ |
78 | SCH_TimeoutID tx_timeout_id; /* Timeout ID for next transmission */ | |
779e40ed | 79 | int tx_suspended; /* Boolean indicating we can't transmit yet */ |
88840341 | 80 | |
b0fe4436 | 81 | int auto_iburst; /* If 1, initiate a burst when going online */ |
d0eb9427 | 82 | int auto_burst; /* If 1, initiate a burst on each poll */ |
7637faa0 ML |
83 | int auto_offline; /* If 1, automatically go offline when requests |
84 | cannot be sent */ | |
88840341 RC |
85 | |
86 | int local_poll; /* Log2 of polling interval at our end */ | |
87 | int remote_poll; /* Log2 of server/peer's polling interval (recovered | |
88 | from received packets) */ | |
cce7a5f1 ML |
89 | int remote_stratum; /* Stratum of the server/peer (recovered from |
90 | received packets) */ | |
88840341 RC |
91 | |
92 | int presend_minpoll; /* If the current polling interval is | |
cd5105b1 ML |
93 | at least this, an extra client packet |
94 | will be send some time before normal | |
88840341 RC |
95 | transmit. This ensures that both |
96 | us and the server/peer have an ARP | |
97 | entry for each other ready, which | |
98 | means our measurement is not | |
99 | botched by an ARP round-trip on one | |
100 | side or the other. */ | |
101 | ||
102 | int presend_done; /* The presend packet has been sent */ | |
103 | ||
104 | int minpoll; /* Log2 of minimum defined polling interval */ | |
105 | int maxpoll; /* Log2 of maximum defined polling interval */ | |
106 | ||
c8fe69c9 BLA |
107 | int min_stratum; /* Increase stratum in received packets to the |
108 | minimum */ | |
109 | ||
7a6ee1d7 ML |
110 | int poll_target; /* Target number of sourcestats samples */ |
111 | ||
1aecc51c ML |
112 | int version; /* Version set in packets for server/peer */ |
113 | ||
7a6ee1d7 ML |
114 | double poll_score; /* Score of current local poll */ |
115 | ||
88840341 RC |
116 | double max_delay; /* Maximum round-trip delay to the |
117 | peer that we can tolerate and still | |
118 | use the sample for generating | |
119 | statistics from */ | |
120 | ||
8fbfe55e | 121 | double max_delay_ratio; /* Largest ratio of delay / |
88840341 RC |
122 | min_delay_in_register that we can |
123 | tolerate. */ | |
124 | ||
b977c95b ML |
125 | double max_delay_dev_ratio; /* Maximum ratio of increase in delay / stddev */ |
126 | ||
6cd55839 ML |
127 | double offset_correction; /* Correction applied to measured offset |
128 | (e.g. for asymmetry in network delay) */ | |
129 | ||
ca28dbd2 | 130 | NAU_Instance auth; /* Authentication */ |
88840341 | 131 | |
30e65496 ML |
132 | /* Count of transmitted packets since last valid response */ |
133 | unsigned int tx_count; | |
88840341 | 134 | |
90b25f5b ML |
135 | /* Flag indicating a valid response was received since last request */ |
136 | int valid_rx; | |
137 | ||
138 | /* Flag indicating the timestamps below are from a valid packet and may | |
139 | be used for synchronisation */ | |
140 | int valid_timestamps; | |
141 | ||
f0f18a02 | 142 | /* Receive and transmit timestamps from the last valid response */ |
90b25f5b ML |
143 | NTP_int64 remote_ntp_rx; |
144 | NTP_int64 remote_ntp_tx; | |
88840341 | 145 | |
f0f18a02 | 146 | /* Local timestamp when the last valid response was received from the |
88840341 RC |
147 | source. We have to be prepared to tinker with this if the local |
148 | clock has its frequency adjusted before we repond. The value we | |
149 | store here is what our own local time was when the same arrived. | |
150 | Before replying, we have to correct this to fit with the | |
151 | parameters for the current reference. (It must be stored | |
152 | relative to local time to permit frequency and offset adjustments | |
153 | to be made when we trim the local clock). */ | |
90b25f5b | 154 | NTP_int64 local_ntp_rx; |
14c8f076 | 155 | NTP_Local_Timestamp local_rx; |
88840341 RC |
156 | |
157 | /* Local timestamp when we last transmitted a packet to the source. | |
158 | We store two versions. The first is in NTP format, and is used | |
159 | to validate the next received packet from the source. | |
160 | Additionally, this is corrected to bring it into line with the | |
d0dfa1de | 161 | current reference. The second is in timespec format, and is kept |
88840341 RC |
162 | relative to the local clock. We modify this in accordance with |
163 | local clock frequency/offset changes, and use this for computing | |
164 | statistics about the source when a return packet arrives. */ | |
165 | NTP_int64 local_ntp_tx; | |
14c8f076 | 166 | NTP_Local_Timestamp local_tx; |
88840341 | 167 | |
2668a12e | 168 | /* Previous values of some variables needed in interleaved mode */ |
2e0870ee | 169 | NTP_Local_Timestamp prev_local_tx; |
2668a12e | 170 | int prev_local_poll; |
64c2fd98 | 171 | unsigned int prev_tx_count; |
2e0870ee | 172 | |
f0f18a02 ML |
173 | /* Flag indicating the two timestamps below were updated since the |
174 | last transmission */ | |
175 | int updated_init_timestamps; | |
176 | ||
177 | /* Timestamps used for (re)starting the symmetric protocol, when we | |
178 | need to respond to a packet which is not a valid response */ | |
179 | NTP_int64 init_remote_ntp_tx; | |
180 | NTP_Local_Timestamp init_local_rx; | |
181 | ||
88840341 RC |
182 | /* The instance record in the main source management module. This |
183 | performs the statistical analysis on the samples we generate */ | |
184 | ||
185 | SRC_Instance source; | |
186 | ||
189aafde ML |
187 | /* Optional median filter for NTP measurements */ |
188 | SPF_Instance filter; | |
189 | ||
88840341 RC |
190 | int burst_good_samples_to_go; |
191 | int burst_total_samples_to_go; | |
192 | ||
535ca64b ML |
193 | /* Report from last valid response */ |
194 | RPT_NTPReport report; | |
88840341 RC |
195 | }; |
196 | ||
a78bf0c3 ML |
197 | typedef struct { |
198 | NTP_Remote_Address addr; | |
199 | NTP_Local_Address local_addr; | |
ca28dbd2 | 200 | NAU_Instance auth; |
a78bf0c3 ML |
201 | int interval; |
202 | } BroadcastDestination; | |
203 | ||
204 | /* Array of BroadcastDestination */ | |
205 | static ARR_Instance broadcasts; | |
206 | ||
88840341 RC |
207 | /* ================================================== */ |
208 | /* Initial delay period before first packet is transmitted (in seconds) */ | |
d1b820e7 | 209 | #define INITIAL_DELAY 0.2 |
88840341 RC |
210 | |
211 | /* Spacing required between samples for any two servers/peers (to | |
212 | minimise risk of network collisions) (in seconds) */ | |
dcce79fd | 213 | #define MIN_SAMPLING_SEPARATION 0.002 |
97d42033 | 214 | #define MAX_SAMPLING_SEPARATION 0.2 |
d1b820e7 | 215 | |
833022b7 ML |
216 | /* Randomness added to spacing between samples for one server/peer */ |
217 | #define SAMPLING_RANDOMNESS 0.02 | |
218 | ||
cce7a5f1 | 219 | /* Adjustment of the peer polling interval */ |
992590e9 | 220 | #define PEER_SAMPLING_ADJ 1.1 |
cce7a5f1 | 221 | |
5b75d4af ML |
222 | /* Maximum spacing between samples in the burst mode as an absolute |
223 | value and ratio to the normal polling interval */ | |
224 | #define MAX_BURST_INTERVAL 2.0 | |
225 | #define MAX_BURST_POLL_RATIO 0.25 | |
88840341 | 226 | |
70928dba ML |
227 | /* Number of samples in initial burst */ |
228 | #define IBURST_GOOD_SAMPLES 4 | |
229 | #define IBURST_TOTAL_SAMPLES SOURCE_REACH_BITS | |
230 | ||
d0eb9427 ML |
231 | /* Number of samples in automatic burst */ |
232 | #define BURST_GOOD_SAMPLES 1 | |
233 | #define MAX_BURST_TOTAL_SAMPLES 4 | |
234 | ||
cd5105b1 | 235 | /* Time to wait after sending packet to 'warm up' link */ |
d23c647e | 236 | #define WARM_UP_DELAY 2.0 |
d1b820e7 | 237 | |
8cc7ebff | 238 | /* Compatible NTP protocol versions */ |
8fbfe55e | 239 | #define NTP_MAX_COMPAT_VERSION NTP_VERSION |
cf001799 | 240 | #define NTP_MIN_COMPAT_VERSION 1 |
8cc7ebff | 241 | |
8fbfe55e | 242 | /* Maximum allowed dispersion - as defined in RFC 5905 (16 seconds) */ |
88840341 RC |
243 | #define NTP_MAX_DISPERSION 16.0 |
244 | ||
df9b5d8c ML |
245 | /* Maximum allowed time for server to process client packet */ |
246 | #define MAX_SERVER_INTERVAL 4.0 | |
247 | ||
8f6a1b53 ML |
248 | /* Maximum acceptable delay in transmission for timestamp correction */ |
249 | #define MAX_TX_DELAY 1.0 | |
250 | ||
f2f834e7 | 251 | /* Maximum allowed values of maxdelay parameters */ |
99147ed8 ML |
252 | #define MAX_MAXDELAY 1.0e3 |
253 | #define MAX_MAXDELAYRATIO 1.0e6 | |
254 | #define MAX_MAXDELAYDEVRATIO 1.0e6 | |
f2f834e7 | 255 | |
a79fbef2 | 256 | /* Minimum and maximum allowed poll interval */ |
dcce79fd | 257 | #define MIN_POLL -6 |
a79fbef2 | 258 | #define MAX_POLL 24 |
0380cf0c | 259 | |
59d1b417 ML |
260 | /* Enable sub-second polling intervals only when the peer delay is not |
261 | longer than 10 milliseconds to restrict them to local networks */ | |
262 | #define MIN_NONLAN_POLL 0 | |
263 | #define MAX_LAN_PEER_DELAY 0.01 | |
264 | ||
8fbfe55e ML |
265 | /* Kiss-o'-Death codes */ |
266 | #define KOD_RATE 0x52415445UL /* RATE */ | |
267 | ||
7aa4bbf6 ML |
268 | /* Maximum poll interval set by KoD RATE */ |
269 | #define MAX_KOD_RATE_POLL SRC_DEFAULT_MAXPOLL | |
270 | ||
16afa8eb ML |
271 | /* Maximum number of missed responses to accept samples using old timestamps |
272 | in the interleaved client/server mode */ | |
273 | #define MAX_CLIENT_INTERLEAVED_TX 4 | |
274 | ||
0baa35ea ML |
275 | /* Maximum ratio of local intervals in the timestamp selection of the |
276 | interleaved mode to prefer a sample using previous timestamps */ | |
277 | #define MAX_INTERLEAVED_L2L_RATIO 0.1 | |
278 | ||
547272e6 ML |
279 | /* Invalid socket, different from the one in ntp_io.c */ |
280 | #define INVALID_SOCK_FD -2 | |
779e40ed | 281 | |
88840341 RC |
282 | /* ================================================== */ |
283 | ||
5214d42c ML |
284 | /* Server IPv4/IPv6 sockets */ |
285 | static int server_sock_fd4; | |
286 | static int server_sock_fd6; | |
287 | ||
88840341 RC |
288 | static ADF_AuthTable access_auth_table; |
289 | ||
2c877fa1 ML |
290 | /* Characters for printing synchronisation status and timestamping source */ |
291 | static const char leap_chars[4] = {'N', '+', '-', '?'}; | |
292 | static const char tss_chars[3] = {'D', 'K', 'H'}; | |
293 | ||
88840341 RC |
294 | /* ================================================== */ |
295 | /* Forward prototypes */ | |
296 | ||
297 | static void transmit_timeout(void *arg); | |
badf97d4 | 298 | static double get_transmit_delay(NCR_Instance inst, int on_tx, double last_tx); |
97d42033 | 299 | static double get_separation(int poll); |
cb8660e7 | 300 | static int parse_packet(NTP_Packet *packet, int length, NTP_PacketInfo *info); |
b0fe4436 | 301 | static void set_connectivity(NCR_Instance inst, SRC_Connectivity connectivity); |
88840341 RC |
302 | |
303 | /* ================================================== */ | |
304 | ||
cb88cea3 ML |
305 | static void |
306 | do_size_checks(void) | |
307 | { | |
308 | /* Assertions to check the sizes of certain data types | |
309 | and the positions of certain record fields */ | |
310 | ||
311 | /* Check that certain invariants are true */ | |
312 | assert(sizeof(NTP_int32) == 4); | |
313 | assert(sizeof(NTP_int64) == 8); | |
314 | ||
315 | /* Check offsets of all fields in the NTP packet format */ | |
316 | assert(offsetof(NTP_Packet, lvm) == 0); | |
317 | assert(offsetof(NTP_Packet, stratum) == 1); | |
318 | assert(offsetof(NTP_Packet, poll) == 2); | |
319 | assert(offsetof(NTP_Packet, precision) == 3); | |
320 | assert(offsetof(NTP_Packet, root_delay) == 4); | |
321 | assert(offsetof(NTP_Packet, root_dispersion) == 8); | |
322 | assert(offsetof(NTP_Packet, reference_id) == 12); | |
323 | assert(offsetof(NTP_Packet, reference_ts) == 16); | |
324 | assert(offsetof(NTP_Packet, originate_ts) == 24); | |
325 | assert(offsetof(NTP_Packet, receive_ts) == 32); | |
326 | assert(offsetof(NTP_Packet, transmit_ts) == 40); | |
327 | } | |
328 | ||
329 | /* ================================================== */ | |
330 | ||
474b2af1 ML |
331 | static void |
332 | do_time_checks(void) | |
333 | { | |
d0dfa1de | 334 | struct timespec now; |
e1accce4 ML |
335 | time_t warning_advance = 3600 * 24 * 365 * 10; /* 10 years */ |
336 | ||
474b2af1 ML |
337 | #ifdef HAVE_LONG_TIME_T |
338 | /* Check that time before NTP_ERA_SPLIT underflows correctly */ | |
339 | ||
d0dfa1de ML |
340 | struct timespec ts1 = {NTP_ERA_SPLIT, 1}, ts2 = {NTP_ERA_SPLIT - 1, 1}; |
341 | NTP_int64 nts1, nts2; | |
474b2af1 ML |
342 | int r; |
343 | ||
99cc9452 ML |
344 | UTI_TimespecToNtp64(&ts1, &nts1, NULL); |
345 | UTI_TimespecToNtp64(&ts2, &nts2, NULL); | |
346 | UTI_Ntp64ToTimespec(&nts1, &ts1); | |
347 | UTI_Ntp64ToTimespec(&nts2, &ts2); | |
474b2af1 | 348 | |
d0dfa1de ML |
349 | r = ts1.tv_sec == NTP_ERA_SPLIT && |
350 | ts1.tv_sec + (1ULL << 32) - 1 == ts2.tv_sec; | |
474b2af1 ML |
351 | |
352 | assert(r); | |
e1accce4 ML |
353 | |
354 | LCL_ReadRawTime(&now); | |
d0dfa1de | 355 | if (ts2.tv_sec - now.tv_sec < warning_advance) |
f282856c | 356 | LOG(LOGS_WARN, "Assumed NTP time ends at %s!", UTI_TimeToLogForm(ts2.tv_sec)); |
e1accce4 ML |
357 | #else |
358 | LCL_ReadRawTime(&now); | |
359 | if (now.tv_sec > 0x7fffffff - warning_advance) | |
f282856c | 360 | LOG(LOGS_WARN, "System time ends at %s!", UTI_TimeToLogForm(0x7fffffff)); |
474b2af1 ML |
361 | #endif |
362 | } | |
363 | ||
364 | /* ================================================== */ | |
365 | ||
43cd119d ML |
366 | static void |
367 | zero_local_timestamp(NTP_Local_Timestamp *ts) | |
368 | { | |
369 | UTI_ZeroTimespec(&ts->ts); | |
370 | ts->err = 0.0; | |
371 | ts->source = NTP_TS_DAEMON; | |
372 | } | |
373 | ||
374 | /* ================================================== */ | |
375 | ||
88840341 RC |
376 | void |
377 | NCR_Initialise(void) | |
378 | { | |
cb88cea3 | 379 | do_size_checks(); |
474b2af1 | 380 | do_time_checks(); |
cb88cea3 | 381 | |
0a0aff14 | 382 | logfileid = CNF_GetLogMeasurements(&log_raw_measurements) ? LOG_FileOpen("measurements", |
2c877fa1 | 383 | " Date (UTC) Time IP Address L St 123 567 ABCD LP RP Score Offset Peer del. Peer disp. Root del. Root disp. Refid MTxRx") |
e78e65ef | 384 | : -1; |
88840341 RC |
385 | |
386 | access_auth_table = ADF_CreateTable(); | |
a78bf0c3 | 387 | broadcasts = ARR_CreateInstance(sizeof (BroadcastDestination)); |
5214d42c | 388 | |
52e12e42 ML |
389 | /* Server socket will be opened when access is allowed */ |
390 | server_sock_fd4 = INVALID_SOCK_FD; | |
391 | server_sock_fd6 = INVALID_SOCK_FD; | |
88840341 RC |
392 | } |
393 | ||
394 | /* ================================================== */ | |
395 | ||
396 | void | |
397 | NCR_Finalise(void) | |
398 | { | |
5214d42c ML |
399 | unsigned int i; |
400 | ||
401 | if (server_sock_fd4 != INVALID_SOCK_FD) | |
402 | NIO_CloseServerSocket(server_sock_fd4); | |
403 | if (server_sock_fd6 != INVALID_SOCK_FD) | |
404 | NIO_CloseServerSocket(server_sock_fd6); | |
405 | ||
ca28dbd2 | 406 | for (i = 0; i < ARR_GetSize(broadcasts); i++) { |
5214d42c | 407 | NIO_CloseServerSocket(((BroadcastDestination *)ARR_GetElement(broadcasts, i))->local_addr.sock_fd); |
ca28dbd2 ML |
408 | NAU_DestroyInstance(((BroadcastDestination *)ARR_GetElement(broadcasts, i))->auth); |
409 | } | |
5214d42c | 410 | |
a78bf0c3 | 411 | ARR_DestroyInstance(broadcasts); |
88840341 | 412 | ADF_DestroyTable(access_auth_table); |
88840341 RC |
413 | } |
414 | ||
415 | /* ================================================== */ | |
416 | ||
417 | static void | |
ba283e6b | 418 | restart_timeout(NCR_Instance inst, double delay) |
88840341 | 419 | { |
779e40ed ML |
420 | /* Check if we can transmit */ |
421 | if (inst->tx_suspended) { | |
cbd77c97 | 422 | assert(!inst->tx_timeout_id); |
779e40ed ML |
423 | return; |
424 | } | |
425 | ||
cbd77c97 ML |
426 | /* Stop both rx and tx timers if running */ |
427 | SCH_RemoveTimeout(inst->rx_timeout_id); | |
428 | inst->rx_timeout_id = 0; | |
429 | SCH_RemoveTimeout(inst->tx_timeout_id); | |
88840341 | 430 | |
779e40ed | 431 | /* Start new timer for transmission */ |
97d42033 | 432 | inst->tx_timeout_id = SCH_AddTimeoutInClass(delay, get_separation(inst->local_poll), |
cbd77c97 | 433 | SAMPLING_RANDOMNESS, |
1c51feb3 ML |
434 | inst->mode == MODE_CLIENT ? |
435 | SCH_NtpClientClass : SCH_NtpPeerClass, | |
cbd77c97 | 436 | transmit_timeout, (void *)inst); |
ba283e6b ML |
437 | } |
438 | ||
439 | /* ================================================== */ | |
8671002b | 440 | |
ba283e6b ML |
441 | static void |
442 | start_initial_timeout(NCR_Instance inst) | |
443 | { | |
045794df | 444 | double delay, last_tx; |
d0dfa1de | 445 | struct timespec now; |
045794df | 446 | |
cbd77c97 | 447 | if (!inst->tx_timeout_id) { |
779e40ed ML |
448 | /* This will be the first transmission after mode change */ |
449 | ||
779e40ed ML |
450 | /* Mark source active */ |
451 | SRC_SetActive(inst->source); | |
a9b9e7be | 452 | } |
ba283e6b | 453 | |
045794df ML |
454 | /* In case the offline period was too short, adjust the delay to keep |
455 | the interval between packets at least as long as the current polling | |
456 | interval */ | |
457 | SCH_GetLastEventTime(&now, NULL, NULL); | |
14c8f076 | 458 | last_tx = UTI_DiffTimespecsToDouble(&now, &inst->local_tx.ts); |
045794df ML |
459 | if (last_tx < 0.0) |
460 | last_tx = 0.0; | |
461 | delay = get_transmit_delay(inst, 0, 0.0) - last_tx; | |
462 | if (delay < INITIAL_DELAY) | |
463 | delay = INITIAL_DELAY; | |
464 | ||
465 | restart_timeout(inst, delay); | |
a9b9e7be | 466 | } |
08faca03 | 467 | |
a9b9e7be ML |
468 | /* ================================================== */ |
469 | ||
470 | static void | |
471 | close_client_socket(NCR_Instance inst) | |
472 | { | |
473 | if (inst->mode == MODE_CLIENT && inst->local_addr.sock_fd != INVALID_SOCK_FD) { | |
474 | NIO_CloseClientSocket(inst->local_addr.sock_fd); | |
475 | inst->local_addr.sock_fd = INVALID_SOCK_FD; | |
779e40ed | 476 | } |
cbd77c97 ML |
477 | |
478 | SCH_RemoveTimeout(inst->rx_timeout_id); | |
479 | inst->rx_timeout_id = 0; | |
88840341 RC |
480 | } |
481 | ||
482 | /* ================================================== */ | |
483 | ||
60a25f6e ML |
484 | static void |
485 | take_offline(NCR_Instance inst) | |
486 | { | |
487 | inst->opmode = MD_OFFLINE; | |
0076458e | 488 | |
cbd77c97 ML |
489 | SCH_RemoveTimeout(inst->tx_timeout_id); |
490 | inst->tx_timeout_id = 0; | |
60a25f6e ML |
491 | |
492 | /* Mark source unreachable */ | |
493 | SRC_ResetReachability(inst->source); | |
8671002b ML |
494 | |
495 | /* And inactive */ | |
496 | SRC_UnsetActive(inst->source); | |
08faca03 | 497 | |
a9b9e7be | 498 | close_client_socket(inst); |
3ebebac6 ML |
499 | |
500 | NCR_ResetInstance(inst); | |
60a25f6e ML |
501 | } |
502 | ||
503 | /* ================================================== */ | |
504 | ||
2458325c | 505 | NCR_Instance |
fa402a17 ML |
506 | NCR_CreateInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, |
507 | SourceParameters *params, const char *name) | |
88840341 RC |
508 | { |
509 | NCR_Instance result; | |
510 | ||
511 | result = MallocNew(struct NCR_Instance_Record); | |
512 | ||
513 | result->remote_addr = *remote_addr; | |
308de812 | 514 | result->local_addr.ip_addr.family = IPADDR_UNSPEC; |
86acea5c | 515 | result->local_addr.if_index = INVALID_IF_INDEX; |
308de812 | 516 | |
2458325c ML |
517 | switch (type) { |
518 | case NTP_SERVER: | |
a9b9e7be | 519 | /* Client socket will be obtained when sending request */ |
779e40ed | 520 | result->local_addr.sock_fd = INVALID_SOCK_FD; |
2458325c ML |
521 | result->mode = MODE_CLIENT; |
522 | break; | |
523 | case NTP_PEER: | |
6d1dda0f | 524 | result->local_addr.sock_fd = NIO_OpenServerSocket(remote_addr); |
2458325c ML |
525 | result->mode = MODE_ACTIVE; |
526 | break; | |
527 | default: | |
528 | assert(0); | |
529 | } | |
88840341 | 530 | |
96d652e5 ML |
531 | result->interleaved = params->interleaved; |
532 | ||
88840341 | 533 | result->minpoll = params->minpoll; |
2c47602c | 534 | if (result->minpoll < MIN_POLL) |
0380cf0c | 535 | result->minpoll = SRC_DEFAULT_MINPOLL; |
a79fbef2 ML |
536 | else if (result->minpoll > MAX_POLL) |
537 | result->minpoll = MAX_POLL; | |
2c47602c | 538 | |
88840341 | 539 | result->maxpoll = params->maxpoll; |
2c47602c | 540 | if (result->maxpoll < MIN_POLL) |
0380cf0c | 541 | result->maxpoll = SRC_DEFAULT_MAXPOLL; |
a79fbef2 ML |
542 | else if (result->maxpoll > MAX_POLL) |
543 | result->maxpoll = MAX_POLL; | |
4b5f4650 ML |
544 | if (result->maxpoll < result->minpoll) |
545 | result->maxpoll = result->minpoll; | |
88840341 | 546 | |
3ebebac6 | 547 | result->min_stratum = params->min_stratum; |
740e8130 ML |
548 | if (result->min_stratum >= NTP_MAX_STRATUM) |
549 | result->min_stratum = NTP_MAX_STRATUM - 1; | |
86626521 | 550 | |
2408bbcd | 551 | /* Presend doesn't work in symmetric mode */ |
88840341 | 552 | result->presend_minpoll = params->presend_minpoll; |
90229984 ML |
553 | if (result->presend_minpoll <= MAX_POLL && result->mode != MODE_CLIENT) |
554 | result->presend_minpoll = MAX_POLL + 1; | |
3ebebac6 | 555 | |
99147ed8 ML |
556 | result->max_delay = CLAMP(0.0, params->max_delay, MAX_MAXDELAY); |
557 | result->max_delay_ratio = CLAMP(0.0, params->max_delay_ratio, MAX_MAXDELAYRATIO); | |
558 | result->max_delay_dev_ratio = CLAMP(0.0, params->max_delay_dev_ratio, MAX_MAXDELAYDEVRATIO); | |
6cd55839 | 559 | result->offset_correction = params->offset; |
b0fe4436 | 560 | result->auto_iburst = params->iburst; |
d0eb9427 | 561 | result->auto_burst = params->burst; |
3ebebac6 ML |
562 | result->auto_offline = params->auto_offline; |
563 | result->poll_target = params->poll_target; | |
88840341 | 564 | |
c4150872 ML |
565 | if (params->nts) { |
566 | IPSockAddr nts_address; | |
567 | ||
568 | if (result->mode == MODE_ACTIVE) | |
569 | LOG(LOGS_WARN, "NTS not supported with peers"); | |
570 | ||
571 | nts_address.ip_addr = remote_addr->ip_addr; | |
572 | nts_address.port = params->nts_port; | |
573 | ||
cc77b0e9 | 574 | result->auth = NAU_CreateNtsInstance(&nts_address, name, params->cert_set, |
6615bb1b | 575 | result->remote_addr.port); |
c4150872 | 576 | } else if (params->authkey != INACTIVE_AUTHKEY) { |
ca28dbd2 | 577 | result->auth = NAU_CreateSymmetricInstance(params->authkey); |
88840341 | 578 | } else { |
ca28dbd2 | 579 | result->auth = NAU_CreateNoneInstance(); |
88840341 RC |
580 | } |
581 | ||
ca28dbd2 ML |
582 | result->version = NAU_GetSuggestedNtpVersion(result->auth); |
583 | ||
e6e9a472 ML |
584 | if (params->version) |
585 | result->version = CLAMP(NTP_MIN_COMPAT_VERSION, params->version, NTP_VERSION); | |
586 | ||
8671002b | 587 | /* Create a source instance for this NTP source */ |
6688f403 | 588 | result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), |
dfe87714 ML |
589 | SRC_NTP, NAU_IsAuthEnabled(result->auth), |
590 | params->sel_options, &result->remote_addr.ip_addr, | |
d0964ffa | 591 | params->min_samples, params->max_samples, |
8ccda538 | 592 | params->min_delay, params->asymmetry); |
8671002b | 593 | |
189aafde ML |
594 | if (params->filter_length >= 1) |
595 | result->filter = SPF_CreateInstance(params->filter_length, params->filter_length, | |
596 | NTP_MAX_DISPERSION, 0.0); | |
597 | else | |
598 | result->filter = NULL; | |
599 | ||
cbd77c97 ML |
600 | result->rx_timeout_id = 0; |
601 | result->tx_timeout_id = 0; | |
779e40ed | 602 | result->tx_suspended = 1; |
b0fe4436 | 603 | result->opmode = MD_OFFLINE; |
badf97d4 | 604 | result->local_poll = result->minpoll; |
4d7eb2f7 | 605 | result->poll_score = 0.0; |
43cd119d | 606 | zero_local_timestamp(&result->local_tx); |
9c760de6 ML |
607 | result->burst_good_samples_to_go = 0; |
608 | result->burst_total_samples_to_go = 0; | |
535ca64b | 609 | memset(&result->report, 0, sizeof (result->report)); |
88840341 | 610 | |
3ebebac6 ML |
611 | NCR_ResetInstance(result); |
612 | ||
b0fe4436 | 613 | set_connectivity(result, params->connectivity); |
93b5b08b | 614 | |
88840341 | 615 | return result; |
88840341 RC |
616 | } |
617 | ||
618 | /* ================================================== */ | |
88840341 RC |
619 | |
620 | /* Destroy an instance */ | |
621 | void | |
622 | NCR_DestroyInstance(NCR_Instance instance) | |
623 | { | |
08faca03 ML |
624 | if (instance->opmode != MD_OFFLINE) |
625 | take_offline(instance); | |
626 | ||
5214d42c ML |
627 | if (instance->mode == MODE_ACTIVE) |
628 | NIO_CloseServerSocket(instance->local_addr.sock_fd); | |
629 | ||
189aafde ML |
630 | if (instance->filter) |
631 | SPF_DestroyInstance(instance->filter); | |
632 | ||
ca28dbd2 ML |
633 | NAU_DestroyInstance(instance->auth); |
634 | ||
88840341 RC |
635 | /* This will destroy the source instance inside the |
636 | structure, which will cause reselection if this was the | |
637 | synchronising source etc. */ | |
638 | SRC_DestroyInstance(instance->source); | |
639 | ||
88840341 RC |
640 | /* Free the data structure */ |
641 | Free(instance); | |
88840341 RC |
642 | } |
643 | ||
644 | /* ================================================== */ | |
645 | ||
779e40ed ML |
646 | void |
647 | NCR_StartInstance(NCR_Instance instance) | |
648 | { | |
649 | instance->tx_suspended = 0; | |
650 | if (instance->opmode != MD_OFFLINE) | |
651 | start_initial_timeout(instance); | |
652 | } | |
653 | ||
654 | /* ================================================== */ | |
655 | ||
3ebebac6 ML |
656 | void |
657 | NCR_ResetInstance(NCR_Instance instance) | |
658 | { | |
659 | instance->tx_count = 0; | |
660 | instance->presend_done = 0; | |
661 | ||
3ebebac6 ML |
662 | instance->remote_poll = 0; |
663 | instance->remote_stratum = 0; | |
664 | ||
90b25f5b ML |
665 | instance->valid_rx = 0; |
666 | instance->valid_timestamps = 0; | |
6e9c0489 ML |
667 | UTI_ZeroNtp64(&instance->remote_ntp_rx); |
668 | UTI_ZeroNtp64(&instance->remote_ntp_tx); | |
669 | UTI_ZeroNtp64(&instance->local_ntp_rx); | |
670 | UTI_ZeroNtp64(&instance->local_ntp_tx); | |
43cd119d | 671 | zero_local_timestamp(&instance->local_rx); |
64c2fd98 | 672 | |
2e0870ee | 673 | zero_local_timestamp(&instance->prev_local_tx); |
2668a12e | 674 | instance->prev_local_poll = 0; |
64c2fd98 | 675 | instance->prev_tx_count = 0; |
f0f18a02 ML |
676 | |
677 | instance->updated_init_timestamps = 0; | |
678 | UTI_ZeroNtp64(&instance->init_remote_ntp_tx); | |
679 | zero_local_timestamp(&instance->init_local_rx); | |
189aafde ML |
680 | |
681 | if (instance->filter) | |
682 | SPF_DropSamples(instance->filter); | |
4d7eb2f7 ML |
683 | } |
684 | ||
685 | /* ================================================== */ | |
badf97d4 | 686 | |
4d7eb2f7 ML |
687 | void |
688 | NCR_ResetPoll(NCR_Instance instance) | |
689 | { | |
badf97d4 ML |
690 | if (instance->local_poll != instance->minpoll) { |
691 | instance->local_poll = instance->minpoll; | |
692 | ||
693 | /* The timer was set with a longer poll interval, restart it */ | |
cbd77c97 | 694 | if (instance->tx_timeout_id) |
badf97d4 ML |
695 | restart_timeout(instance, get_transmit_delay(instance, 0, 0.0)); |
696 | } | |
3ebebac6 ML |
697 | } |
698 | ||
699 | /* ================================================== */ | |
700 | ||
29c1df46 | 701 | void |
e8062b7f | 702 | NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int ntp_only) |
29c1df46 | 703 | { |
dec0d3bf | 704 | memset(&inst->report, 0, sizeof (inst->report)); |
4d7eb2f7 | 705 | NCR_ResetInstance(inst); |
0b2e77ae | 706 | |
0b2e77ae ML |
707 | if (!ntp_only) |
708 | NAU_ChangeAddress(inst->auth, &remote_addr->ip_addr); | |
709 | ||
29c1df46 | 710 | inst->remote_addr = *remote_addr; |
29c1df46 ML |
711 | |
712 | if (inst->mode == MODE_CLIENT) | |
713 | close_client_socket(inst); | |
5214d42c ML |
714 | else { |
715 | NIO_CloseServerSocket(inst->local_addr.sock_fd); | |
eb75ce7d | 716 | inst->local_addr.ip_addr.family = IPADDR_UNSPEC; |
86acea5c | 717 | inst->local_addr.if_index = INVALID_IF_INDEX; |
6d1dda0f | 718 | inst->local_addr.sock_fd = NIO_OpenServerSocket(remote_addr); |
5214d42c | 719 | } |
29c1df46 | 720 | |
42dd5caa ML |
721 | /* Update the reference ID and reset the source/sourcestats instances */ |
722 | SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr), | |
723 | &inst->remote_addr.ip_addr); | |
724 | SRC_ResetInstance(inst->source); | |
29c1df46 ML |
725 | } |
726 | ||
727 | /* ================================================== */ | |
728 | ||
88840341 | 729 | static void |
7a6ee1d7 | 730 | adjust_poll(NCR_Instance inst, double adj) |
88840341 | 731 | { |
7a6ee1d7 | 732 | inst->poll_score += adj; |
88840341 | 733 | |
7a6ee1d7 ML |
734 | if (inst->poll_score >= 1.0) { |
735 | inst->local_poll += (int)inst->poll_score; | |
736 | inst->poll_score -= (int)inst->poll_score; | |
88840341 | 737 | } |
7a6ee1d7 ML |
738 | |
739 | if (inst->poll_score < 0.0) { | |
740 | inst->local_poll += (int)(inst->poll_score - 1.0); | |
741 | inst->poll_score -= (int)(inst->poll_score - 1.0); | |
88840341 RC |
742 | } |
743 | ||
744 | /* Clamp polling interval to defined range */ | |
745 | if (inst->local_poll < inst->minpoll) { | |
746 | inst->local_poll = inst->minpoll; | |
7a6ee1d7 | 747 | inst->poll_score = 0; |
88840341 RC |
748 | } else if (inst->local_poll > inst->maxpoll) { |
749 | inst->local_poll = inst->maxpoll; | |
7a6ee1d7 | 750 | inst->poll_score = 1.0; |
88840341 | 751 | } |
59d1b417 ML |
752 | |
753 | /* Don't allow a sub-second polling interval if the source is not reachable | |
754 | or it is not in a local network according to the measured delay */ | |
755 | if (inst->local_poll < MIN_NONLAN_POLL && | |
756 | (!SRC_IsReachable(inst->source) || | |
757 | SST_MinRoundTripDelay(SRC_GetSourcestats(inst->source)) > MAX_LAN_PEER_DELAY)) | |
758 | inst->local_poll = MIN_NONLAN_POLL; | |
88840341 RC |
759 | } |
760 | ||
761 | /* ================================================== */ | |
762 | ||
030e3b2d ML |
763 | static double |
764 | get_poll_adj(NCR_Instance inst, double error_in_estimate, double peer_distance) | |
765 | { | |
766 | double poll_adj; | |
c2ab1426 | 767 | int samples; |
030e3b2d ML |
768 | |
769 | if (error_in_estimate > peer_distance) { | |
189aafde ML |
770 | /* If the prediction is not even within +/- the peer distance of the peer, |
771 | we are clearly not tracking the peer at all well, so we back off the | |
772 | sampling rate depending on just how bad the situation is */ | |
c2ab1426 | 773 | poll_adj = -log(error_in_estimate / peer_distance) / log(2.0); |
030e3b2d | 774 | } else { |
c2ab1426 | 775 | samples = SST_Samples(SRC_GetSourcestats(inst->source)); |
030e3b2d ML |
776 | |
777 | /* Adjust polling interval so that the number of sourcestats samples | |
778 | remains close to the target value */ | |
779 | poll_adj = ((double)samples / inst->poll_target - 1.0) / inst->poll_target; | |
780 | ||
781 | /* Make interval shortening quicker */ | |
782 | if (samples < inst->poll_target) { | |
783 | poll_adj *= 2.0; | |
784 | } | |
785 | } | |
786 | ||
787 | return poll_adj; | |
788 | } | |
789 | ||
790 | /* ================================================== */ | |
791 | ||
62cd319a ML |
792 | static int |
793 | get_transmit_poll(NCR_Instance inst) | |
794 | { | |
795 | int poll; | |
796 | ||
797 | poll = inst->local_poll; | |
798 | ||
799 | /* In symmetric mode, if the peer is responding, use shorter of the local | |
800 | and remote poll interval, but not shorter than the minimum */ | |
801 | if (inst->mode == MODE_ACTIVE && poll > inst->remote_poll && | |
7352e470 | 802 | SRC_IsReachable(inst->source)) |
62cd319a ML |
803 | poll = MAX(inst->remote_poll, inst->minpoll); |
804 | ||
805 | return poll; | |
806 | } | |
807 | ||
808 | /* ================================================== */ | |
809 | ||
cf700a00 | 810 | static double |
78ae4ebf | 811 | get_transmit_delay(NCR_Instance inst, int on_tx, double last_tx) |
cf700a00 | 812 | { |
cce7a5f1 | 813 | int poll_to_use, stratum_diff; |
cf700a00 ML |
814 | double delay_time; |
815 | ||
816 | /* If we're in burst mode, queue for immediate dispatch. | |
817 | ||
818 | If we're operating in client/server mode, queue the timeout for | |
819 | the poll interval hence. The fact that a timeout has been queued | |
820 | in the transmit handler is immaterial - that is only done so that | |
821 | we at least send something, if no reply is heard. | |
822 | ||
823 | If we're in symmetric mode, we have to take account of the peer's | |
824 | wishes, otherwise his sampling regime will fall to pieces. If | |
825 | we're in client/server mode, we don't care what poll interval the | |
826 | server responded with last time. */ | |
827 | ||
62cd319a ML |
828 | poll_to_use = get_transmit_poll(inst); |
829 | delay_time = UTI_Log2ToDouble(poll_to_use); | |
830 | ||
cf700a00 ML |
831 | switch (inst->opmode) { |
832 | case MD_OFFLINE: | |
833 | assert(0); | |
834 | break; | |
835 | case MD_ONLINE: | |
cf700a00 ML |
836 | switch(inst->mode) { |
837 | case MODE_CLIENT: | |
2408bbcd ML |
838 | if (inst->presend_done) |
839 | delay_time = WARM_UP_DELAY; | |
cf700a00 ML |
840 | break; |
841 | ||
842 | case MODE_ACTIVE: | |
992590e9 | 843 | /* If the remote stratum is higher than ours, wait a bit for the next |
4a243687 ML |
844 | packet before responding in order to minimize the delay of the |
845 | measurement and its error for the peer which has higher stratum. | |
846 | If the remote stratum is equal to ours, try to interleave packets | |
847 | evenly with the peer. */ | |
cce7a5f1 | 848 | stratum_diff = inst->remote_stratum - REF_GetOurStratum(); |
992590e9 | 849 | if ((stratum_diff > 0 && last_tx * PEER_SAMPLING_ADJ < delay_time) || |
cce7a5f1 ML |
850 | (!on_tx && !stratum_diff && |
851 | last_tx / delay_time > PEER_SAMPLING_ADJ - 0.5)) | |
852 | delay_time *= PEER_SAMPLING_ADJ; | |
853 | ||
854 | /* Substract the already spend time */ | |
78ae4ebf ML |
855 | if (last_tx > 0.0) |
856 | delay_time -= last_tx; | |
857 | if (delay_time < 0.0) | |
858 | delay_time = 0.0; | |
cf700a00 ML |
859 | |
860 | break; | |
861 | default: | |
862 | assert(0); | |
863 | break; | |
864 | } | |
865 | break; | |
866 | ||
867 | case MD_BURST_WAS_ONLINE: | |
868 | case MD_BURST_WAS_OFFLINE: | |
3f3ebd3b | 869 | /* Burst modes */ |
5b75d4af | 870 | delay_time = MIN(MAX_BURST_INTERVAL, MAX_BURST_POLL_RATIO * delay_time); |
cf700a00 ML |
871 | break; |
872 | default: | |
873 | assert(0); | |
874 | break; | |
875 | } | |
876 | ||
877 | return delay_time; | |
878 | } | |
879 | ||
97d42033 ML |
880 | /* ================================================== */ |
881 | /* Calculate sampling separation for given polling interval */ | |
882 | ||
883 | static double | |
884 | get_separation(int poll) | |
885 | { | |
886 | double separation; | |
887 | ||
8aa4ae02 ML |
888 | assert(poll >= MIN_POLL && poll <= MAX_POLL); |
889 | ||
97d42033 ML |
890 | /* Allow up to 8 sources using the same short interval to not be limited |
891 | by the separation */ | |
892 | separation = UTI_Log2ToDouble(poll - 3); | |
893 | ||
894 | return CLAMP(MIN_SAMPLING_SEPARATION, separation, MAX_SAMPLING_SEPARATION); | |
895 | } | |
896 | ||
cbd77c97 ML |
897 | /* ================================================== */ |
898 | /* Timeout handler for closing the client socket when no acceptable | |
899 | reply can be received from the server */ | |
900 | ||
901 | static void | |
902 | receive_timeout(void *arg) | |
903 | { | |
904 | NCR_Instance inst = (NCR_Instance)arg; | |
905 | ||
d7868091 | 906 | DEBUG_LOG("Receive timeout for %s", UTI_IPSockAddrToString(&inst->remote_addr)); |
cbd77c97 ML |
907 | |
908 | inst->rx_timeout_id = 0; | |
909 | close_client_socket(inst); | |
910 | } | |
911 | ||
cf700a00 ML |
912 | /* ================================================== */ |
913 | ||
e3c77f9b | 914 | static int |
88840341 | 915 | transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ |
90b25f5b | 916 | int interleaved, /* Flag enabling interleaved mode */ |
88840341 | 917 | int my_poll, /* The log2 of the local poll interval */ |
73d4eaaf | 918 | int version, /* The NTP version to be set in the packet */ |
aca1daf7 | 919 | uint32_t kod, /* KoD code - 0 disabled */ |
ca28dbd2 | 920 | NAU_Instance auth, /* The authentication to be used for the packet */ |
90b25f5b ML |
921 | NTP_int64 *remote_ntp_rx, /* The receive timestamp from received packet */ |
922 | NTP_int64 *remote_ntp_tx, /* The transmit timestamp from received packet */ | |
923 | NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */ | |
924 | NTP_Local_Timestamp *local_tx, /* The TX time of the previous packet | |
925 | RESULT : TX time of this packet */ | |
2c7ab983 ML |
926 | NTP_int64 *local_ntp_rx, /* The receive timestamp from the previous packet |
927 | RESULT : receive timestamp from this packet */ | |
928 | NTP_int64 *local_ntp_tx, /* The transmit timestamp from the previous packet | |
929 | RESULT : transmit timestamp from this packet */ | |
308de812 | 930 | NTP_Remote_Address *where_to, /* Where to address the reponse to */ |
9ea1e4e4 ML |
931 | NTP_Local_Address *from, /* From what address to send it */ |
932 | NTP_Packet *request, /* The received packet if responding */ | |
933 | NTP_PacketInfo *request_info /* and its info */ | |
88840341 RC |
934 | ) |
935 | { | |
cb8660e7 | 936 | NTP_PacketInfo info; |
88840341 | 937 | NTP_Packet message; |
d0dfa1de | 938 | struct timespec local_receive, local_transmit; |
859e0c23 | 939 | double smooth_offset, local_transmit_err; |
ca28dbd2 | 940 | int ret, precision; |
116c6972 | 941 | NTP_int64 ts_fuzz; |
88840341 RC |
942 | |
943 | /* Parameters read from reference module */ | |
7f45eb79 | 944 | int are_we_synchronised, our_stratum, smooth_time; |
88840341 | 945 | NTP_Leap leap_status; |
116c6972 | 946 | uint32_t our_ref_id; |
d0dfa1de | 947 | struct timespec our_ref_time; |
859e0c23 | 948 | double our_root_delay, our_root_dispersion; |
88840341 | 949 | |
ca28dbd2 ML |
950 | assert(auth || (request && request_info)); |
951 | ||
73d4eaaf ML |
952 | /* Don't reply with version higher than ours */ |
953 | if (version > NTP_VERSION) { | |
954 | version = NTP_VERSION; | |
955 | } | |
88840341 | 956 | |
f0f18a02 ML |
957 | /* Check if the packet can be formed in the interleaved mode */ |
958 | if (interleaved && (!remote_ntp_rx || !local_tx || UTI_IsZeroTimespec(&local_tx->ts))) | |
90b25f5b ML |
959 | interleaved = 0; |
960 | ||
8225bf01 ML |
961 | smooth_time = 0; |
962 | smooth_offset = 0.0; | |
963 | ||
ff03b813 ML |
964 | /* Get an initial transmit timestamp. A more accurate timestamp will be |
965 | taken later in this function. */ | |
966 | SCH_GetLastEventTime(&local_transmit, NULL, NULL); | |
967 | ||
8225bf01 ML |
968 | if (my_mode == MODE_CLIENT) { |
969 | /* Don't reveal local time or state of the clock in client packets */ | |
970 | precision = 32; | |
2aab6a85 | 971 | leap_status = our_stratum = our_ref_id = 0; |
8225bf01 | 972 | our_root_delay = our_root_dispersion = 0.0; |
d0dfa1de | 973 | UTI_ZeroTimespec(&our_ref_time); |
7f45eb79 | 974 | } else { |
8225bf01 ML |
975 | REF_GetReferenceParams(&local_transmit, |
976 | &are_we_synchronised, &leap_status, | |
977 | &our_stratum, | |
978 | &our_ref_id, &our_ref_time, | |
979 | &our_root_delay, &our_root_dispersion); | |
980 | ||
981 | /* Get current smoothing offset when sending packet to a client */ | |
982 | if (SMT_IsEnabled() && (my_mode == MODE_SERVER || my_mode == MODE_BROADCAST)) { | |
983 | smooth_offset = SMT_GetOffset(&local_transmit); | |
984 | smooth_time = fabs(smooth_offset) > LCL_GetSysPrecisionAsQuantum(); | |
985 | ||
986 | /* Suppress leap second when smoothing and slew mode are enabled */ | |
987 | if (REF_GetLeapMode() == REF_LeapModeSlew && | |
988 | (leap_status == LEAP_InsertSecond || leap_status == LEAP_DeleteSecond)) | |
989 | leap_status = LEAP_Normal; | |
990 | } | |
991 | ||
992 | precision = LCL_GetSysPrecisionAsLog(); | |
7f45eb79 ML |
993 | } |
994 | ||
90b25f5b | 995 | if (smooth_time && !UTI_IsZeroTimespec(&local_rx->ts)) { |
ab1f01ba | 996 | our_ref_id = NTP_REFID_SMOOTH; |
d0dfa1de | 997 | UTI_AddDoubleToTimespec(&our_ref_time, smooth_offset, &our_ref_time); |
14c8f076 | 998 | UTI_AddDoubleToTimespec(&local_rx->ts, smooth_offset, &local_receive); |
ab1f01ba | 999 | } else { |
14c8f076 | 1000 | local_receive = local_rx->ts; |
ab1f01ba ML |
1001 | } |
1002 | ||
aca1daf7 ML |
1003 | if (kod != 0) { |
1004 | leap_status = LEAP_Unsynchronised; | |
1005 | our_stratum = NTP_INVALID_STRATUM; | |
1006 | our_ref_id = kod; | |
1007 | } | |
1008 | ||
88840341 | 1009 | /* Generate transmit packet */ |
2aab6a85 | 1010 | message.lvm = NTP_LVM(leap_status, version, my_mode); |
8fbfe55e ML |
1011 | /* Stratum 16 and larger are invalid */ |
1012 | if (our_stratum < NTP_MAX_STRATUM) { | |
4ba843f8 RC |
1013 | message.stratum = our_stratum; |
1014 | } else { | |
4ba843f8 RC |
1015 | message.stratum = NTP_INVALID_STRATUM; |
1016 | } | |
75a7af9e | 1017 | |
88840341 | 1018 | message.poll = my_poll; |
8225bf01 | 1019 | message.precision = precision; |
99cc9452 ML |
1020 | message.root_delay = UTI_DoubleToNtp32(our_root_delay); |
1021 | message.root_dispersion = UTI_DoubleToNtp32(our_root_dispersion); | |
b9b896d8 | 1022 | message.reference_id = htonl(our_ref_id); |
88840341 RC |
1023 | |
1024 | /* Now fill in timestamps */ | |
7f45eb79 | 1025 | |
99cc9452 | 1026 | UTI_TimespecToNtp64(&our_ref_time, &message.reference_ts, NULL); |
88840341 | 1027 | |
be8215e1 | 1028 | /* Don't reveal timestamps which are not necessary for the protocol */ |
88840341 | 1029 | |
be8215e1 ML |
1030 | if (my_mode != MODE_CLIENT || interleaved) { |
1031 | /* Originate - this comes from the last packet the source sent us */ | |
1032 | message.originate_ts = interleaved ? *remote_ntp_rx : *remote_ntp_tx; | |
8225bf01 | 1033 | |
2c7ab983 ML |
1034 | do { |
1035 | /* Prepare random bits which will be added to the receive timestamp */ | |
1036 | UTI_GetNtp64Fuzz(&ts_fuzz, precision); | |
1037 | ||
1038 | /* Receive - this is when we received the last packet from the source. | |
1039 | This timestamp will have been adjusted so that it will now look to | |
1040 | the source like we have been running on our latest estimate of | |
1041 | frequency all along */ | |
1042 | UTI_TimespecToNtp64(&local_receive, &message.receive_ts, &ts_fuzz); | |
1043 | ||
1044 | /* Do not send a packet with a non-zero receive timestamp equal to the | |
1045 | originate timestamp or previous receive timestamp */ | |
1046 | } while (!UTI_IsZeroNtp64(&message.receive_ts) && | |
1047 | UTI_IsEqualAnyNtp64(&message.receive_ts, &message.originate_ts, | |
1048 | local_ntp_rx, NULL)); | |
be8215e1 ML |
1049 | } else { |
1050 | UTI_ZeroNtp64(&message.originate_ts); | |
1051 | UTI_ZeroNtp64(&message.receive_ts); | |
1052 | } | |
df6c2a43 | 1053 | |
061579ec | 1054 | do { |
cb8660e7 ML |
1055 | if (!parse_packet(&message, NTP_HEADER_LENGTH, &info)) |
1056 | return 0; | |
1057 | ||
061579ec ML |
1058 | /* Prepare random bits which will be added to the transmit timestamp */ |
1059 | UTI_GetNtp64Fuzz(&ts_fuzz, precision); | |
1060 | ||
ff03b813 ML |
1061 | /* Get a more accurate transmit timestamp if it needs to be saved in the |
1062 | packet (i.e. in the server, symmetric, and broadcast basic modes) */ | |
1063 | if (!interleaved && precision < 32) { | |
1064 | LCL_ReadCookedTime(&local_transmit, &local_transmit_err); | |
1065 | if (smooth_time) | |
1066 | UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit); | |
ff03b813 | 1067 | } |
061579ec | 1068 | |
ca28dbd2 ML |
1069 | UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit, |
1070 | &message.transmit_ts, &ts_fuzz); | |
1071 | ||
1072 | /* Generate the authentication data */ | |
1073 | if (auth) { | |
1074 | if (!NAU_GenerateRequestAuth(auth, &message, &info)) { | |
1075 | DEBUG_LOG("Could not generate request auth"); | |
1076 | return 0; | |
577aed48 | 1077 | } |
061579ec | 1078 | } else { |
aca1daf7 ML |
1079 | if (!NAU_GenerateResponseAuth(request, request_info, &message, &info, |
1080 | where_to, from, kod)) { | |
ca28dbd2 ML |
1081 | DEBUG_LOG("Could not generate response auth"); |
1082 | return 0; | |
1083 | } | |
777303f1 | 1084 | } |
061579ec | 1085 | |
2c7ab983 ML |
1086 | /* Do not send a packet with a non-zero transmit timestamp which is |
1087 | equal to any of the following timestamps: | |
1088 | - receive (to allow reliable detection of the interleaved mode) | |
1089 | - originate (to prevent the packet from being its own valid response | |
1090 | in the symmetric mode) | |
1091 | - previous transmit (to invalidate responses to the previous packet) | |
1092 | (the precision must be at least -30 to prevent an infinite loop!) */ | |
1093 | } while (!UTI_IsZeroNtp64(&message.transmit_ts) && | |
1094 | UTI_IsEqualAnyNtp64(&message.transmit_ts, &message.receive_ts, | |
1095 | &message.originate_ts, local_ntp_tx)); | |
88840341 | 1096 | |
b8ee6d6e ML |
1097 | if (request_info && request_info->length < info.length) { |
1098 | DEBUG_LOG("Response longer than request req_len=%d res_len=%d", | |
1099 | request_info->length, info.length); | |
1100 | return 0; | |
1101 | } | |
1102 | ||
ff03b813 ML |
1103 | /* If the transmit timestamp will be saved, get an even more |
1104 | accurate daemon timestamp closer to the transmission */ | |
1105 | if (local_tx) | |
1106 | LCL_ReadCookedTime(&local_transmit, &local_transmit_err); | |
1107 | ||
cb8660e7 | 1108 | ret = NIO_SendPacket(&message, where_to, from, info.length, local_tx != NULL); |
8fbfe55e | 1109 | |
88840341 | 1110 | if (local_tx) { |
ff03b813 ML |
1111 | if (smooth_time) |
1112 | UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit); | |
14c8f076 | 1113 | local_tx->ts = local_transmit; |
859e0c23 | 1114 | local_tx->err = local_transmit_err; |
14c8f076 | 1115 | local_tx->source = NTP_TS_DAEMON; |
88840341 RC |
1116 | } |
1117 | ||
90b25f5b ML |
1118 | if (local_ntp_rx) |
1119 | *local_ntp_rx = message.receive_ts; | |
1120 | if (local_ntp_tx) | |
88840341 | 1121 | *local_ntp_tx = message.transmit_ts; |
88840341 | 1122 | |
e3c77f9b | 1123 | return ret; |
88840341 RC |
1124 | } |
1125 | ||
88840341 RC |
1126 | /* ================================================== */ |
1127 | /* Timeout handler for transmitting to a source. */ | |
1128 | ||
1129 | static void | |
1130 | transmit_timeout(void *arg) | |
1131 | { | |
1132 | NCR_Instance inst = (NCR_Instance) arg; | |
eb75ce7d | 1133 | NTP_Local_Address local_addr; |
f0f18a02 | 1134 | int interleaved, initial, sent; |
88840341 | 1135 | |
cbd77c97 | 1136 | inst->tx_timeout_id = 0; |
60a25f6e ML |
1137 | |
1138 | switch (inst->opmode) { | |
1139 | case MD_BURST_WAS_ONLINE: | |
1140 | /* With online burst switch to online before last packet */ | |
1141 | if (inst->burst_total_samples_to_go <= 1) | |
1142 | inst->opmode = MD_ONLINE; | |
deaf0ffe | 1143 | break; |
60a25f6e ML |
1144 | case MD_BURST_WAS_OFFLINE: |
1145 | if (inst->burst_total_samples_to_go <= 0) | |
1146 | take_offline(inst); | |
1147 | break; | |
d0eb9427 ML |
1148 | case MD_ONLINE: |
1149 | /* Start a new burst if the burst option is enabled and the average | |
1150 | polling interval including the burst will not fall below the | |
1151 | minimum polling interval */ | |
99e3045d | 1152 | if (inst->auto_burst && inst->local_poll > inst->minpoll) |
d0eb9427 ML |
1153 | NCR_InitiateSampleBurst(inst, BURST_GOOD_SAMPLES, |
1154 | MIN(1 << (inst->local_poll - inst->minpoll), | |
1155 | MAX_BURST_TOTAL_SAMPLES)); | |
deaf0ffe | 1156 | break; |
60a25f6e ML |
1157 | default: |
1158 | break; | |
1159 | } | |
1160 | ||
1161 | if (inst->opmode == MD_OFFLINE) { | |
1162 | return; | |
1163 | } | |
1164 | ||
d7868091 | 1165 | DEBUG_LOG("Transmit timeout for %s", UTI_IPSockAddrToString(&inst->remote_addr)); |
88840341 | 1166 | |
ca28dbd2 ML |
1167 | /* Prepare authentication */ |
1168 | if (!NAU_PrepareRequestAuth(inst->auth)) { | |
1169 | if (inst->burst_total_samples_to_go > 0) | |
1170 | inst->burst_total_samples_to_go--; | |
1171 | adjust_poll(inst, 0.25); | |
1172 | SRC_UpdateReachability(inst->source, 0); | |
1173 | restart_timeout(inst, get_transmit_delay(inst, 1, 0.0)); | |
1174 | return; | |
1175 | } | |
1176 | ||
a9b9e7be ML |
1177 | /* Open new client socket */ |
1178 | if (inst->mode == MODE_CLIENT) { | |
1179 | close_client_socket(inst); | |
1180 | assert(inst->local_addr.sock_fd == INVALID_SOCK_FD); | |
6d1dda0f | 1181 | inst->local_addr.sock_fd = NIO_OpenClientSocket(&inst->remote_addr); |
a9b9e7be ML |
1182 | } |
1183 | ||
eb75ce7d ML |
1184 | /* Don't require the packet to be sent from the same address as before */ |
1185 | local_addr.ip_addr.family = IPADDR_UNSPEC; | |
86acea5c | 1186 | local_addr.if_index = INVALID_IF_INDEX; |
eb75ce7d ML |
1187 | local_addr.sock_fd = inst->local_addr.sock_fd; |
1188 | ||
64c2fd98 ML |
1189 | /* In symmetric mode, don't send a packet in interleaved mode unless it |
1190 | is the first response to the last valid request received from the peer | |
1191 | and there was just one response to the previous valid request. This | |
1192 | prevents the peer from matching the transmit timestamp with an older | |
b896bb5a ML |
1193 | response if it can't detect missed responses. In client mode, which has |
1194 | at most one response per request, check how many responses are missing to | |
1195 | prevent the server from responding with a very old transmit timestamp. */ | |
64c2fd98 | 1196 | interleaved = inst->interleaved && |
b896bb5a ML |
1197 | ((inst->mode == MODE_CLIENT && |
1198 | inst->tx_count < MAX_CLIENT_INTERLEAVED_TX) || | |
1199 | (inst->mode == MODE_ACTIVE && | |
1200 | inst->prev_tx_count == 1 && inst->tx_count == 0)); | |
64c2fd98 | 1201 | |
f0f18a02 ML |
1202 | /* In symmetric mode, if no valid response was received since the previous |
1203 | transmission, respond to the last received packet even if it failed some | |
1204 | specific NTP tests. This is necessary for starting and restarting the | |
1205 | protocol, e.g. when a packet was lost. */ | |
1206 | initial = inst->mode == MODE_ACTIVE && !inst->valid_rx && | |
1207 | !UTI_IsZeroNtp64(&inst->init_remote_ntp_tx); | |
1208 | ||
1209 | /* Prepare for the response */ | |
1210 | inst->valid_rx = 0; | |
1211 | inst->updated_init_timestamps = 0; | |
1212 | if (initial) | |
1213 | inst->valid_timestamps = 0; | |
1214 | ||
88840341 | 1215 | /* Check whether we need to 'warm up' the link to the other end by |
cd5105b1 | 1216 | sending an NTP exchange to ensure both ends' ARP caches are |
2b3d64c3 ML |
1217 | primed or whether we need to send two packets first to ensure a |
1218 | server in the interleaved mode has a fresh timestamp for us. */ | |
9c760de6 ML |
1219 | if (inst->presend_minpoll <= inst->local_poll && !inst->presend_done && |
1220 | !inst->burst_total_samples_to_go) { | |
64c2fd98 | 1221 | inst->presend_done = interleaved ? 2 : 1; |
2b3d64c3 ML |
1222 | } else if (inst->presend_done > 0) { |
1223 | inst->presend_done--; | |
88840341 RC |
1224 | } |
1225 | ||
f0f18a02 | 1226 | /* Send the request (which may also be a response in the symmetric mode) */ |
aca1daf7 | 1227 | sent = transmit_packet(inst->mode, interleaved, inst->local_poll, inst->version, 0, |
ca28dbd2 | 1228 | inst->auth, |
f0f18a02 ML |
1229 | initial ? NULL : &inst->remote_ntp_rx, |
1230 | initial ? &inst->init_remote_ntp_tx : &inst->remote_ntp_tx, | |
1231 | initial ? &inst->init_local_rx : &inst->local_rx, | |
1232 | &inst->local_tx, &inst->local_ntp_rx, &inst->local_ntp_tx, | |
9ea1e4e4 | 1233 | &inst->remote_addr, &local_addr, NULL, NULL); |
d446950c | 1234 | |
88840341 | 1235 | ++inst->tx_count; |
535ca64b ML |
1236 | if (sent) |
1237 | inst->report.total_tx_count++; | |
88840341 | 1238 | |
d446950c ML |
1239 | /* If the source loses connectivity and our packets are still being sent, |
1240 | back off the sampling rate to reduce the network traffic. If it's the | |
1241 | source to which we are currently locked, back off slowly. */ | |
8b93e1a7 ML |
1242 | |
1243 | if (inst->tx_count >= 2) { | |
1244 | /* Implies we have missed at least one transmission */ | |
0c4968ec | 1245 | |
d446950c ML |
1246 | if (sent) { |
1247 | adjust_poll(inst, SRC_IsSyncPeer(inst->source) ? 0.1 : 0.25); | |
1248 | } | |
0c4968ec ML |
1249 | |
1250 | SRC_UpdateReachability(inst->source, 0); | |
88840341 RC |
1251 | } |
1252 | ||
7637faa0 ML |
1253 | /* With auto_offline take the source offline if sending failed */ |
1254 | if (!sent && inst->auto_offline) | |
1255 | NCR_SetConnectivity(inst, SRC_OFFLINE); | |
1256 | ||
88840341 | 1257 | switch (inst->opmode) { |
88840341 | 1258 | case MD_BURST_WAS_ONLINE: |
4e66b5ce ML |
1259 | /* When not reachable, don't stop online burst until sending succeeds */ |
1260 | if (!sent && !SRC_IsReachable(inst->source)) | |
1261 | break; | |
1262 | /* Fall through */ | |
88840341 | 1263 | case MD_BURST_WAS_OFFLINE: |
60a25f6e | 1264 | --inst->burst_total_samples_to_go; |
78ae4ebf | 1265 | break; |
7637faa0 ML |
1266 | case MD_OFFLINE: |
1267 | return; | |
78ae4ebf | 1268 | default: |
88840341 RC |
1269 | break; |
1270 | } | |
1271 | ||
78ae4ebf | 1272 | /* Restart timer for this message */ |
ba283e6b | 1273 | restart_timeout(inst, get_transmit_delay(inst, 1, 0.0)); |
88840341 | 1274 | |
cbd77c97 ML |
1275 | /* If a client packet was just sent, schedule a timeout to close the socket |
1276 | at the time when all server replies would fail the delay test, so the | |
1277 | socket is not open for longer than necessary */ | |
1278 | if (inst->mode == MODE_CLIENT) | |
1279 | inst->rx_timeout_id = SCH_AddTimeoutByDelay(inst->max_delay + MAX_SERVER_INTERVAL, | |
1280 | receive_timeout, (void *)inst); | |
1281 | } | |
88840341 | 1282 | |
8fbfe55e ML |
1283 | /* ================================================== */ |
1284 | ||
8fbfe55e | 1285 | static int |
588785e1 | 1286 | parse_packet(NTP_Packet *packet, int length, NTP_PacketInfo *info) |
8fbfe55e | 1287 | { |
588785e1 ML |
1288 | if (length < NTP_HEADER_LENGTH || length % 4U != 0) { |
1289 | DEBUG_LOG("NTP packet has invalid length %d", length); | |
1290 | return 0; | |
1291 | } | |
1292 | ||
1293 | info->length = length; | |
1294 | info->version = NTP_LVM_TO_VERSION(packet->lvm); | |
1295 | info->mode = NTP_LVM_TO_MODE(packet->lvm); | |
1296 | info->ext_fields = 0; | |
46cac4e2 | 1297 | info->auth.mode = NTP_AUTH_NONE; |
588785e1 ML |
1298 | |
1299 | if (info->version < NTP_MIN_COMPAT_VERSION || info->version > NTP_MAX_COMPAT_VERSION) { | |
1300 | DEBUG_LOG("NTP packet has invalid version %d", info->version); | |
1301 | return 0; | |
1302 | } | |
1303 | ||
56a102ed ML |
1304 | /* Parse authentication extension fields or MAC */ |
1305 | if (!NAU_ParsePacket(packet, info)) | |
1306 | return 0; | |
8fbfe55e | 1307 | |
56a102ed | 1308 | return 1; |
8fbfe55e ML |
1309 | } |
1310 | ||
88840341 RC |
1311 | /* ================================================== */ |
1312 | ||
c68ca40c ML |
1313 | static int |
1314 | check_delay_ratio(NCR_Instance inst, SST_Stats stats, | |
1315 | struct timespec *sample_time, double delay) | |
1316 | { | |
1317 | double last_sample_ago, predicted_offset, min_delay, skew, std_dev; | |
1318 | double max_delay; | |
1319 | ||
1320 | if (inst->max_delay_ratio < 1.0 || | |
1321 | !SST_GetDelayTestData(stats, sample_time, &last_sample_ago, | |
1322 | &predicted_offset, &min_delay, &skew, &std_dev)) | |
1323 | return 1; | |
1324 | ||
1325 | max_delay = min_delay * inst->max_delay_ratio + | |
1326 | last_sample_ago * (skew + LCL_GetMaxClockError()); | |
1327 | ||
1328 | if (delay <= max_delay) | |
1329 | return 1; | |
1330 | ||
1331 | DEBUG_LOG("maxdelayratio: delay=%e max_delay=%e", delay, max_delay); | |
1332 | return 0; | |
1333 | } | |
1334 | ||
1335 | /* ================================================== */ | |
1336 | ||
51fe80ad ML |
1337 | static int |
1338 | check_delay_dev_ratio(NCR_Instance inst, SST_Stats stats, | |
1339 | struct timespec *sample_time, double offset, double delay) | |
1340 | { | |
1341 | double last_sample_ago, predicted_offset, min_delay, skew, std_dev; | |
1342 | double delta, max_delta, error_in_estimate; | |
1343 | ||
1344 | if (!SST_GetDelayTestData(stats, sample_time, &last_sample_ago, | |
1345 | &predicted_offset, &min_delay, &skew, &std_dev)) | |
1346 | return 1; | |
1347 | ||
1348 | /* Require that the ratio of the increase in delay from the minimum to the | |
1349 | standard deviation is less than max_delay_dev_ratio. In the allowed | |
1350 | increase in delay include also dispersion. */ | |
1351 | ||
1352 | max_delta = std_dev * inst->max_delay_dev_ratio + | |
1353 | last_sample_ago * (skew + LCL_GetMaxClockError()); | |
1354 | delta = (delay - min_delay) / 2.0; | |
1355 | ||
1356 | if (delta <= max_delta) | |
1357 | return 1; | |
1358 | ||
1359 | error_in_estimate = offset + predicted_offset; | |
1360 | ||
1361 | /* Before we decide to drop the sample, make sure the difference between | |
1362 | measured offset and predicted offset is not significantly larger than | |
1363 | the increase in delay */ | |
1364 | if (fabs(error_in_estimate) - delta > max_delta) | |
1365 | return 1; | |
1366 | ||
1367 | DEBUG_LOG("maxdelaydevratio: error=%e delay=%e delta=%e max_delta=%e", | |
1368 | error_in_estimate, delay, delta, max_delta); | |
1369 | return 0; | |
1370 | } | |
1371 | ||
1372 | /* ================================================== */ | |
1373 | ||
7a88e0a8 ML |
1374 | static int |
1375 | check_sync_loop(NCR_Instance inst, NTP_Packet *message, NTP_Local_Address *local_addr, | |
1376 | struct timespec *local_ts) | |
1377 | { | |
1378 | double our_root_delay, our_root_dispersion; | |
1379 | int are_we_synchronised, our_stratum; | |
1380 | struct timespec our_ref_time; | |
1381 | NTP_Leap leap_status; | |
1382 | uint32_t our_ref_id; | |
1383 | ||
00498631 | 1384 | /* Check if a server socket is open, i.e. a client or peer can actually |
7a88e0a8 | 1385 | be synchronised to us */ |
00498631 | 1386 | if (!NIO_IsServerSocketOpen()) |
7a88e0a8 ML |
1387 | return 1; |
1388 | ||
1389 | /* Check if the source indicates that it is synchronised to our address | |
1390 | (assuming it uses the same address as the one from which we send requests | |
1391 | to the source) */ | |
1392 | if (message->stratum > 1 && | |
1393 | message->reference_id == htonl(UTI_IPToRefid(&local_addr->ip_addr))) | |
1394 | return 0; | |
1395 | ||
1396 | /* Compare our reference data with the source to make sure it is not us | |
1397 | (e.g. due to a misconfiguration) */ | |
1398 | ||
1399 | REF_GetReferenceParams(local_ts, &are_we_synchronised, &leap_status, &our_stratum, | |
1400 | &our_ref_id, &our_ref_time, &our_root_delay, &our_root_dispersion); | |
1401 | ||
1402 | if (message->stratum == our_stratum && | |
1403 | message->reference_id == htonl(our_ref_id) && | |
1404 | message->root_delay == UTI_DoubleToNtp32(our_root_delay) && | |
1405 | !UTI_IsZeroNtp64(&message->reference_ts)) { | |
1406 | NTP_int64 ntp_ref_time; | |
1407 | ||
1408 | UTI_TimespecToNtp64(&our_ref_time, &ntp_ref_time, NULL); | |
1409 | if (UTI_CompareNtp64(&message->reference_ts, &ntp_ref_time) == 0) { | |
1410 | DEBUG_LOG("Source %s is me", UTI_IPToString(&inst->remote_addr.ip_addr)); | |
1411 | return 0; | |
1412 | } | |
1413 | } | |
1414 | ||
1415 | return 1; | |
1416 | } | |
1417 | ||
1418 | /* ================================================== */ | |
1419 | ||
189aafde ML |
1420 | static void |
1421 | process_sample(NCR_Instance inst, NTP_Sample *sample) | |
1422 | { | |
1423 | double estimated_offset, error_in_estimate, filtered_sample_ago; | |
1424 | NTP_Sample filtered_sample; | |
1425 | int filtered_samples; | |
1426 | ||
1427 | /* Accumulate the sample to the median filter if it is enabled. When the | |
1428 | filter produces a result, check if it is not too old, i.e. the filter did | |
1429 | not miss too many samples due to missing responses or failing tests. */ | |
1430 | if (inst->filter) { | |
1431 | SPF_AccumulateSample(inst->filter, sample); | |
1432 | ||
1433 | filtered_samples = SPF_GetNumberOfSamples(inst->filter); | |
1434 | ||
1435 | if (!SPF_GetFilteredSample(inst->filter, &filtered_sample)) | |
1436 | return; | |
1437 | ||
1438 | filtered_sample_ago = UTI_DiffTimespecsToDouble(&sample->time, &filtered_sample.time); | |
1439 | ||
1440 | if (filtered_sample_ago > SOURCE_REACH_BITS / 2 * filtered_samples * | |
1441 | UTI_Log2ToDouble(inst->local_poll)) { | |
1442 | DEBUG_LOG("filtered sample dropped ago=%f poll=%d", filtered_sample_ago, | |
1443 | inst->local_poll); | |
1444 | return; | |
1445 | } | |
1446 | ||
1447 | sample = &filtered_sample; | |
1448 | } | |
1449 | ||
1450 | /* Get the estimated offset predicted from previous samples. The | |
1451 | convention here is that positive means local clock FAST of | |
1452 | reference, i.e. backwards to the way that 'offset' is defined. */ | |
1453 | estimated_offset = SST_PredictOffset(SRC_GetSourcestats(inst->source), &sample->time); | |
1454 | ||
1455 | error_in_estimate = fabs(-sample->offset - estimated_offset); | |
1456 | ||
1457 | SRC_AccumulateSample(inst->source, sample); | |
1458 | SRC_SelectSource(inst->source); | |
1459 | ||
1460 | adjust_poll(inst, get_poll_adj(inst, error_in_estimate, | |
1461 | sample->peer_dispersion + 0.5 * sample->peer_delay)); | |
1462 | } | |
1463 | ||
1464 | /* ================================================== */ | |
1465 | ||
aaf744df | 1466 | static int |
2d492eac ML |
1467 | process_response(NCR_Instance inst, NTP_Local_Address *local_addr, |
1468 | NTP_Local_Timestamp *rx_ts, NTP_Packet *message, NTP_PacketInfo *info) | |
88840341 | 1469 | { |
6bef8aa0 | 1470 | NTP_Sample sample; |
1045adaa ML |
1471 | SST_Stats stats; |
1472 | ||
89b127bf | 1473 | int pkt_leap, pkt_version; |
ca28dbd2 | 1474 | uint32_t pkt_refid; |
88840341 RC |
1475 | double pkt_root_delay; |
1476 | double pkt_root_dispersion; | |
1477 | ||
8fbfe55e ML |
1478 | /* The skew and estimated frequency offset relative to the remote source */ |
1479 | double skew, source_freq_lo, source_freq_hi; | |
88840341 | 1480 | |
8fbfe55e | 1481 | /* RFC 5905 packet tests */ |
90b25f5b ML |
1482 | int test1, test2n, test2i, test2, test3, test5, test6, test7; |
1483 | int interleaved_packet, valid_packet, synced_packet; | |
88840341 | 1484 | |
8fbfe55e ML |
1485 | /* Additional tests */ |
1486 | int testA, testB, testC, testD; | |
1487 | int good_packet; | |
88840341 | 1488 | |
8fbfe55e ML |
1489 | /* Kiss-o'-Death codes */ |
1490 | int kod_rate; | |
88840341 | 1491 | |
2e0870ee ML |
1492 | NTP_Local_Timestamp local_receive, local_transmit; |
1493 | double remote_interval, local_interval, response_time; | |
8fbfe55e | 1494 | double delay_time, precision; |
f0f18a02 | 1495 | int updated_timestamps; |
9f9dd794 | 1496 | |
8fbfe55e | 1497 | /* ==================== */ |
88840341 | 1498 | |
1045adaa ML |
1499 | stats = SRC_GetSourcestats(inst->source); |
1500 | ||
8fbfe55e | 1501 | pkt_leap = NTP_LVM_TO_LEAP(message->lvm); |
89b127bf | 1502 | pkt_version = NTP_LVM_TO_VERSION(message->lvm); |
8fbfe55e | 1503 | pkt_refid = ntohl(message->reference_id); |
99cc9452 ML |
1504 | pkt_root_delay = UTI_Ntp32ToDouble(message->root_delay); |
1505 | pkt_root_dispersion = UTI_Ntp32ToDouble(message->root_dispersion); | |
88840341 | 1506 | |
8fbfe55e ML |
1507 | /* Check if the packet is valid per RFC 5905, section 8. |
1508 | The test values are 1 when passed and 0 when failed. */ | |
1509 | ||
1510 | /* Test 1 checks for duplicate packet */ | |
666ece12 ML |
1511 | test1 = UTI_CompareNtp64(&message->receive_ts, &inst->remote_ntp_rx) || |
1512 | UTI_CompareNtp64(&message->transmit_ts, &inst->remote_ntp_tx); | |
90b25f5b ML |
1513 | |
1514 | /* Test 2 checks for bogus packet in the basic and interleaved modes. This | |
1515 | ensures the source is responding to the latest packet we sent to it. */ | |
6e9c0489 | 1516 | test2n = !UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_tx); |
90b25f5b | 1517 | test2i = inst->interleaved && |
6e9c0489 | 1518 | !UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_rx); |
90b25f5b ML |
1519 | test2 = test2n || test2i; |
1520 | interleaved_packet = !test2n && test2i; | |
8fbfe55e ML |
1521 | |
1522 | /* Test 3 checks for invalid timestamps. This can happen when the | |
1523 | association if not properly 'up'. */ | |
6e9c0489 ML |
1524 | test3 = !UTI_IsZeroNtp64(&message->originate_ts) && |
1525 | !UTI_IsZeroNtp64(&message->receive_ts) && | |
1526 | !UTI_IsZeroNtp64(&message->transmit_ts); | |
8fbfe55e ML |
1527 | |
1528 | /* Test 4 would check for denied access. It would always pass as this | |
1529 | function is called only for known sources. */ | |
1530 | ||
ca28dbd2 ML |
1531 | /* Test 5 checks for authentication failure */ |
1532 | test5 = NAU_CheckResponseAuth(inst->auth, message, info); | |
8fbfe55e ML |
1533 | |
1534 | /* Test 6 checks for unsynchronised server */ | |
1535 | test6 = pkt_leap != LEAP_Unsynchronised && | |
1536 | message->stratum < NTP_MAX_STRATUM && | |
1537 | message->stratum != NTP_INVALID_STRATUM; | |
1538 | ||
1539 | /* Test 7 checks for bad data. The root distance must be smaller than a | |
37e6357c ML |
1540 | defined maximum. */ |
1541 | test7 = pkt_root_delay / 2.0 + pkt_root_dispersion < NTP_MAX_DISPERSION; | |
8fbfe55e | 1542 | |
cea21adb ML |
1543 | /* The packet is considered valid if the tests 1-5 passed. The timestamps |
1544 | can be used for synchronisation if the tests 6 and 7 passed too. */ | |
1545 | valid_packet = test1 && test2 && test3 && test5; | |
1546 | synced_packet = valid_packet && test6 && test7; | |
8fbfe55e ML |
1547 | |
1548 | /* Check for Kiss-o'-Death codes */ | |
1549 | kod_rate = 0; | |
1550 | if (test1 && test2 && test5 && pkt_leap == LEAP_Unsynchronised && | |
1551 | message->stratum == NTP_INVALID_STRATUM) { | |
1552 | if (pkt_refid == KOD_RATE) | |
1553 | kod_rate = 1; | |
88840341 RC |
1554 | } |
1555 | ||
90b25f5b ML |
1556 | if (synced_packet && (!interleaved_packet || inst->valid_timestamps)) { |
1557 | /* These are the timespec equivalents of the remote and local epochs */ | |
2e0870ee | 1558 | struct timespec remote_receive, remote_transmit, remote_request_receive; |
2668a12e ML |
1559 | struct timespec local_average, remote_average, prev_remote_transmit; |
1560 | double prev_remote_poll_interval; | |
90b25f5b | 1561 | |
2e0870ee | 1562 | /* Select remote and local timestamps for the new sample */ |
90b25f5b | 1563 | if (interleaved_packet) { |
0baa35ea ML |
1564 | /* Prefer previous local TX and remote RX timestamps if it will make |
1565 | the intervals significantly shorter in order to improve the accuracy | |
1566 | of the measured delay */ | |
1567 | if (!UTI_IsZeroTimespec(&inst->prev_local_tx.ts) && | |
1568 | MAX_INTERLEAVED_L2L_RATIO * | |
1569 | UTI_DiffTimespecsToDouble(&inst->local_tx.ts, &inst->local_rx.ts) > | |
1570 | UTI_DiffTimespecsToDouble(&inst->local_rx.ts, &inst->prev_local_tx.ts)) { | |
1571 | UTI_Ntp64ToTimespec(&inst->remote_ntp_rx, &remote_receive); | |
1572 | remote_request_receive = remote_receive; | |
1573 | local_transmit = inst->prev_local_tx; | |
1574 | } else { | |
1575 | UTI_Ntp64ToTimespec(&message->receive_ts, &remote_receive); | |
1576 | UTI_Ntp64ToTimespec(&inst->remote_ntp_rx, &remote_request_receive); | |
1577 | local_transmit = inst->local_tx; | |
1578 | } | |
2e0870ee | 1579 | UTI_Ntp64ToTimespec(&message->transmit_ts, &remote_transmit); |
2668a12e | 1580 | UTI_Ntp64ToTimespec(&inst->remote_ntp_tx, &prev_remote_transmit); |
2e0870ee | 1581 | local_receive = inst->local_rx; |
90b25f5b | 1582 | } else { |
2e0870ee ML |
1583 | UTI_Ntp64ToTimespec(&message->receive_ts, &remote_receive); |
1584 | UTI_Ntp64ToTimespec(&message->transmit_ts, &remote_transmit); | |
2668a12e | 1585 | UTI_ZeroTimespec(&prev_remote_transmit); |
2e0870ee ML |
1586 | remote_request_receive = remote_receive; |
1587 | local_receive = *rx_ts; | |
1588 | local_transmit = inst->local_tx; | |
90b25f5b | 1589 | } |
88840341 | 1590 | |
2e0870ee ML |
1591 | /* Calculate intervals between remote and local timestamps */ |
1592 | UTI_AverageDiffTimespecs(&remote_receive, &remote_transmit, | |
1593 | &remote_average, &remote_interval); | |
1594 | UTI_AverageDiffTimespecs(&local_transmit.ts, &local_receive.ts, | |
1595 | &local_average, &local_interval); | |
1596 | response_time = fabs(UTI_DiffTimespecsToDouble(&remote_transmit, | |
1597 | &remote_request_receive)); | |
1598 | ||
1599 | precision = LCL_GetSysPrecisionAsQuantum() + UTI_Log2ToDouble(message->precision); | |
1600 | ||
14bb9f29 | 1601 | /* Calculate delay */ |
6bef8aa0 ML |
1602 | sample.peer_delay = fabs(local_interval - remote_interval); |
1603 | if (sample.peer_delay < precision) | |
1604 | sample.peer_delay = precision; | |
88840341 | 1605 | |
8fbfe55e | 1606 | /* Calculate offset. Following the NTP definition, this is negative |
88840341 | 1607 | if we are fast of the remote source. */ |
6bef8aa0 | 1608 | sample.offset = UTI_DiffTimespecsToDouble(&remote_average, &local_average); |
6cd55839 ML |
1609 | |
1610 | /* Apply configured correction */ | |
6bef8aa0 | 1611 | sample.offset += inst->offset_correction; |
6cd55839 | 1612 | |
88840341 RC |
1613 | /* We treat the time of the sample as being midway through the local |
1614 | measurement period. An analysis assuming constant relative | |
1615 | frequency and zero network delay shows this is the only possible | |
1616 | choice to estimate the frequency difference correctly for every | |
1617 | sample pair. */ | |
6bef8aa0 | 1618 | sample.time = local_average; |
88840341 | 1619 | |
2e0870ee ML |
1620 | SST_GetFrequencyRange(stats, &source_freq_lo, &source_freq_hi); |
1621 | ||
88840341 | 1622 | /* Calculate skew */ |
1d72d22b | 1623 | skew = (source_freq_hi - source_freq_lo) / 2.0; |
88840341 RC |
1624 | |
1625 | /* and then calculate peer dispersion */ | |
6bef8aa0 ML |
1626 | sample.peer_dispersion = MAX(precision, MAX(local_transmit.err, local_receive.err)) + |
1627 | skew * fabs(local_interval); | |
88840341 | 1628 | |
2668a12e ML |
1629 | /* If the source is an active peer, this is the minimum assumed interval |
1630 | between previous two transmissions (if not constrained by minpoll) */ | |
1631 | prev_remote_poll_interval = UTI_Log2ToDouble(MIN(inst->remote_poll, | |
1632 | inst->prev_local_poll)); | |
1633 | ||
8fbfe55e ML |
1634 | /* Additional tests required to pass before accumulating the sample */ |
1635 | ||
23a4e8b3 | 1636 | /* Test A requires that the minimum estimate of the peer delay is not |
2668a12e | 1637 | larger than the configured maximum, in both client modes that the server |
b896bb5a ML |
1638 | processing time is sane, and in interleaved symmetric mode that the |
1639 | measured delay and intervals between remote timestamps don't indicate | |
1640 | a missed response */ | |
6bef8aa0 ML |
1641 | testA = sample.peer_delay - sample.peer_dispersion <= inst->max_delay && |
1642 | precision <= inst->max_delay && | |
b896bb5a | 1643 | !(inst->mode == MODE_CLIENT && response_time > MAX_SERVER_INTERVAL) && |
90b25f5b | 1644 | !(inst->mode == MODE_ACTIVE && interleaved_packet && |
6bef8aa0 | 1645 | (sample.peer_delay > 0.5 * prev_remote_poll_interval || |
2668a12e ML |
1646 | UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts) <= 0 || |
1647 | (inst->remote_poll <= inst->prev_local_poll && | |
1648 | UTI_DiffTimespecsToDouble(&remote_transmit, &prev_remote_transmit) > | |
1649 | 1.5 * prev_remote_poll_interval))); | |
8fbfe55e | 1650 | |
e1645966 ML |
1651 | /* Test B requires in client mode that the ratio of the round trip delay |
1652 | to the minimum one currently in the stats data register is less than an | |
1653 | administrator-defined value */ | |
6bef8aa0 | 1654 | testB = check_delay_ratio(inst, stats, &sample.time, sample.peer_delay); |
8fbfe55e ML |
1655 | |
1656 | /* Test C requires that the ratio of the increase in delay from the minimum | |
1657 | one in the stats data register to the standard deviation of the offsets | |
1658 | in the register is less than an administrator-defined value or the | |
1659 | difference between measured offset and predicted offset is larger than | |
1660 | the increase in delay */ | |
6bef8aa0 | 1661 | testC = check_delay_dev_ratio(inst, stats, &sample.time, sample.offset, sample.peer_delay); |
8fbfe55e | 1662 | |
7a88e0a8 ML |
1663 | /* Test D requires that the source is not synchronised to us and is not us |
1664 | to prevent a synchronisation loop */ | |
1665 | testD = check_sync_loop(inst, message, local_addr, &rx_ts->ts); | |
88840341 | 1666 | } else { |
2e0870ee | 1667 | remote_interval = local_interval = response_time = 0.0; |
6bef8aa0 ML |
1668 | sample.offset = sample.peer_delay = sample.peer_dispersion = 0.0; |
1669 | sample.time = rx_ts->ts; | |
2e0870ee ML |
1670 | local_receive = *rx_ts; |
1671 | local_transmit = inst->local_tx; | |
8fbfe55e | 1672 | testA = testB = testC = testD = 0; |
88840341 RC |
1673 | } |
1674 | ||
8fbfe55e ML |
1675 | /* The packet is considered good for synchronisation if |
1676 | the additional tests passed */ | |
1677 | good_packet = testA && testB && testC && testD; | |
1678 | ||
6bef8aa0 ML |
1679 | sample.root_delay = pkt_root_delay + sample.peer_delay; |
1680 | sample.root_dispersion = pkt_root_dispersion + sample.peer_dispersion; | |
8fbfe55e | 1681 | |
90b25f5b ML |
1682 | /* Update the NTP timestamps. If it's a valid packet from a synchronised |
1683 | source, the timestamps may be used later when processing a packet in the | |
96d652e5 | 1684 | interleaved mode. Protect the timestamps against replay attacks in client |
33053a5e ML |
1685 | mode, and also in symmetric mode as long as the peers use the same polling |
1686 | interval and never start with clocks in future or very distant past. | |
1687 | The authentication test (test5) is required to prevent DoS attacks using | |
1688 | unauthenticated packets on authenticated symmetric associations. */ | |
96d652e5 | 1689 | if ((inst->mode == MODE_CLIENT && valid_packet && !inst->valid_rx) || |
f0f18a02 ML |
1690 | (inst->mode == MODE_ACTIVE && valid_packet && |
1691 | (!inst->valid_rx || | |
33053a5e | 1692 | UTI_CompareNtp64(&inst->remote_ntp_tx, &message->transmit_ts) < 0))) { |
90b25f5b ML |
1693 | inst->remote_ntp_rx = message->receive_ts; |
1694 | inst->remote_ntp_tx = message->transmit_ts; | |
1695 | inst->local_rx = *rx_ts; | |
1696 | inst->valid_timestamps = synced_packet; | |
f0f18a02 ML |
1697 | |
1698 | UTI_ZeroNtp64(&inst->init_remote_ntp_tx); | |
1699 | zero_local_timestamp(&inst->init_local_rx); | |
1700 | inst->updated_init_timestamps = 0; | |
1701 | updated_timestamps = 2; | |
0baa35ea ML |
1702 | |
1703 | /* Don't use the same set of timestamps for the next sample */ | |
1704 | if (interleaved_packet) | |
1705 | inst->prev_local_tx = inst->local_tx; | |
1706 | else | |
1707 | zero_local_timestamp(&inst->prev_local_tx); | |
f0f18a02 ML |
1708 | } else if (inst->mode == MODE_ACTIVE && |
1709 | test1 && !UTI_IsZeroNtp64(&message->transmit_ts) && test5 && | |
1710 | (!inst->updated_init_timestamps || | |
1711 | UTI_CompareNtp64(&inst->init_remote_ntp_tx, &message->transmit_ts) < 0)) { | |
1712 | inst->init_remote_ntp_tx = message->transmit_ts; | |
1713 | inst->init_local_rx = *rx_ts; | |
1714 | inst->updated_init_timestamps = 1; | |
1715 | updated_timestamps = 1; | |
1716 | } else { | |
1717 | updated_timestamps = 0; | |
90b25f5b ML |
1718 | } |
1719 | ||
1720 | /* Accept at most one response per request. The NTP specification recommends | |
1721 | resetting local_ntp_tx to make the following packets fail test2 or test3, | |
33053a5e | 1722 | but that would not allow the code above to make multiple updates of the |
2408bbcd | 1723 | timestamps in symmetric mode. Also, ignore presend responses. */ |
90b25f5b ML |
1724 | if (inst->valid_rx) { |
1725 | test2 = test3 = 0; | |
1726 | valid_packet = synced_packet = good_packet = 0; | |
1727 | } else if (valid_packet) { | |
2408bbcd ML |
1728 | if (inst->presend_done) { |
1729 | testA = 0; | |
1730 | good_packet = 0; | |
1731 | } | |
90b25f5b ML |
1732 | inst->valid_rx = 1; |
1733 | } | |
1734 | ||
2e0870ee ML |
1735 | if ((unsigned int)local_receive.source >= sizeof (tss_chars) || |
1736 | (unsigned int)local_transmit.source >= sizeof (tss_chars)) | |
9f9dd794 ML |
1737 | assert(0); |
1738 | ||
f282856c | 1739 | DEBUG_LOG("NTP packet lvm=%o stratum=%d poll=%d prec=%d root_delay=%f root_disp=%f refid=%"PRIx32" [%s]", |
8fbfe55e ML |
1740 | message->lvm, message->stratum, message->poll, message->precision, |
1741 | pkt_root_delay, pkt_root_dispersion, pkt_refid, | |
1742 | message->stratum == NTP_INVALID_STRATUM ? UTI_RefidToString(pkt_refid) : ""); | |
f282856c | 1743 | DEBUG_LOG("reference=%s origin=%s receive=%s transmit=%s", |
99cc9452 ML |
1744 | UTI_Ntp64ToString(&message->reference_ts), |
1745 | UTI_Ntp64ToString(&message->originate_ts), | |
1746 | UTI_Ntp64ToString(&message->receive_ts), | |
1747 | UTI_Ntp64ToString(&message->transmit_ts)); | |
f282856c | 1748 | DEBUG_LOG("offset=%.9f delay=%.9f dispersion=%f root_delay=%f root_dispersion=%f", |
6bef8aa0 ML |
1749 | sample.offset, sample.peer_delay, sample.peer_dispersion, |
1750 | sample.root_delay, sample.root_dispersion); | |
2e0870ee ML |
1751 | DEBUG_LOG("remote_interval=%.9f local_interval=%.9f response_time=%.9f txs=%c rxs=%c", |
1752 | remote_interval, local_interval, response_time, | |
1753 | tss_chars[local_transmit.source], tss_chars[local_receive.source]); | |
f0f18a02 ML |
1754 | DEBUG_LOG("test123=%d%d%d test567=%d%d%d testABCD=%d%d%d%d kod_rate=%d interleaved=%d" |
1755 | " presend=%d valid=%d good=%d updated=%d", | |
8fbfe55e | 1756 | test1, test2, test3, test5, test6, test7, testA, testB, testC, testD, |
2408bbcd | 1757 | kod_rate, interleaved_packet, inst->presend_done, valid_packet, good_packet, |
f0f18a02 | 1758 | updated_timestamps); |
8fbfe55e | 1759 | |
8fbfe55e | 1760 | if (valid_packet) { |
577290c5 ML |
1761 | inst->remote_poll = message->poll; |
1762 | inst->remote_stratum = message->stratum != NTP_INVALID_STRATUM ? | |
1763 | message->stratum : NTP_MAX_STRATUM; | |
1764 | ||
2668a12e | 1765 | inst->prev_local_poll = inst->local_poll; |
64c2fd98 | 1766 | inst->prev_tx_count = inst->tx_count; |
30e65496 | 1767 | inst->tx_count = 0; |
2668a12e | 1768 | |
30e65496 | 1769 | SRC_UpdateReachability(inst->source, synced_packet); |
1a8dcce8 | 1770 | SRC_UpdateStatus(inst->source, MAX(message->stratum, inst->min_stratum), pkt_leap); |
88840341 | 1771 | |
8fbfe55e | 1772 | if (good_packet) { |
189aafde ML |
1773 | /* Adjust the polling interval, accumulate the sample, etc. */ |
1774 | process_sample(inst, &sample); | |
030e3b2d ML |
1775 | |
1776 | /* If we're in burst mode, check whether the burst is completed and | |
1777 | revert to the previous mode */ | |
1778 | switch (inst->opmode) { | |
1779 | case MD_BURST_WAS_ONLINE: | |
1780 | case MD_BURST_WAS_OFFLINE: | |
1781 | --inst->burst_good_samples_to_go; | |
030e3b2d | 1782 | if (inst->burst_good_samples_to_go <= 0) { |
60a25f6e | 1783 | if (inst->opmode == MD_BURST_WAS_ONLINE) |
030e3b2d | 1784 | inst->opmode = MD_ONLINE; |
60a25f6e ML |
1785 | else |
1786 | take_offline(inst); | |
030e3b2d ML |
1787 | } |
1788 | break; | |
1789 | default: | |
1790 | break; | |
88840341 | 1791 | } |
30e65496 | 1792 | } else { |
feef0dd9 ML |
1793 | /* Slowly increase the polling interval if we can't get a good response */ |
1794 | adjust_poll(inst, testD ? 0.02 : 0.1); | |
030e3b2d | 1795 | } |
88840341 | 1796 | |
a9b9e7be ML |
1797 | /* If in client mode, no more packets are expected to be coming from the |
1798 | server and the socket can be closed */ | |
1799 | close_client_socket(inst); | |
1800 | ||
86acea5c | 1801 | /* Update the local address and interface */ |
eb75ce7d | 1802 | inst->local_addr.ip_addr = local_addr->ip_addr; |
86acea5c | 1803 | inst->local_addr.if_index = local_addr->if_index; |
eb75ce7d | 1804 | |
cea21adb ML |
1805 | /* And now, requeue the timer */ |
1806 | if (inst->opmode != MD_OFFLINE) { | |
2577e20f | 1807 | delay_time = get_transmit_delay(inst, 0, |
14c8f076 | 1808 | UTI_DiffTimespecsToDouble(&inst->local_rx.ts, &inst->local_tx.ts)); |
88840341 | 1809 | |
cea21adb | 1810 | if (kod_rate) { |
f282856c | 1811 | LOG(LOGS_WARN, "Received KoD RATE from %s", |
b76ea642 ML |
1812 | UTI_IPToString(&inst->remote_addr.ip_addr)); |
1813 | ||
cea21adb | 1814 | /* Back off for a while and stop ongoing burst */ |
beaaaad1 | 1815 | delay_time += 4 * UTI_Log2ToDouble(inst->local_poll); |
cf700a00 | 1816 | |
cea21adb ML |
1817 | if (inst->opmode == MD_BURST_WAS_OFFLINE || inst->opmode == MD_BURST_WAS_ONLINE) { |
1818 | inst->burst_good_samples_to_go = 0; | |
cea21adb ML |
1819 | } |
1820 | } | |
88840341 | 1821 | |
cea21adb ML |
1822 | /* Get rid of old timeout and start a new one */ |
1823 | assert(inst->tx_timeout_id); | |
1824 | restart_timeout(inst, delay_time); | |
1825 | } | |
535ca64b ML |
1826 | |
1827 | /* Update the NTP report */ | |
1828 | inst->report.remote_addr = inst->remote_addr.ip_addr; | |
1829 | inst->report.local_addr = inst->local_addr.ip_addr; | |
1830 | inst->report.remote_port = inst->remote_addr.port; | |
89b127bf ML |
1831 | inst->report.leap = pkt_leap; |
1832 | inst->report.version = pkt_version; | |
535ca64b ML |
1833 | inst->report.mode = NTP_LVM_TO_MODE(message->lvm); |
1834 | inst->report.stratum = message->stratum; | |
1835 | inst->report.poll = message->poll; | |
1836 | inst->report.precision = message->precision; | |
1837 | inst->report.root_delay = pkt_root_delay; | |
1838 | inst->report.root_dispersion = pkt_root_dispersion; | |
1839 | inst->report.ref_id = pkt_refid; | |
1840 | UTI_Ntp64ToTimespec(&message->reference_ts, &inst->report.ref_time); | |
6bef8aa0 ML |
1841 | inst->report.offset = sample.offset; |
1842 | inst->report.peer_delay = sample.peer_delay; | |
1843 | inst->report.peer_dispersion = sample.peer_dispersion; | |
2e0870ee | 1844 | inst->report.response_time = response_time; |
535ca64b ML |
1845 | inst->report.jitter_asymmetry = SST_GetJitterAsymmetry(stats); |
1846 | inst->report.tests = ((((((((test1 << 1 | test2) << 1 | test3) << 1 | | |
1847 | test5) << 1 | test6) << 1 | test7) << 1 | | |
1848 | testA) << 1 | testB) << 1 | testC) << 1 | testD; | |
1849 | inst->report.interleaved = interleaved_packet; | |
ca28dbd2 | 1850 | inst->report.authenticated = NAU_IsAuthEnabled(inst->auth); |
2e0870ee ML |
1851 | inst->report.tx_tss_char = tss_chars[local_transmit.source]; |
1852 | inst->report.rx_tss_char = tss_chars[local_receive.source]; | |
535ca64b ML |
1853 | |
1854 | inst->report.total_valid_count++; | |
88840341 RC |
1855 | } |
1856 | ||
1857 | /* Do measurement logging */ | |
0a0aff14 | 1858 | if (logfileid != -1 && (log_raw_measurements || synced_packet)) { |
756c2e9a | 1859 | LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d %1d%1d%1d %1d%1d%1d%d %2d %2d %4.2f %10.3e %10.3e %10.3e %10.3e %10.3e %08"PRIX32" %1d%1c %1c %1c", |
6bef8aa0 | 1860 | UTI_TimeToLogForm(sample.time.tv_sec), |
8265ff28 | 1861 | UTI_IPToString(&inst->remote_addr.ip_addr), |
2c877fa1 | 1862 | leap_chars[pkt_leap], |
88840341 | 1863 | message->stratum, |
8fbfe55e | 1864 | test1, test2, test3, test5, test6, test7, testA, testB, testC, testD, |
5c691a54 | 1865 | inst->local_poll, message->poll, |
7a6ee1d7 | 1866 | inst->poll_score, |
6bef8aa0 | 1867 | sample.offset, sample.peer_delay, sample.peer_dispersion, |
2c877fa1 ML |
1868 | pkt_root_delay, pkt_root_dispersion, pkt_refid, |
1869 | NTP_LVM_TO_MODE(message->lvm), interleaved_packet ? 'I' : 'B', | |
2e0870ee ML |
1870 | tss_chars[local_transmit.source], |
1871 | tss_chars[local_receive.source]); | |
88840341 | 1872 | } |
aaf744df | 1873 | |
b0838280 | 1874 | return good_packet; |
88840341 RC |
1875 | } |
1876 | ||
1877 | /* ================================================== */ | |
8fbfe55e | 1878 | /* From RFC 5905, the standard handling of received packets, depending |
88840341 RC |
1879 | on the mode of the packet and of the source, is : |
1880 | ||
8fbfe55e ML |
1881 | +------------------+---------------------------------------+ |
1882 | | | Packet Mode | | |
1883 | +------------------+-------+-------+-------+-------+-------+ | |
1884 | | Association Mode | 1 | 2 | 3 | 4 | 5 | | |
1885 | +------------------+-------+-------+-------+-------+-------+ | |
1886 | | No Association 0 | NEWPS | DSCRD | FXMIT | MANY | NEWBC | | |
1887 | | Symm. Active 1 | PROC | PROC | DSCRD | DSCRD | DSCRD | | |
1888 | | Symm. Passive 2 | PROC | ERR | DSCRD | DSCRD | DSCRD | | |
1889 | | Client 3 | DSCRD | DSCRD | DSCRD | PROC | DSCRD | | |
1890 | | Server 4 | DSCRD | DSCRD | DSCRD | DSCRD | DSCRD | | |
1891 | | Broadcast 5 | DSCRD | DSCRD | DSCRD | DSCRD | DSCRD | | |
1892 | | Bcast Client 6 | DSCRD | DSCRD | DSCRD | DSCRD | PROC | | |
1893 | +------------------+-------+-------+-------+-------+-------+ | |
1894 | ||
8f6a1b53 ML |
1895 | Association mode 0 is implemented in NCR_ProcessRxUnknown(), other modes |
1896 | in NCR_ProcessRxKnown(). | |
8fbfe55e ML |
1897 | |
1898 | Broadcast, manycast and ephemeral symmetric passive associations are not | |
1899 | supported yet. | |
88840341 RC |
1900 | */ |
1901 | ||
1902 | /* ================================================== */ | |
cc3f5962 ML |
1903 | /* This routine is called when a new packet arrives off the network, |
1904 | and it relates to a source we have an ongoing protocol exchange with */ | |
88840341 | 1905 | |
aaf744df | 1906 | int |
14c8f076 ML |
1907 | NCR_ProcessRxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, |
1908 | NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) | |
88840341 | 1909 | { |
cb8660e7 ML |
1910 | int proc_packet, proc_as_unknown; |
1911 | NTP_PacketInfo info; | |
88840341 | 1912 | |
567e66a0 ML |
1913 | inst->report.total_rx_count++; |
1914 | ||
cb8660e7 | 1915 | if (!parse_packet(message, length, &info)) |
aaf744df | 1916 | return 0; |
88840341 | 1917 | |
8fbfe55e ML |
1918 | proc_packet = 0; |
1919 | proc_as_unknown = 0; | |
777303f1 | 1920 | |
88840341 | 1921 | /* Now, depending on the mode we decide what to do */ |
cb8660e7 | 1922 | switch (info.mode) { |
88840341 | 1923 | case MODE_ACTIVE: |
8fbfe55e | 1924 | switch (inst->mode) { |
88840341 RC |
1925 | case MODE_ACTIVE: |
1926 | /* Ordinary symmetric peering */ | |
8fbfe55e | 1927 | proc_packet = 1; |
88840341 RC |
1928 | break; |
1929 | case MODE_PASSIVE: | |
1930 | /* In this software this case should not arise, we don't | |
1931 | support unconfigured peers */ | |
1932 | break; | |
1933 | case MODE_CLIENT: | |
1934 | /* This is where we have the remote configured as a server and he has | |
8fbfe55e ML |
1935 | us configured as a peer, process as from an unknown source */ |
1936 | proc_as_unknown = 1; | |
88840341 RC |
1937 | break; |
1938 | default: | |
8fbfe55e | 1939 | /* Discard */ |
88840341 RC |
1940 | break; |
1941 | } | |
88840341 RC |
1942 | break; |
1943 | ||
8fbfe55e ML |
1944 | case MODE_PASSIVE: |
1945 | switch (inst->mode) { | |
88840341 | 1946 | case MODE_ACTIVE: |
8fbfe55e ML |
1947 | /* This would arise if we have the remote configured as a peer and |
1948 | he does not have us configured */ | |
8fbfe55e | 1949 | proc_packet = 1; |
88840341 RC |
1950 | break; |
1951 | case MODE_PASSIVE: | |
8fbfe55e | 1952 | /* Error condition in RFC 5905 */ |
88840341 RC |
1953 | break; |
1954 | default: | |
8fbfe55e | 1955 | /* Discard */ |
88840341 RC |
1956 | break; |
1957 | } | |
1958 | break; | |
1959 | ||
8fbfe55e ML |
1960 | case MODE_CLIENT: |
1961 | /* If message is client mode, we just respond with a server mode | |
1962 | packet, regardless of what we think the remote machine is | |
1963 | supposed to be. However, even though this is a configured | |
1964 | peer or server, we still implement access restrictions on | |
1965 | client mode operation. | |
88840341 | 1966 | |
8fbfe55e ML |
1967 | This copes with the case for an isolated network where one |
1968 | machine is set by eye and is used as the master, with the | |
1969 | other machines pointed at it. If the master goes down, we | |
1970 | want to be able to reset its time at startup by relying on | |
1971 | one of the secondaries to flywheel it. The behaviour coded here | |
1972 | is required in the secondaries to make this possible. */ | |
1973 | ||
1974 | proc_as_unknown = 1; | |
1975 | break; | |
1976 | ||
1977 | case MODE_SERVER: | |
8fbfe55e | 1978 | switch (inst->mode) { |
88840341 | 1979 | case MODE_CLIENT: |
8fbfe55e ML |
1980 | /* Standard case where he's a server and we're the client */ |
1981 | proc_packet = 1; | |
88840341 RC |
1982 | break; |
1983 | default: | |
8fbfe55e | 1984 | /* Discard */ |
88840341 RC |
1985 | break; |
1986 | } | |
1987 | break; | |
1988 | ||
1989 | case MODE_BROADCAST: | |
8fbfe55e | 1990 | /* Just ignore these */ |
88840341 RC |
1991 | break; |
1992 | ||
1993 | default: | |
1994 | /* Obviously ignore */ | |
1995 | break; | |
8fbfe55e ML |
1996 | } |
1997 | ||
8fbfe55e | 1998 | if (proc_packet) { |
dccd6196 ML |
1999 | /* Check if the reply was received by the socket that sent the request */ |
2000 | if (local_addr->sock_fd != inst->local_addr.sock_fd) { | |
f282856c | 2001 | DEBUG_LOG("Packet received by wrong socket %d (expected %d)", |
dccd6196 | 2002 | local_addr->sock_fd, inst->local_addr.sock_fd); |
aaf744df | 2003 | return 0; |
dccd6196 ML |
2004 | } |
2005 | ||
2006 | /* Ignore packets from offline sources */ | |
2007 | if (inst->opmode == MD_OFFLINE || inst->tx_suspended) { | |
f282856c | 2008 | DEBUG_LOG("Packet from offline source"); |
aaf744df | 2009 | return 0; |
dccd6196 ML |
2010 | } |
2011 | ||
2d492eac | 2012 | return process_response(inst, local_addr, rx_ts, message, &info); |
8fbfe55e | 2013 | } else if (proc_as_unknown) { |
14c8f076 | 2014 | NCR_ProcessRxUnknown(&inst->remote_addr, local_addr, rx_ts, message, length); |
aaf744df ML |
2015 | /* It's not a reply to our request, don't return success */ |
2016 | return 0; | |
8fbfe55e | 2017 | } else { |
cb8660e7 | 2018 | DEBUG_LOG("NTP packet discarded mode=%d our_mode=%u", (int)info.mode, inst->mode); |
aaf744df | 2019 | return 0; |
88840341 | 2020 | } |
88840341 RC |
2021 | } |
2022 | ||
2023 | /* ================================================== */ | |
2024 | /* This routine is called when a new packet arrives off the network, | |
73e49868 | 2025 | and it relates to a source we don't know (not our server or peer) */ |
88840341 RC |
2026 | |
2027 | void | |
14c8f076 ML |
2028 | NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, |
2029 | NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) | |
88840341 | 2030 | { |
cb8660e7 ML |
2031 | NTP_PacketInfo info; |
2032 | NTP_Mode my_mode; | |
96d652e5 ML |
2033 | NTP_int64 *local_ntp_rx, *local_ntp_tx; |
2034 | NTP_Local_Timestamp local_tx, *tx_ts; | |
ca28dbd2 | 2035 | int log_index, interleaved, poll, version; |
aca1daf7 | 2036 | uint32_t kod; |
88840341 | 2037 | |
91e74c70 ML |
2038 | /* Ignore the packet if it wasn't received by server socket */ |
2039 | if (!NIO_IsServerSocket(local_addr->sock_fd)) { | |
f282856c | 2040 | DEBUG_LOG("NTP request packet received by client socket %d", local_addr->sock_fd); |
91e74c70 ML |
2041 | return; |
2042 | } | |
2043 | ||
cb8660e7 | 2044 | if (!parse_packet(message, length, &info)) |
8cc7ebff | 2045 | return; |
8cc7ebff | 2046 | |
8fbfe55e | 2047 | if (!ADF_IsAllowed(access_auth_table, &remote_addr->ip_addr)) { |
d7868091 ML |
2048 | DEBUG_LOG("NTP packet received from unauthorised host %s", |
2049 | UTI_IPToString(&remote_addr->ip_addr)); | |
8fbfe55e ML |
2050 | return; |
2051 | } | |
88840341 | 2052 | |
cb8660e7 | 2053 | switch (info.mode) { |
8fbfe55e | 2054 | case MODE_ACTIVE: |
88840341 RC |
2055 | /* We are symmetric passive, even though we don't ever lock to him */ |
2056 | my_mode = MODE_PASSIVE; | |
8fbfe55e ML |
2057 | break; |
2058 | case MODE_CLIENT: | |
2059 | /* Reply with server packet */ | |
2060 | my_mode = MODE_SERVER; | |
8fbfe55e | 2061 | break; |
fbca570d ML |
2062 | case MODE_UNDEFINED: |
2063 | /* Check if it is an NTPv1 client request (NTPv1 packets have a reserved | |
2064 | field instead of the mode field and the actual mode is determined from | |
2065 | the port numbers). Don't ever respond with a mode 0 packet! */ | |
cb8660e7 | 2066 | if (info.version == 1 && remote_addr->port != NTP_PORT) { |
fbca570d ML |
2067 | my_mode = MODE_SERVER; |
2068 | break; | |
2069 | } | |
2070 | /* Fall through */ | |
8fbfe55e ML |
2071 | default: |
2072 | /* Discard */ | |
cb8660e7 | 2073 | DEBUG_LOG("NTP packet discarded mode=%d", (int)info.mode); |
8fbfe55e | 2074 | return; |
88840341 | 2075 | } |
8fbfe55e | 2076 | |
aca1daf7 | 2077 | kod = 0; |
3a2d33d5 | 2078 | log_index = CLG_LogServiceAccess(CLG_NTP, &remote_addr->ip_addr, &rx_ts->ts); |
b506594c ML |
2079 | |
2080 | /* Don't reply to all requests if the rate is excessive */ | |
3a2d33d5 | 2081 | if (log_index >= 0 && CLG_LimitServiceRate(CLG_NTP, log_index)) { |
f282856c | 2082 | DEBUG_LOG("NTP packet discarded to limit response rate"); |
b506594c ML |
2083 | return; |
2084 | } | |
086e886d | 2085 | |
ca28dbd2 | 2086 | /* Check authentication */ |
aca1daf7 ML |
2087 | if (!NAU_CheckRequestAuth(message, &info, &kod)) { |
2088 | DEBUG_LOG("NTP packet failed auth mode=%d kod=%"PRIx32, (int)info.auth.mode, kod); | |
2089 | ||
2090 | /* Don't respond unless a non-zero KoD was returned */ | |
2091 | if (kod == 0) | |
2092 | return; | |
f8df4789 ML |
2093 | } else if (info.auth.mode != NTP_AUTH_NONE && info.auth.mode != NTP_AUTH_MSSNTP) { |
2094 | CLG_LogAuthNtpRequest(); | |
61dd4e0c | 2095 | } |
8fbfe55e | 2096 | |
96d652e5 ML |
2097 | local_ntp_rx = local_ntp_tx = NULL; |
2098 | tx_ts = NULL; | |
2099 | interleaved = 0; | |
2100 | ||
2101 | /* Check if the client is using the interleaved mode. If it is, save the | |
2102 | new transmit timestamp and if the old transmit timestamp is valid, respond | |
2103 | in the interleaved mode. This means the third reply to a new client is | |
2104 | the earliest one that can be interleaved. We don't want to waste time | |
2105 | on clients that are not using the interleaved mode. */ | |
aca1daf7 | 2106 | if (kod == 0 && log_index >= 0) { |
96d652e5 | 2107 | CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx); |
6e9c0489 | 2108 | interleaved = !UTI_IsZeroNtp64(local_ntp_rx) && |
c6dd7496 ML |
2109 | !UTI_CompareNtp64(&message->originate_ts, local_ntp_rx) && |
2110 | UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts); | |
96d652e5 ML |
2111 | |
2112 | if (interleaved) { | |
4b98dada | 2113 | UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts); |
96d652e5 ML |
2114 | tx_ts = &local_tx; |
2115 | } else { | |
6e9c0489 | 2116 | UTI_ZeroNtp64(local_ntp_tx); |
96d652e5 ML |
2117 | local_ntp_tx = NULL; |
2118 | } | |
2119 | } | |
2120 | ||
018a1c42 ML |
2121 | /* Suggest the client to increase its polling interval if it indicates |
2122 | the interval is shorter than the rate limiting interval */ | |
2123 | poll = CLG_GetNtpMinPoll(); | |
2124 | poll = MAX(poll, message->poll); | |
2125 | ||
fdfcabd7 ML |
2126 | /* Respond with the same version */ |
2127 | version = info.version; | |
2128 | ||
96d652e5 | 2129 | /* Send a reply */ |
aca1daf7 | 2130 | transmit_packet(my_mode, interleaved, poll, version, kod, NULL, |
ca28dbd2 | 2131 | &message->receive_ts, &message->transmit_ts, |
9ea1e4e4 ML |
2132 | rx_ts, tx_ts, local_ntp_rx, NULL, remote_addr, local_addr, |
2133 | message, &info); | |
96d652e5 ML |
2134 | |
2135 | /* Save the transmit timestamp */ | |
2136 | if (tx_ts) | |
2137 | UTI_TimespecToNtp64(&tx_ts->ts, local_ntp_tx, NULL); | |
88840341 RC |
2138 | } |
2139 | ||
2140 | /* ================================================== */ | |
2141 | ||
8f6a1b53 | 2142 | static void |
14c8f076 | 2143 | update_tx_timestamp(NTP_Local_Timestamp *tx_ts, NTP_Local_Timestamp *new_tx_ts, |
bd736f92 | 2144 | NTP_int64 *local_ntp_rx, NTP_int64 *local_ntp_tx, NTP_Packet *message) |
8f6a1b53 ML |
2145 | { |
2146 | double delay; | |
2147 | ||
14c8f076 | 2148 | if (UTI_IsZeroTimespec(&tx_ts->ts)) { |
f282856c | 2149 | DEBUG_LOG("Unexpected TX update"); |
8f6a1b53 ML |
2150 | return; |
2151 | } | |
2152 | ||
2153 | /* Check if this is the last packet that was sent */ | |
6e9c0489 ML |
2154 | if ((local_ntp_rx && UTI_CompareNtp64(&message->receive_ts, local_ntp_rx)) || |
2155 | (local_ntp_tx && UTI_CompareNtp64(&message->transmit_ts, local_ntp_tx))) { | |
f282856c | 2156 | DEBUG_LOG("RX/TX timestamp mismatch"); |
8f6a1b53 ML |
2157 | return; |
2158 | } | |
2159 | ||
14c8f076 | 2160 | delay = UTI_DiffTimespecsToDouble(&new_tx_ts->ts, &tx_ts->ts); |
8f6a1b53 ML |
2161 | |
2162 | if (delay < 0.0 || delay > MAX_TX_DELAY) { | |
f282856c | 2163 | DEBUG_LOG("Unacceptable TX delay %.9f", delay); |
8f6a1b53 ML |
2164 | return; |
2165 | } | |
2166 | ||
2167 | *tx_ts = *new_tx_ts; | |
2168 | ||
f282856c | 2169 | DEBUG_LOG("Updated TX timestamp delay=%.9f", delay); |
8f6a1b53 ML |
2170 | } |
2171 | ||
2172 | /* ================================================== */ | |
2173 | ||
2174 | void | |
14c8f076 ML |
2175 | NCR_ProcessTxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, |
2176 | NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length) | |
8f6a1b53 | 2177 | { |
cb8660e7 | 2178 | NTP_PacketInfo info; |
8f6a1b53 | 2179 | |
cb8660e7 | 2180 | if (!parse_packet(message, length, &info)) |
8f6a1b53 ML |
2181 | return; |
2182 | ||
8f6a1b53 | 2183 | /* Server and passive mode packets are responses to unknown sources */ |
cb8660e7 | 2184 | if (info.mode != MODE_CLIENT && info.mode != MODE_ACTIVE) { |
14c8f076 | 2185 | NCR_ProcessTxUnknown(&inst->remote_addr, local_addr, tx_ts, message, length); |
8f6a1b53 ML |
2186 | return; |
2187 | } | |
2188 | ||
bd736f92 ML |
2189 | update_tx_timestamp(&inst->local_tx, tx_ts, &inst->local_ntp_rx, &inst->local_ntp_tx, |
2190 | message); | |
8f6a1b53 ML |
2191 | } |
2192 | ||
2193 | /* ================================================== */ | |
2194 | ||
2195 | void | |
14c8f076 ML |
2196 | NCR_ProcessTxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, |
2197 | NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length) | |
8f6a1b53 | 2198 | { |
96d652e5 ML |
2199 | NTP_int64 *local_ntp_rx, *local_ntp_tx; |
2200 | NTP_Local_Timestamp local_tx; | |
cb8660e7 | 2201 | NTP_PacketInfo info; |
96d652e5 ML |
2202 | int log_index; |
2203 | ||
cb8660e7 | 2204 | if (!parse_packet(message, length, &info)) |
96d652e5 ML |
2205 | return; |
2206 | ||
cb8660e7 | 2207 | if (info.mode == MODE_BROADCAST) |
2d67871b ML |
2208 | return; |
2209 | ||
96d652e5 ML |
2210 | log_index = CLG_GetClientIndex(&remote_addr->ip_addr); |
2211 | if (log_index < 0) | |
2212 | return; | |
2213 | ||
cb8660e7 | 2214 | if (SMT_IsEnabled() && info.mode == MODE_SERVER) |
da2d33e9 ML |
2215 | UTI_AddDoubleToTimespec(&tx_ts->ts, SMT_GetOffset(&tx_ts->ts), &tx_ts->ts); |
2216 | ||
96d652e5 ML |
2217 | CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx); |
2218 | ||
2219 | UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts); | |
2220 | update_tx_timestamp(&local_tx, tx_ts, local_ntp_rx, NULL, message); | |
2221 | UTI_TimespecToNtp64(&local_tx.ts, local_ntp_tx, NULL); | |
8f6a1b53 ML |
2222 | } |
2223 | ||
2224 | /* ================================================== */ | |
2225 | ||
88840341 | 2226 | void |
d0dfa1de | 2227 | NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double doffset) |
88840341 | 2228 | { |
40d82675 | 2229 | double delta; |
7958b176 | 2230 | |
14c8f076 ML |
2231 | if (!UTI_IsZeroTimespec(&inst->local_rx.ts)) |
2232 | UTI_AdjustTimespec(&inst->local_rx.ts, when, &inst->local_rx.ts, &delta, dfreq, doffset); | |
2233 | if (!UTI_IsZeroTimespec(&inst->local_tx.ts)) | |
2234 | UTI_AdjustTimespec(&inst->local_tx.ts, when, &inst->local_tx.ts, &delta, dfreq, doffset); | |
0baa35ea ML |
2235 | if (!UTI_IsZeroTimespec(&inst->prev_local_tx.ts)) |
2236 | UTI_AdjustTimespec(&inst->prev_local_tx.ts, when, &inst->prev_local_tx.ts, &delta, dfreq, | |
2237 | doffset); | |
f0f18a02 | 2238 | if (!UTI_IsZeroTimespec(&inst->init_local_rx.ts)) |
b2964417 | 2239 | UTI_AdjustTimespec(&inst->init_local_rx.ts, when, &inst->init_local_rx.ts, &delta, dfreq, |
f0f18a02 | 2240 | doffset); |
189aafde ML |
2241 | |
2242 | if (inst->filter) | |
2243 | SPF_SlewSamples(inst->filter, when, dfreq, doffset); | |
88840341 RC |
2244 | } |
2245 | ||
2246 | /* ================================================== */ | |
2247 | ||
b0fe4436 ML |
2248 | static void |
2249 | set_connectivity(NCR_Instance inst, SRC_Connectivity connectivity) | |
88840341 | 2250 | { |
8b9021bf ML |
2251 | if (connectivity == SRC_MAYBE_ONLINE) |
2252 | connectivity = NIO_IsServerConnectable(&inst->remote_addr) ? SRC_ONLINE : SRC_OFFLINE; | |
2253 | ||
ce6b8969 ML |
2254 | switch (connectivity) { |
2255 | case SRC_ONLINE: | |
2256 | switch (inst->opmode) { | |
2257 | case MD_ONLINE: | |
2258 | /* Nothing to do */ | |
2259 | break; | |
2260 | case MD_OFFLINE: | |
ce6b8969 ML |
2261 | inst->opmode = MD_ONLINE; |
2262 | NCR_ResetInstance(inst); | |
2263 | start_initial_timeout(inst); | |
b0fe4436 ML |
2264 | if (inst->auto_iburst) |
2265 | NCR_InitiateSampleBurst(inst, IBURST_GOOD_SAMPLES, IBURST_TOTAL_SAMPLES); | |
ce6b8969 ML |
2266 | break; |
2267 | case MD_BURST_WAS_ONLINE: | |
2268 | /* Will revert */ | |
2269 | break; | |
2270 | case MD_BURST_WAS_OFFLINE: | |
2271 | inst->opmode = MD_BURST_WAS_ONLINE; | |
ce6b8969 ML |
2272 | break; |
2273 | default: | |
2274 | assert(0); | |
2275 | } | |
88840341 | 2276 | break; |
ce6b8969 ML |
2277 | case SRC_OFFLINE: |
2278 | switch (inst->opmode) { | |
2279 | case MD_ONLINE: | |
ce6b8969 ML |
2280 | take_offline(inst); |
2281 | break; | |
2282 | case MD_OFFLINE: | |
2283 | break; | |
2284 | case MD_BURST_WAS_ONLINE: | |
2285 | inst->opmode = MD_BURST_WAS_OFFLINE; | |
ce6b8969 ML |
2286 | break; |
2287 | case MD_BURST_WAS_OFFLINE: | |
2288 | break; | |
2289 | default: | |
2290 | assert(0); | |
2291 | } | |
88840341 | 2292 | break; |
ce6b8969 ML |
2293 | default: |
2294 | assert(0); | |
88840341 | 2295 | } |
88840341 RC |
2296 | } |
2297 | ||
2298 | /* ================================================== */ | |
2299 | ||
b0fe4436 ML |
2300 | void |
2301 | NCR_SetConnectivity(NCR_Instance inst, SRC_Connectivity connectivity) | |
2302 | { | |
2303 | OperatingMode prev_opmode; | |
2304 | int was_online, is_online; | |
2305 | ||
2306 | prev_opmode = inst->opmode; | |
2307 | ||
2308 | set_connectivity(inst, connectivity); | |
2309 | ||
2310 | /* Report an important change */ | |
2311 | was_online = prev_opmode == MD_ONLINE || prev_opmode == MD_BURST_WAS_ONLINE; | |
2312 | is_online = inst->opmode == MD_ONLINE || inst->opmode == MD_BURST_WAS_ONLINE; | |
2313 | if (was_online != is_online) | |
2314 | LOG(LOGS_INFO, "Source %s %s", | |
2315 | UTI_IPToString(&inst->remote_addr.ip_addr), is_online ? "online" : "offline"); | |
2316 | } | |
2317 | ||
2318 | /* ================================================== */ | |
2319 | ||
88840341 RC |
2320 | void |
2321 | NCR_ModifyMinpoll(NCR_Instance inst, int new_minpoll) | |
2322 | { | |
2c47602c | 2323 | if (new_minpoll < MIN_POLL || new_minpoll > MAX_POLL) |
0380cf0c | 2324 | return; |
88840341 | 2325 | inst->minpoll = new_minpoll; |
f282856c | 2326 | LOG(LOGS_INFO, "Source %s new minpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_minpoll); |
4b5f4650 ML |
2327 | if (inst->maxpoll < inst->minpoll) |
2328 | NCR_ModifyMaxpoll(inst, inst->minpoll); | |
88840341 RC |
2329 | } |
2330 | ||
2331 | /* ================================================== */ | |
2332 | ||
2333 | void | |
2334 | NCR_ModifyMaxpoll(NCR_Instance inst, int new_maxpoll) | |
2335 | { | |
2c47602c | 2336 | if (new_maxpoll < MIN_POLL || new_maxpoll > MAX_POLL) |
0380cf0c | 2337 | return; |
88840341 | 2338 | inst->maxpoll = new_maxpoll; |
f282856c | 2339 | LOG(LOGS_INFO, "Source %s new maxpoll %d", UTI_IPToString(&inst->remote_addr.ip_addr), new_maxpoll); |
4b5f4650 ML |
2340 | if (inst->minpoll > inst->maxpoll) |
2341 | NCR_ModifyMinpoll(inst, inst->maxpoll); | |
88840341 RC |
2342 | } |
2343 | ||
2344 | /* ================================================== */ | |
2345 | ||
2346 | void | |
2347 | NCR_ModifyMaxdelay(NCR_Instance inst, double new_max_delay) | |
2348 | { | |
99147ed8 | 2349 | inst->max_delay = CLAMP(0.0, new_max_delay, MAX_MAXDELAY); |
74f0c092 | 2350 | LOG(LOGS_INFO, "Source %s new maxdelay %f", |
f2f834e7 | 2351 | UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay); |
88840341 RC |
2352 | } |
2353 | ||
2354 | /* ================================================== */ | |
2355 | ||
2356 | void | |
2357 | NCR_ModifyMaxdelayratio(NCR_Instance inst, double new_max_delay_ratio) | |
2358 | { | |
99147ed8 | 2359 | inst->max_delay_ratio = CLAMP(0.0, new_max_delay_ratio, MAX_MAXDELAYRATIO); |
74f0c092 | 2360 | LOG(LOGS_INFO, "Source %s new maxdelayratio %f", |
f2f834e7 | 2361 | UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_ratio); |
88840341 RC |
2362 | } |
2363 | ||
2364 | /* ================================================== */ | |
2365 | ||
6ed5a650 ML |
2366 | void |
2367 | NCR_ModifyMaxdelaydevratio(NCR_Instance inst, double new_max_delay_dev_ratio) | |
2368 | { | |
99147ed8 | 2369 | inst->max_delay_dev_ratio = CLAMP(0.0, new_max_delay_dev_ratio, MAX_MAXDELAYDEVRATIO); |
74f0c092 | 2370 | LOG(LOGS_INFO, "Source %s new maxdelaydevratio %f", |
f2f834e7 | 2371 | UTI_IPToString(&inst->remote_addr.ip_addr), inst->max_delay_dev_ratio); |
6ed5a650 ML |
2372 | } |
2373 | ||
2374 | /* ================================================== */ | |
2375 | ||
78300d01 ML |
2376 | void |
2377 | NCR_ModifyMinstratum(NCR_Instance inst, int new_min_stratum) | |
2378 | { | |
2379 | inst->min_stratum = new_min_stratum; | |
f282856c | 2380 | LOG(LOGS_INFO, "Source %s new minstratum %d", |
78300d01 ML |
2381 | UTI_IPToString(&inst->remote_addr.ip_addr), new_min_stratum); |
2382 | } | |
2383 | ||
2384 | /* ================================================== */ | |
2385 | ||
bed5b72c ML |
2386 | void |
2387 | NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target) | |
2388 | { | |
2389 | inst->poll_target = new_poll_target; | |
f282856c | 2390 | LOG(LOGS_INFO, "Source %s new polltarget %d", |
bed5b72c ML |
2391 | UTI_IPToString(&inst->remote_addr.ip_addr), new_poll_target); |
2392 | } | |
2393 | ||
2394 | /* ================================================== */ | |
2395 | ||
88840341 RC |
2396 | void |
2397 | NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples) | |
2398 | { | |
2399 | ||
2400 | if (inst->mode == MODE_CLIENT) { | |
2401 | ||
2402 | /* We want to prevent burst mode being used on symmetric active | |
2403 | associations - it will play havoc with the peer's sampling | |
2404 | strategy. (This obviously relies on us having the peer | |
2405 | configured that way if he has us configured symmetric active - | |
2406 | but there's not much else we can do.) */ | |
2407 | ||
2408 | switch (inst->opmode) { | |
2409 | case MD_BURST_WAS_OFFLINE: | |
2410 | case MD_BURST_WAS_ONLINE: | |
2411 | /* If already burst sampling, don't start again */ | |
2412 | break; | |
2413 | ||
2414 | case MD_ONLINE: | |
8671002b | 2415 | case MD_OFFLINE: |
779e40ed ML |
2416 | inst->opmode = inst->opmode == MD_ONLINE ? |
2417 | MD_BURST_WAS_ONLINE : MD_BURST_WAS_OFFLINE; | |
8671002b ML |
2418 | inst->burst_good_samples_to_go = n_good_samples; |
2419 | inst->burst_total_samples_to_go = n_total_samples; | |
2420 | start_initial_timeout(inst); | |
2421 | break; | |
88840341 | 2422 | default: |
6b0198c2 | 2423 | assert(0); |
88840341 RC |
2424 | break; |
2425 | } | |
2426 | } | |
2427 | ||
2428 | } | |
2429 | ||
2430 | /* ================================================== */ | |
2431 | ||
2432 | void | |
d0dfa1de | 2433 | NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now) |
88840341 | 2434 | { |
62cd319a | 2435 | report->poll = get_transmit_poll(inst); |
88840341 RC |
2436 | |
2437 | switch (inst->mode) { | |
2438 | case MODE_CLIENT: | |
2439 | report->mode = RPT_NTP_CLIENT; | |
2440 | break; | |
2441 | case MODE_ACTIVE: | |
2442 | report->mode = RPT_NTP_PEER; | |
2443 | break; | |
2444 | default: | |
6b0198c2 | 2445 | assert(0); |
88840341 | 2446 | } |
88840341 RC |
2447 | } |
2448 | ||
2449 | /* ================================================== */ | |
2450 | ||
79c7384e ML |
2451 | void |
2452 | NCR_GetAuthReport(NCR_Instance inst, RPT_AuthReport *report) | |
2453 | { | |
2454 | NAU_GetReport(inst->auth, report); | |
2455 | } | |
2456 | ||
2457 | /* ================================================== */ | |
2458 | ||
535ca64b ML |
2459 | void |
2460 | NCR_GetNTPReport(NCR_Instance inst, RPT_NTPReport *report) | |
2461 | { | |
2462 | *report = inst->report; | |
2463 | } | |
2464 | ||
2465 | /* ================================================== */ | |
2466 | ||
88840341 | 2467 | int |
8265ff28 | 2468 | NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all) |
88840341 RC |
2469 | { |
2470 | ADF_Status status; | |
2471 | ||
2472 | if (allow) { | |
2473 | if (all) { | |
2474 | status = ADF_AllowAll(access_auth_table, ip_addr, subnet_bits); | |
2475 | } else { | |
2476 | status = ADF_Allow(access_auth_table, ip_addr, subnet_bits); | |
2477 | } | |
2478 | } else { | |
2479 | if (all) { | |
2480 | status = ADF_DenyAll(access_auth_table, ip_addr, subnet_bits); | |
2481 | } else { | |
2482 | status = ADF_Deny(access_auth_table, ip_addr, subnet_bits); | |
2483 | } | |
2484 | } | |
2485 | ||
52e12e42 | 2486 | if (status != ADF_SUCCESS) |
88840341 | 2487 | return 0; |
52e12e42 ML |
2488 | |
2489 | /* Keep server sockets open only when an address allowed */ | |
2490 | if (allow) { | |
2491 | NTP_Remote_Address remote_addr; | |
2492 | ||
2493 | if (server_sock_fd4 == INVALID_SOCK_FD && | |
2494 | ADF_IsAnyAllowed(access_auth_table, IPADDR_INET4)) { | |
2495 | remote_addr.ip_addr.family = IPADDR_INET4; | |
2496 | server_sock_fd4 = NIO_OpenServerSocket(&remote_addr); | |
2497 | } | |
2498 | if (server_sock_fd6 == INVALID_SOCK_FD && | |
2499 | ADF_IsAnyAllowed(access_auth_table, IPADDR_INET6)) { | |
2500 | remote_addr.ip_addr.family = IPADDR_INET6; | |
2501 | server_sock_fd6 = NIO_OpenServerSocket(&remote_addr); | |
2502 | } | |
88840341 | 2503 | } else { |
52e12e42 ML |
2504 | if (server_sock_fd4 != INVALID_SOCK_FD && |
2505 | !ADF_IsAnyAllowed(access_auth_table, IPADDR_INET4)) { | |
2506 | NIO_CloseServerSocket(server_sock_fd4); | |
2507 | server_sock_fd4 = INVALID_SOCK_FD; | |
2508 | } | |
2509 | if (server_sock_fd6 != INVALID_SOCK_FD && | |
2510 | !ADF_IsAnyAllowed(access_auth_table, IPADDR_INET6)) { | |
2511 | NIO_CloseServerSocket(server_sock_fd6); | |
2512 | server_sock_fd6 = INVALID_SOCK_FD; | |
2513 | } | |
88840341 | 2514 | } |
52e12e42 ML |
2515 | |
2516 | return 1; | |
88840341 RC |
2517 | } |
2518 | ||
2519 | /* ================================================== */ | |
2520 | ||
2521 | int | |
8265ff28 | 2522 | NCR_CheckAccessRestriction(IPAddr *ip_addr) |
88840341 RC |
2523 | { |
2524 | return ADF_IsAllowed(access_auth_table, ip_addr); | |
2525 | } | |
2526 | ||
2527 | /* ================================================== */ | |
2528 | ||
88840341 RC |
2529 | void |
2530 | NCR_IncrementActivityCounters(NCR_Instance inst, int *online, int *offline, | |
2531 | int *burst_online, int *burst_offline) | |
2532 | { | |
2533 | switch (inst->opmode) { | |
2534 | case MD_BURST_WAS_OFFLINE: | |
2535 | ++*burst_offline; | |
2536 | break; | |
2537 | case MD_BURST_WAS_ONLINE: | |
2538 | ++*burst_online; | |
2539 | break; | |
2540 | case MD_ONLINE: | |
2541 | ++*online; | |
2542 | break; | |
2543 | case MD_OFFLINE: | |
2544 | ++*offline; | |
2545 | break; | |
2546 | default: | |
6b0198c2 | 2547 | assert(0); |
88840341 RC |
2548 | break; |
2549 | } | |
2550 | } | |
2551 | ||
2552 | /* ================================================== */ | |
48b6c2aa ML |
2553 | |
2554 | NTP_Remote_Address * | |
2555 | NCR_GetRemoteAddress(NCR_Instance inst) | |
2556 | { | |
2557 | return &inst->remote_addr; | |
2558 | } | |
2559 | ||
2560 | /* ================================================== */ | |
2ea87490 | 2561 | |
eb75ce7d ML |
2562 | uint32_t |
2563 | NCR_GetLocalRefid(NCR_Instance inst) | |
2564 | { | |
2565 | return UTI_IPToRefid(&inst->local_addr.ip_addr); | |
2566 | } | |
2567 | ||
2568 | /* ================================================== */ | |
2569 | ||
2ea87490 ML |
2570 | int NCR_IsSyncPeer(NCR_Instance inst) |
2571 | { | |
2572 | return SRC_IsSyncPeer(inst->source); | |
2573 | } | |
2574 | ||
2575 | /* ================================================== */ | |
a78bf0c3 | 2576 | |
d690faeb ML |
2577 | void |
2578 | NCR_DumpAuthData(NCR_Instance inst) | |
2579 | { | |
2580 | NAU_DumpData(inst->auth); | |
2581 | } | |
2582 | ||
2583 | /* ================================================== */ | |
2584 | ||
a78bf0c3 ML |
2585 | static void |
2586 | broadcast_timeout(void *arg) | |
2587 | { | |
2588 | BroadcastDestination *destination; | |
2589 | NTP_int64 orig_ts; | |
14c8f076 | 2590 | NTP_Local_Timestamp recv_ts; |
97d42033 | 2591 | int poll; |
a78bf0c3 ML |
2592 | |
2593 | destination = ARR_GetElement(broadcasts, (long)arg); | |
97d42033 | 2594 | poll = log(destination->interval) / log(2.0) + 0.5; |
a78bf0c3 | 2595 | |
6e9c0489 | 2596 | UTI_ZeroNtp64(&orig_ts); |
43cd119d | 2597 | zero_local_timestamp(&recv_ts); |
a78bf0c3 | 2598 | |
aca1daf7 | 2599 | transmit_packet(MODE_BROADCAST, 0, poll, NTP_VERSION, 0, destination->auth, |
ca28dbd2 ML |
2600 | &orig_ts, &orig_ts, &recv_ts, NULL, NULL, NULL, |
2601 | &destination->addr, &destination->local_addr, NULL, NULL); | |
a78bf0c3 ML |
2602 | |
2603 | /* Requeue timeout. We don't care if interval drifts gradually. */ | |
97d42033 | 2604 | SCH_AddTimeoutInClass(destination->interval, get_separation(poll), SAMPLING_RANDOMNESS, |
a78bf0c3 ML |
2605 | SCH_NtpBroadcastClass, broadcast_timeout, arg); |
2606 | } | |
2607 | ||
2608 | /* ================================================== */ | |
2609 | ||
2610 | void | |
500c9cbf | 2611 | NCR_AddBroadcastDestination(NTP_Remote_Address *addr, int interval) |
a78bf0c3 ML |
2612 | { |
2613 | BroadcastDestination *destination; | |
2614 | ||
2615 | destination = (BroadcastDestination *)ARR_GetNewElement(broadcasts); | |
2616 | ||
500c9cbf | 2617 | destination->addr = *addr; |
a78bf0c3 | 2618 | destination->local_addr.ip_addr.family = IPADDR_UNSPEC; |
86acea5c | 2619 | destination->local_addr.if_index = INVALID_IF_INDEX; |
6d1dda0f | 2620 | destination->local_addr.sock_fd = NIO_OpenServerSocket(&destination->addr); |
ca28dbd2 | 2621 | destination->auth = NAU_CreateNoneInstance(); |
beaaaad1 | 2622 | destination->interval = CLAMP(1, interval, 1 << MAX_POLL); |
a78bf0c3 | 2623 | |
97d42033 | 2624 | SCH_AddTimeoutInClass(destination->interval, MAX_SAMPLING_SEPARATION, SAMPLING_RANDOMNESS, |
a78bf0c3 ML |
2625 | SCH_NtpBroadcastClass, broadcast_timeout, |
2626 | (void *)(long)(ARR_GetSize(broadcasts) - 1)); | |
2627 | } |