]> git.ipfire.org Git - thirdparty/chrony.git/blame - ntp_sources.c
conf: rework allow/deny parser
[thirdparty/chrony.git] / ntp_sources.c
CommitLineData
88840341 1/*
88840341
RC
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
6672f045 5 * Copyright (C) Richard P. Curnow 1997-2003
883b7eed 6 * Copyright (C) Miroslav Lichvar 2011-2012, 2014, 2016, 2020-2021
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 Functions which manage the pool of NTP sources that we are currently
26 a client of or peering with.
27
28 */
29
da2c8d90
ML
30#include "config.h"
31
88840341
RC
32#include "sysincl.h"
33
9e71932c 34#include "array.h"
88840341
RC
35#include "ntp_sources.h"
36#include "ntp_core.h"
5a09adeb 37#include "ntp_io.h"
88840341
RC
38#include "util.h"
39#include "logging.h"
40#include "local.h"
aa91c608 41#include "memory.h"
6ee357d2 42#include "nameserv_async.h"
6db8ec1b 43#include "privops.h"
aa91c608 44#include "sched.h"
88840341
RC
45
46/* ================================================== */
47
4d139eec
ML
48/* Maximum number of sources */
49#define MAX_SOURCES 65536
50
88840341
RC
51/* Record type private to this file, used to store information about
52 particular sources */
53typedef struct {
48b6c2aa 54 NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
d7e3ad17
ML
55 means this slot in table is in use
56 (an IPADDR_ID address means the address
57 is not resolved yet) */
88840341 58 NCR_Instance data; /* Data for the protocol engine for this source */
eb9e6701
ML
59 char *name; /* Name of the source as it was specified
60 (may be an IP address) */
d274fe44 61 int pool_id; /* ID of the pool from which was this source
c743ecbf 62 added or INVALID_POOL */
308bcae2 63 int tentative; /* Flag indicating there was no valid response
62e66bda 64 received from the source yet */
951f14ae
ML
65 uint32_t conf_id; /* Configuration ID, which can be shared with
66 different sources in case of a pool */
88840341
RC
67} SourceRecord;
68
beaf2752
ML
69/* Hash table of SourceRecord, its size is a power of two and it's never
70 more than half full */
9e71932c 71static ARR_Instance records;
88840341 72
9e71932c 73/* Number of sources in the hash table */
88840341
RC
74static int n_sources;
75
779e40ed
ML
76/* Flag indicating new sources will be started automatically when added */
77static int auto_start_sources = 0;
78
2e52aca3
ML
79/* Flag indicating a record is currently being modified */
80static int record_lock;
81
d7e3ad17
ML
82/* Last assigned address ID */
83static uint32_t last_address_id = 0;
84
951f14ae
ML
85/* Last assigned configuration ID */
86static uint32_t last_conf_id = 0;
87
d7e3ad17 88/* Source scheduled for name resolving (first resolving or replacement) */
aa91c608 89struct UnresolvedSource {
8c75f446
ML
90 /* Current address of the source (IPADDR_ID is used for a single source
91 with unknown address and IPADDR_UNSPEC for a pool of sources) */
d7e3ad17
ML
92 NTP_Remote_Address address;
93 /* ID of the pool if not a single source */
d274fe44 94 int pool_id;
d7e3ad17 95 /* Name to be resolved */
aa91c608 96 char *name;
d7e3ad17 97 /* Flag indicating addresses should be used in a random order */
dec1d2bf 98 int random_order;
d7e3ad17 99 /* Next unresolved source in the list */
aa91c608
ML
100 struct UnresolvedSource *next;
101};
102
9b137b2e
ML
103#define RESOLVE_INTERVAL_UNIT 7
104#define MIN_RESOLVE_INTERVAL 2
105#define MAX_RESOLVE_INTERVAL 9
3c06e57f 106#define MIN_REPLACEMENT_INTERVAL 8
9b137b2e 107
aa91c608
ML
108static struct UnresolvedSource *unresolved_sources = NULL;
109static int resolving_interval = 0;
dc22df93 110static int resolving_restart = 0;
aa91c608 111static SCH_TimeoutID resolving_id;
6ee357d2
ML
112static struct UnresolvedSource *resolving_source = NULL;
113static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
aa91c608 114
c743ecbf
ML
115#define MAX_POOL_SOURCES 16
116#define INVALID_POOL (-1)
117
e949cf59 118/* Pool of sources with the same name */
c743ecbf 119struct SourcePool {
8c256323 120 /* Number of all sources from the pool */
308bcae2 121 int sources;
8c256323
ML
122 /* Number of sources with unresolved address */
123 int unresolved_sources;
124 /* Number of non-tentative sources */
125 int confirmed_sources;
126 /* Maximum number of confirmed sources */
308bcae2 127 int max_sources;
c743ecbf
ML
128};
129
d274fe44 130/* Array of SourcePool (indexed by their ID) */
c743ecbf
ML
131static ARR_Instance pools;
132
2e52aca3
ML
133/* Requested update of a source's address */
134struct AddressUpdate {
135 NTP_Remote_Address old_address;
136 NTP_Remote_Address new_address;
137};
138
139/* Update saved when record_lock is true */
140static struct AddressUpdate saved_address_update;
141
88840341
RC
142/* ================================================== */
143/* Forward prototypes */
6ee357d2 144
2507b666 145static void resolve_sources(void);
9e71932c 146static void rehash_records(void);
2e52aca3 147static void handle_saved_address_update(void);
e949cf59 148static void clean_source_record(SourceRecord *record);
d274fe44 149static void remove_pool_sources(int pool_id, int tentative, int unresolved);
8c256323 150static void remove_unresolved_source(struct UnresolvedSource *us);
6ee357d2 151
88840341 152static void
d0dfa1de
ML
153slew_sources(struct timespec *raw,
154 struct timespec *cooked,
88840341 155 double dfreq,
88840341 156 double doffset,
44c9744d 157 LCL_ChangeType change_type,
88840341
RC
158 void *anything);
159
160/* ================================================== */
161
162/* Flag indicating whether module is initialised */
163static int initialised = 0;
164
165/* ================================================== */
166
9e71932c
ML
167static SourceRecord *
168get_record(unsigned index)
169{
170 return (SourceRecord *)ARR_GetElement(records, index);
171}
172
173/* ================================================== */
174
8c256323
ML
175static struct SourcePool *
176get_pool(unsigned index)
177{
178 return (struct SourcePool *)ARR_GetElement(pools, index);
179}
180
181/* ================================================== */
182
88840341
RC
183void
184NSR_Initialise(void)
185{
88840341
RC
186 n_sources = 0;
187 initialised = 1;
188
9e71932c
ML
189 records = ARR_CreateInstance(sizeof (SourceRecord));
190 rehash_records();
191
c743ecbf
ML
192 pools = ARR_CreateInstance(sizeof (struct SourcePool));
193
88840341 194 LCL_AddParameterChangeHandler(slew_sources, NULL);
88840341
RC
195}
196
197/* ================================================== */
198
199void
200NSR_Finalise(void)
201{
27641876 202 NSR_RemoveAllSources();
f6ed7844 203
5f6f265f
ML
204 LCL_RemoveParameterChangeHandler(slew_sources, NULL);
205
9e71932c 206 ARR_DestroyInstance(records);
8c256323 207 ARR_DestroyInstance(pools);
9e71932c 208
8c256323
ML
209 while (unresolved_sources)
210 remove_unresolved_source(unresolved_sources);
f6ed7844 211
88840341 212 initialised = 0;
88840341
RC
213}
214
215/* ================================================== */
fb4c3f31
ML
216/* Find a slot matching an IP address. It is assumed that there can
217 only ever be one record for a particular IP address. */
88840341 218
fb4c3f31
ML
219static int
220find_slot(IPAddr *ip_addr, int *slot)
88840341 221{
9e71932c 222 SourceRecord *record;
4e0df8c2
ML
223 uint32_t hash;
224 unsigned int i, size;
88840341 225
9e71932c 226 size = ARR_GetSize(records);
02de782f
ML
227
228 *slot = 0;
88840341 229
fb4c3f31
ML
230 switch (ip_addr->family) {
231 case IPADDR_INET4:
232 case IPADDR_INET6:
233 case IPADDR_ID:
234 break;
235 default:
236 return 0;
237 }
8265ff28 238
fb4c3f31 239 hash = UTI_IPToHash(ip_addr);
88840341 240
4e0df8c2
ML
241 for (i = 0; i < size / 2; i++) {
242 /* Use quadratic probing */
243 *slot = (hash + (i + i * i) / 2) % size;
9e71932c 244 record = get_record(*slot);
4e0df8c2 245
9e71932c 246 if (!record->remote_addr)
4e0df8c2
ML
247 break;
248
fb4c3f31
ML
249 if (UTI_CompareIPs(&record->remote_addr->ip_addr, ip_addr, NULL) == 0)
250 return 1;
88840341 251 }
fb4c3f31
ML
252
253 return 0;
254}
255
256/* ================================================== */
257/* Find a slot matching an IP address and port. The function returns:
3fc72c0c 258 0 => IP not matched, empty slot returned if a valid address was provided
fb4c3f31
ML
259 1 => Only IP matched, port doesn't match
260 2 => Both IP and port matched. */
261
262static int
263find_slot2(NTP_Remote_Address *remote_addr, int *slot)
264{
265 if (!find_slot(&remote_addr->ip_addr, slot))
266 return 0;
267
268 return get_record(*slot)->remote_addr->port == remote_addr->port ? 2 : 1;
88840341
RC
269}
270
271/* ================================================== */
9e71932c 272/* Check if hash table of given size is sufficient to contain sources */
beaf2752 273
9e71932c
ML
274static int
275check_hashtable_size(unsigned int sources, unsigned int size)
276{
beaf2752 277 return sources * 2 <= size;
9e71932c
ML
278}
279
280/* ================================================== */
281
282static void
283rehash_records(void)
284{
c743ecbf 285 SourceRecord *temp_records;
9e71932c 286 unsigned int i, old_size, new_size;
fb4c3f31 287 int slot;
9e71932c 288
2e52aca3
ML
289 assert(!record_lock);
290
9e71932c
ML
291 old_size = ARR_GetSize(records);
292
293 temp_records = MallocArray(SourceRecord, old_size);
294 memcpy(temp_records, ARR_GetElements(records), old_size * sizeof (SourceRecord));
295
296 /* The size of the hash table is always a power of two */
beaf2752 297 for (new_size = 1; !check_hashtable_size(n_sources, new_size); new_size *= 2)
9e71932c
ML
298 ;
299
300 ARR_SetSize(records, new_size);
301
302 for (i = 0; i < new_size; i++)
303 get_record(i)->remote_addr = NULL;
304
305 for (i = 0; i < old_size; i++) {
306 if (!temp_records[i].remote_addr)
307 continue;
308
fb4c3f31
ML
309 if (find_slot2(temp_records[i].remote_addr, &slot) != 0)
310 assert(0);
9e71932c 311
c743ecbf 312 *get_record(slot) = temp_records[i];
9e71932c
ML
313 }
314
315 Free(temp_records);
316}
317
318/* ================================================== */
319
2458325c 320/* Procedure to add a new source */
c743ecbf 321static NSR_Status
951f14ae 322add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
d274fe44 323 SourceParameters *params, int pool_id, uint32_t conf_id)
88840341 324{
9e71932c 325 SourceRecord *record;
fb4c3f31 326 int slot;
88840341
RC
327
328 assert(initialised);
329
88840341 330 /* Find empty bin & check that we don't have the address already */
fb4c3f31 331 if (find_slot2(remote_addr, &slot) != 0) {
88840341 332 return NSR_AlreadyInUse;
eb9e6701
ML
333 } else if (!name && !UTI_IsIPReal(&remote_addr->ip_addr)) {
334 /* Name is required for non-real addresses */
335 return NSR_InvalidName;
4d139eec
ML
336 } else if (n_sources >= MAX_SOURCES) {
337 return NSR_TooManySources;
88840341 338 } else {
9e71932c 339 if (remote_addr->ip_addr.family != IPADDR_INET4 &&
d7e3ad17
ML
340 remote_addr->ip_addr.family != IPADDR_INET6 &&
341 remote_addr->ip_addr.family != IPADDR_ID) {
8265ff28 342 return NSR_InvalidAF;
88840341
RC
343 } else {
344 n_sources++;
9e71932c
ML
345
346 if (!check_hashtable_size(n_sources, ARR_GetSize(records))) {
347 rehash_records();
fb4c3f31
ML
348 if (find_slot2(remote_addr, &slot) != 0)
349 assert(0);
9e71932c
ML
350 }
351
2e52aca3
ML
352 assert(!record_lock);
353 record_lock = 1;
354
9e71932c 355 record = get_record(slot);
eb9e6701
ML
356 assert(!name || !UTI_IsStringIP(name));
357 record->name = Strdup(name ? name : UTI_IPToString(&remote_addr->ip_addr));
358 record->data = NCR_CreateInstance(remote_addr, type, params, record->name);
9e71932c 359 record->remote_addr = NCR_GetRemoteAddress(record->data);
d274fe44 360 record->pool_id = pool_id;
62e66bda 361 record->tentative = 1;
951f14ae 362 record->conf_id = conf_id;
9e71932c 363
2e52aca3
ML
364 record_lock = 0;
365
d274fe44
ML
366 if (record->pool_id != INVALID_POOL) {
367 get_pool(record->pool_id)->sources++;
8c256323 368 if (!UTI_IsIPReal(&remote_addr->ip_addr))
d274fe44 369 get_pool(record->pool_id)->unresolved_sources++;
8c256323
ML
370 }
371
d7e3ad17 372 if (auto_start_sources && UTI_IsIPReal(&remote_addr->ip_addr))
9e71932c
ML
373 NCR_StartInstance(record->data);
374
2e52aca3
ML
375 /* The new instance is allowed to change its address immediately */
376 handle_saved_address_update();
377
88840341
RC
378 return NSR_Success;
379 }
380 }
381}
382
383/* ================================================== */
384
c743ecbf 385static NSR_Status
e8062b7f
ML
386change_source_address(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr,
387 int replacement)
c743ecbf
ML
388{
389 int slot1, slot2, found;
390 SourceRecord *record;
d7e3ad17 391 LOG_Severity severity;
2ae008bc 392 char *name;
c743ecbf 393
fb4c3f31 394 found = find_slot2(old_addr, &slot1);
b0fc5832 395 if (found != 2)
c743ecbf
ML
396 return NSR_NoSuchSource;
397
9468fd4a
ML
398 /* Make sure there is no other source using the new address (with the same
399 or different port), but allow a source to have its port changed */
fb4c3f31 400 found = find_slot2(new_addr, &slot2);
9468fd4a 401 if (found == 2 || (found != 0 && slot1 != slot2))
c743ecbf
ML
402 return NSR_AlreadyInUse;
403
2e52aca3
ML
404 assert(!record_lock);
405 record_lock = 1;
406
c743ecbf 407 record = get_record(slot1);
e8062b7f 408 NCR_ChangeRemoteAddress(record->data, new_addr, !replacement);
2e52aca3
ML
409
410 if (record->remote_addr != NCR_GetRemoteAddress(record->data) ||
411 UTI_CompareIPs(&record->remote_addr->ip_addr, &new_addr->ip_addr, NULL) != 0)
412 assert(0);
413
8c256323
ML
414 if (!UTI_IsIPReal(&old_addr->ip_addr) && UTI_IsIPReal(&new_addr->ip_addr)) {
415 if (auto_start_sources)
416 NCR_StartInstance(record->data);
d274fe44
ML
417 if (record->pool_id != INVALID_POOL)
418 get_pool(record->pool_id)->unresolved_sources--;
8c256323 419 }
c743ecbf 420
62e66bda
ML
421 if (!record->tentative) {
422 record->tentative = 1;
423
d274fe44
ML
424 if (record->pool_id != INVALID_POOL)
425 get_pool(record->pool_id)->confirmed_sources--;
62e66bda
ML
426 }
427
2e52aca3
ML
428 record_lock = 0;
429
2ae008bc 430 name = record->name;
d7e3ad17
ML
431 severity = UTI_IsIPReal(&old_addr->ip_addr) ? LOGS_INFO : LOGS_DEBUG;
432
a608496f 433 if (found == 0) {
9468fd4a
ML
434 /* The hash table must be rebuilt for the changed address */
435 rehash_records();
436
e8062b7f
ML
437 LOG(severity, "Source %s %s %s (%s)", UTI_IPToString(&old_addr->ip_addr),
438 replacement ? "replaced with" : "changed to",
eb9e6701 439 UTI_IPToString(&new_addr->ip_addr), name);
9468fd4a
ML
440 } else {
441 LOG(severity, "Source %s (%s) changed port to %d",
eb9e6701 442 UTI_IPToString(&new_addr->ip_addr), name, new_addr->port);
9468fd4a 443 }
c743ecbf
ML
444
445 return NSR_Success;
446}
447
448/* ================================================== */
449
2e52aca3
ML
450static void
451handle_saved_address_update(void)
452{
453 if (!UTI_IsIPReal(&saved_address_update.old_address.ip_addr))
454 return;
455
456 if (change_source_address(&saved_address_update.old_address,
457 &saved_address_update.new_address, 0) != NSR_Success)
458 /* This is expected to happen only if the old address is wrong */
459 LOG(LOGS_ERR, "Could not change %s to %s",
460 UTI_IPSockAddrToString(&saved_address_update.old_address),
d9b72047 461 UTI_IPSockAddrToString(&saved_address_update.new_address));
2e52aca3
ML
462
463 saved_address_update.old_address.ip_addr.family = IPADDR_UNSPEC;
464}
465
466/* ================================================== */
467
5a09adeb
ML
468static int
469replace_source_connectable(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
470{
471 if (!NIO_IsServerConnectable(new_addr)) {
472 DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip_addr));
473 return 0;
474 }
475
e8062b7f 476 if (change_source_address(old_addr, new_addr, 1) == NSR_AlreadyInUse)
5a09adeb
ML
477 return 0;
478
2e52aca3
ML
479 handle_saved_address_update();
480
5a09adeb
ML
481 return 1;
482}
483
484/* ================================================== */
485
40f85912
ML
486static void
487process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs)
488{
d7e3ad17
ML
489 NTP_Remote_Address old_addr, new_addr;
490 SourceRecord *record;
dec1d2bf 491 unsigned short first = 0;
d7e3ad17 492 int i, j;
40f85912 493
dec1d2bf
ML
494 if (us->random_order)
495 UTI_GetRandomBytes(&first, sizeof (first));
40f85912 496
d7e3ad17
ML
497 for (i = 0; i < n_addrs; i++) {
498 new_addr.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs];
40f85912 499
d7e3ad17 500 DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
dec1d2bf 501
d274fe44 502 if (us->pool_id != INVALID_POOL) {
f3aea33a
ML
503 /* In the pool resolving mode, try to replace a source from
504 the pool which does not have a real address yet */
d7e3ad17
ML
505 for (j = 0; j < ARR_GetSize(records); j++) {
506 record = get_record(j);
d274fe44 507 if (!record->remote_addr || record->pool_id != us->pool_id ||
d7e3ad17
ML
508 UTI_IsIPReal(&record->remote_addr->ip_addr))
509 continue;
510 old_addr = *record->remote_addr;
511 new_addr.port = old_addr.port;
5a09adeb 512 if (replace_source_connectable(&old_addr, &new_addr))
f3aea33a
ML
513 ;
514 break;
d7e3ad17 515 }
c743ecbf 516 } else {
d7e3ad17 517 new_addr.port = us->address.port;
5a09adeb 518 if (replace_source_connectable(&us->address, &new_addr))
c743ecbf
ML
519 break;
520 }
40f85912
ML
521 }
522}
523
524/* ================================================== */
525
8c256323
ML
526static int
527is_resolved(struct UnresolvedSource *us)
528{
fb4c3f31 529 int slot;
8c256323 530
d274fe44
ML
531 if (us->pool_id != INVALID_POOL) {
532 return get_pool(us->pool_id)->unresolved_sources <= 0;
8c256323
ML
533 } else {
534 /* If the address is no longer present, it was removed or replaced
535 (i.e. resolved) */
fb4c3f31 536 return find_slot2(&us->address, &slot) == 0;
8c256323
ML
537 }
538}
539
540/* ================================================== */
541
2507b666
ML
542static void
543resolve_sources_timeout(void *arg)
544{
545 resolving_id = 0;
546 resolve_sources();
547}
548
549/* ================================================== */
550
aa91c608 551static void
4d1a754e 552name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything)
aa91c608 553{
8c256323 554 struct UnresolvedSource *us, *next;
aa91c608 555
6ee357d2
ML
556 us = (struct UnresolvedSource *)anything;
557
558 assert(us == resolving_source);
2507b666 559 assert(resolving_id == 0);
aa91c608 560
f282856c 561 DEBUG_LOG("%s resolved to %d addrs", us->name, n_addrs);
8de04a80 562
6ee357d2
ML
563 switch (status) {
564 case DNS_TryAgain:
565 break;
566 case DNS_Success:
40f85912 567 process_resolved_name(us, ip_addrs, n_addrs);
6ee357d2
ML
568 break;
569 case DNS_Failure:
f282856c 570 LOG(LOGS_WARN, "Invalid host %s", us->name);
6ee357d2
ML
571 break;
572 default:
573 assert(0);
574 }
aa91c608 575
6ee357d2
ML
576 next = us->next;
577
9d1c1505 578 /* Don't repeat the resolving if it (permanently) failed, it was a
8c256323 579 replacement of a real address, or all addresses are already resolved */
9d1c1505 580 if (status == DNS_Failure || UTI_IsIPReal(&us->address.ip_addr) || is_resolved(us))
8c256323 581 remove_unresolved_source(us);
aa91c608 582
dc22df93
ML
583 /* If a restart was requested and this was the last source in the list,
584 start with the first source again (if there still is one) */
585 if (!next && resolving_restart) {
586 next = unresolved_sources;
587 resolving_restart = 0;
588 }
589
6ee357d2
ML
590 resolving_source = next;
591
592 if (next) {
593 /* Continue with the next source in the list */
f282856c 594 DEBUG_LOG("resolving %s", next->name);
6ee357d2 595 DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next);
aa91c608 596 } else {
6ee357d2
ML
597 /* This was the last source in the list. If some sources couldn't
598 be resolved, try again in exponentially increasing interval. */
599 if (unresolved_sources) {
2507b666
ML
600 resolving_interval = CLAMP(MIN_RESOLVE_INTERVAL, resolving_interval + 1,
601 MAX_RESOLVE_INTERVAL);
602 resolving_id = SCH_AddTimeoutByDelay(RESOLVE_INTERVAL_UNIT * (1 << resolving_interval),
603 resolve_sources_timeout, NULL);
6ee357d2
ML
604 } else {
605 resolving_interval = 0;
606 }
607
608 /* This round of resolving is done */
609 if (resolving_end_handler)
610 (resolving_end_handler)();
aa91c608
ML
611 }
612}
613
614/* ================================================== */
615
6ee357d2 616static void
2507b666 617resolve_sources(void)
6ee357d2 618{
8c256323 619 struct UnresolvedSource *us, *next, *i;
6ee357d2
ML
620
621 assert(!resolving_source);
622
8c256323
ML
623 /* Remove sources that don't need to be resolved anymore */
624 for (i = unresolved_sources; i; i = next) {
625 next = i->next;
626 if (is_resolved(i))
627 remove_unresolved_source(i);
628 }
629
630 if (!unresolved_sources)
631 return;
632
6db8ec1b 633 PRV_ReloadDNS();
6ee357d2
ML
634
635 /* Start with the first source in the list, name_resolve_handler
636 will iterate over the rest */
637 us = unresolved_sources;
638
639 resolving_source = us;
f282856c 640 DEBUG_LOG("resolving %s", us->name);
6ee357d2
ML
641 DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us);
642}
643
644/* ================================================== */
645
c743ecbf
ML
646static void
647append_unresolved_source(struct UnresolvedSource *us)
648{
649 struct UnresolvedSource **i;
650
651 for (i = &unresolved_sources; *i; i = &(*i)->next)
652 ;
653 *i = us;
654 us->next = NULL;
655}
656
657/* ================================================== */
658
8c256323
ML
659static void
660remove_unresolved_source(struct UnresolvedSource *us)
661{
662 struct UnresolvedSource **i;
663
664 for (i = &unresolved_sources; *i; i = &(*i)->next) {
665 if (*i == us) {
666 *i = us->next;
667 Free(us->name);
668 Free(us);
669 break;
670 }
671 }
672}
673
674/* ================================================== */
675
0a63ad95
ML
676static int get_unused_pool_id(void)
677{
678 struct UnresolvedSource *us;
679 int i;
680
681 for (i = 0; i < ARR_GetSize(pools); i++) {
682 if (get_pool(i)->sources > 0)
683 continue;
684
685 /* Make sure there is no name waiting to be resolved using this pool */
686 for (us = unresolved_sources; us; us = us->next) {
687 if (us->pool_id == i)
688 break;
689 }
690 if (us)
691 continue;
692
693 return i;
694 }
695
696 return INVALID_POOL;
697}
698
699/* ================================================== */
700
c743ecbf 701NSR_Status
951f14ae
ML
702NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
703 SourceParameters *params, uint32_t *conf_id)
c743ecbf 704{
951f14ae
ML
705 NSR_Status s;
706
707 s = add_source(remote_addr, NULL, type, params, INVALID_POOL, last_conf_id + 1);
708 if (s != NSR_Success)
709 return s;
710
711 last_conf_id++;
712 if (conf_id)
713 *conf_id = last_conf_id;
714
715 return s;
c743ecbf
ML
716}
717
718/* ================================================== */
719
3763befd 720NSR_Status
951f14ae
ML
721NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
722 SourceParameters *params, uint32_t *conf_id)
aa91c608 723{
c743ecbf
ML
724 struct UnresolvedSource *us;
725 struct SourcePool *sp;
4eeaf342 726 NTP_Remote_Address remote_addr;
0a63ad95 727 int i, new_sources, pool_id;
4eeaf342 728
eb9e6701 729 /* If the name is an IP address, add the source with the address directly */
4eeaf342
ML
730 if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
731 remote_addr.port = port;
951f14ae 732 return NSR_AddSource(&remote_addr, type, params, conf_id);
3763befd
ML
733 }
734
735 /* Make sure the name is at least printable and has no spaces */
736 for (i = 0; name[i] != '\0'; i++) {
48709d9c 737 if (!isgraph((unsigned char)name[i]))
3763befd 738 return NSR_InvalidName;
4eeaf342 739 }
aa91c608
ML
740
741 us = MallocNew(struct UnresolvedSource);
c743ecbf 742 us->name = Strdup(name);
dec1d2bf 743 us->random_order = 0;
d7e3ad17
ML
744
745 remote_addr.ip_addr.family = IPADDR_ID;
746 remote_addr.ip_addr.addr.id = ++last_address_id;
747 remote_addr.port = port;
aa91c608 748
c743ecbf 749 if (!pool) {
d274fe44 750 us->pool_id = INVALID_POOL;
d7e3ad17
ML
751 us->address = remote_addr;
752 new_sources = 1;
c743ecbf 753 } else {
0a63ad95
ML
754 pool_id = get_unused_pool_id();
755 if (pool_id != INVALID_POOL) {
756 sp = get_pool(pool_id);
757 } else {
758 sp = ARR_GetNewElement(pools);
759 pool_id = ARR_GetSize(pools) - 1;
760 }
761
308bcae2 762 sp->sources = 0;
8c256323
ML
763 sp->unresolved_sources = 0;
764 sp->confirmed_sources = 0;
d7e3ad17 765 sp->max_sources = CLAMP(1, params->max_sources, MAX_POOL_SOURCES);
0a63ad95 766 us->pool_id = pool_id;
d7e3ad17
ML
767 us->address.ip_addr.family = IPADDR_UNSPEC;
768 new_sources = MIN(2 * sp->max_sources, MAX_POOL_SOURCES);
c743ecbf
ML
769 }
770
771 append_unresolved_source(us);
3763befd 772
951f14ae
ML
773 last_conf_id++;
774 if (conf_id)
775 *conf_id = last_conf_id;
776
d7e3ad17
ML
777 for (i = 0; i < new_sources; i++) {
778 if (i > 0)
779 remote_addr.ip_addr.addr.id = ++last_address_id;
d274fe44 780 if (add_source(&remote_addr, name, type, params, us->pool_id, last_conf_id) != NSR_Success)
d7e3ad17
ML
781 return NSR_TooManySources;
782 }
783
3763befd 784 return NSR_UnresolvedName;
aa91c608
ML
785}
786
787/* ================================================== */
788
6ee357d2
ML
789void
790NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
791{
792 resolving_end_handler = handler;
793}
794
795/* ================================================== */
796
7fb50d9a
ML
797void
798NSR_ResolveSources(void)
799{
800 /* Try to resolve unresolved sources now */
6ee357d2 801 if (unresolved_sources) {
dc22df93 802 /* Allow only one resolving to be running at a time */
6ee357d2 803 if (!resolving_source) {
2507b666 804 if (resolving_id != 0) {
6ee357d2 805 SCH_RemoveTimeout(resolving_id);
2507b666 806 resolving_id = 0;
6ee357d2
ML
807 resolving_interval--;
808 }
2507b666 809 resolve_sources();
dc22df93
ML
810 } else {
811 /* Try again as soon as the current resolving ends */
812 resolving_restart = 1;
6ee357d2
ML
813 }
814 } else {
815 /* No unresolved sources, we are done */
816 if (resolving_end_handler)
817 (resolving_end_handler)();
7fb50d9a
ML
818 }
819}
820
821/* ================================================== */
822
779e40ed
ML
823void NSR_StartSources(void)
824{
d7e3ad17 825 NTP_Remote_Address *addr;
9e71932c 826 unsigned int i;
779e40ed 827
9e71932c 828 for (i = 0; i < ARR_GetSize(records); i++) {
d7e3ad17
ML
829 addr = get_record(i)->remote_addr;
830 if (!addr || !UTI_IsIPReal(&addr->ip_addr))
779e40ed 831 continue;
9e71932c 832 NCR_StartInstance(get_record(i)->data);
779e40ed
ML
833 }
834}
835
836/* ================================================== */
837
838void NSR_AutoStartSources(void)
839{
840 auto_start_sources = 1;
841}
842
843/* ================================================== */
844
f2c80cae
ML
845static void
846clean_source_record(SourceRecord *record)
847{
848 assert(record->remote_addr);
8c256323 849
d274fe44
ML
850 if (record->pool_id != INVALID_POOL) {
851 struct SourcePool *pool = get_pool(record->pool_id);
8c256323
ML
852
853 pool->sources--;
854 if (!UTI_IsIPReal(&record->remote_addr->ip_addr))
855 pool->unresolved_sources--;
856 if (!record->tentative)
857 pool->confirmed_sources--;
858 if (pool->max_sources > pool->sources)
859 pool->max_sources = pool->sources;
860 }
861
f2c80cae
ML
862 record->remote_addr = NULL;
863 NCR_DestroyInstance(record->data);
eb9e6701 864 Free(record->name);
f2c80cae
ML
865
866 n_sources--;
867}
868
869/* ================================================== */
870
88840341
RC
871/* Procedure to remove a source. We don't bother whether the port
872 address is matched - we're only interested in removing a record for
14542306 873 the right IP address. */
88840341 874NSR_Status
14542306 875NSR_RemoveSource(IPAddr *address)
88840341 876{
fb4c3f31 877 int slot;
88840341
RC
878
879 assert(initialised);
880
14542306 881 if (find_slot(address, &slot) == 0)
88840341 882 return NSR_NoSuchSource;
5fb0a9d5 883
f2c80cae 884 clean_source_record(get_record(slot));
5fb0a9d5
ML
885
886 /* Rehash the table to make sure there are no broken probe sequences.
887 This is costly, but it's not expected to happen frequently. */
888
9e71932c 889 rehash_records();
5fb0a9d5
ML
890
891 return NSR_Success;
88840341
RC
892}
893
894/* ================================================== */
895
951f14ae
ML
896void
897NSR_RemoveSourcesById(uint32_t conf_id)
898{
899 SourceRecord *record;
900 unsigned int i;
901
902 for (i = 0; i < ARR_GetSize(records); i++) {
903 record = get_record(i);
904 if (!record->remote_addr || record->conf_id != conf_id)
905 continue;
906 clean_source_record(record);
907 }
908
909 rehash_records();
910}
911
912/* ================================================== */
913
7fda9c67
ML
914void
915NSR_RemoveAllSources(void)
916{
9e71932c
ML
917 SourceRecord *record;
918 unsigned int i;
7fda9c67 919
9e71932c
ML
920 for (i = 0; i < ARR_GetSize(records); i++) {
921 record = get_record(i);
922 if (!record->remote_addr)
7fda9c67 923 continue;
f2c80cae 924 clean_source_record(record);
7fda9c67 925 }
f2c80cae
ML
926
927 rehash_records();
7fda9c67
ML
928}
929
930/* ================================================== */
931
c743ecbf 932static void
e949cf59 933resolve_source_replacement(SourceRecord *record)
c743ecbf
ML
934{
935 struct UnresolvedSource *us;
936
eb9e6701
ML
937 DEBUG_LOG("trying to replace %s (%s)",
938 UTI_IPToString(&record->remote_addr->ip_addr), record->name);
e949cf59 939
c743ecbf 940 us = MallocNew(struct UnresolvedSource);
e949cf59 941 us->name = Strdup(record->name);
dec1d2bf
ML
942 /* If there never was a valid reply from this source (e.g. it was a bad
943 replacement), ignore the order of addresses from the resolver to not get
944 stuck to a pair of addresses if the order doesn't change, or a group of
945 IPv4/IPv6 addresses if the resolver prefers inaccessible IP family */
946 us->random_order = record->tentative;
d274fe44 947 us->pool_id = INVALID_POOL;
d7e3ad17 948 us->address = *record->remote_addr;
c743ecbf
ML
949
950 append_unresolved_source(us);
951 NSR_ResolveSources();
952}
953
954/* ================================================== */
955
956void
957NSR_HandleBadSource(IPAddr *address)
958{
d0dfa1de
ML
959 static struct timespec last_replacement;
960 struct timespec now;
e949cf59 961 SourceRecord *record;
eb9e6701 962 IPAddr ip_addr;
c743ecbf 963 double diff;
fb4c3f31 964 int slot;
c743ecbf 965
fb4c3f31 966 if (!find_slot(address, &slot))
c743ecbf
ML
967 return;
968
e949cf59 969 record = get_record(slot);
c743ecbf 970
eb9e6701
ML
971 /* Don't try to replace a source specified by an IP address unless the
972 address changed since the source was added (e.g. by NTS-KE) */
973 if (UTI_StringToIP(record->name, &ip_addr) &&
974 UTI_CompareIPs(&record->remote_addr->ip_addr, &ip_addr, NULL) == 0)
e949cf59
ML
975 return;
976
977 /* Don't resolve names too frequently */
c743ecbf 978 SCH_GetLastEventTime(NULL, NULL, &now);
cfe706f0 979 diff = UTI_DiffTimespecsToDouble(&now, &last_replacement);
e949cf59 980 if (fabs(diff) < RESOLVE_INTERVAL_UNIT * (1 << MIN_REPLACEMENT_INTERVAL)) {
f282856c 981 DEBUG_LOG("replacement postponed");
c743ecbf
ML
982 return;
983 }
984 last_replacement = now;
985
e949cf59 986 resolve_source_replacement(record);
c743ecbf
ML
987}
988
989/* ================================================== */
990
3eb43f46
GP
991void
992NSR_RefreshAddresses(void)
993{
994 SourceRecord *record;
995 unsigned int i;
996
997 for (i = 0; i < ARR_GetSize(records); i++) {
998 record = get_record(i);
eb9e6701 999 if (!record->remote_addr)
3eb43f46
GP
1000 continue;
1001
1002 resolve_source_replacement(record);
1003 }
1004}
1005
1006/* ================================================== */
1007
e8062b7f
ML
1008NSR_Status
1009NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
1010{
2e52aca3
ML
1011 int slot;
1012
1013 if (!UTI_IsIPReal(&old_addr->ip_addr) || !UTI_IsIPReal(&new_addr->ip_addr))
e8062b7f
ML
1014 return NSR_InvalidAF;
1015
2e52aca3
ML
1016 if (UTI_CompareIPs(&old_addr->ip_addr, &new_addr->ip_addr, NULL) != 0 &&
1017 find_slot(&new_addr->ip_addr, &slot))
1018 return NSR_AlreadyInUse;
1019
1020 /* If a record is being modified (e.g. by change_source_address(), or the
1021 source is just being created), postpone the change to avoid corruption */
1022
1023 if (!record_lock)
1024 return change_source_address(old_addr, new_addr, 0);
1025
1026 if (UTI_IsIPReal(&saved_address_update.old_address.ip_addr))
1027 return NSR_TooManySources;
1028
1029 saved_address_update.old_address = *old_addr;
1030 saved_address_update.new_address = *new_addr;
1031
1032 return NSR_Success;
e8062b7f
ML
1033}
1034
1035/* ================================================== */
1036
d274fe44 1037static void remove_pool_sources(int pool_id, int tentative, int unresolved)
308bcae2
ML
1038{
1039 SourceRecord *record;
1040 unsigned int i, removed;
1041
1042 for (i = removed = 0; i < ARR_GetSize(records); i++) {
1043 record = get_record(i);
1044
d274fe44 1045 if (!record->remote_addr || record->pool_id != pool_id)
d7e3ad17
ML
1046 continue;
1047
1048 if ((tentative && !record->tentative) ||
1049 (unresolved && UTI_IsIPReal(&record->remote_addr->ip_addr)))
308bcae2
ML
1050 continue;
1051
d7e3ad17 1052 DEBUG_LOG("removing %ssource %s", tentative ? "tentative " : "",
308bcae2
ML
1053 UTI_IPToString(&record->remote_addr->ip_addr));
1054
1055 clean_source_record(record);
1056 removed++;
1057 }
1058
1059 if (removed)
1060 rehash_records();
1061}
1062
eb75ce7d
ML
1063/* ================================================== */
1064
1065uint32_t
1066NSR_GetLocalRefid(IPAddr *address)
1067{
fb4c3f31 1068 int slot;
eb75ce7d 1069
fb4c3f31 1070 if (!find_slot(address, &slot))
eb75ce7d
ML
1071 return 0;
1072
1073 return NCR_GetLocalRefid(get_record(slot)->data);
1074}
1075
1076/* ================================================== */
1077
93f63589
ML
1078char *
1079NSR_GetName(IPAddr *address)
1080{
fb4c3f31 1081 int slot;
93f63589 1082
fb4c3f31 1083 if (!find_slot(address, &slot))
b585954b 1084 return NULL;
93f63589 1085
eb9e6701 1086 return get_record(slot)->name;
93f63589
ML
1087}
1088
1089/* ================================================== */
1090
777303f1
ML
1091/* This routine is called by ntp_io when a new packet arrives off the network,
1092 possibly with an authentication tail */
88840341 1093void
14c8f076
ML
1094NSR_ProcessRx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
1095 NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length)
88840341 1096{
308bcae2
ML
1097 SourceRecord *record;
1098 struct SourcePool *pool;
fb4c3f31 1099 int slot;
88840341
RC
1100
1101 assert(initialised);
1102
fb4c3f31
ML
1103 /* Must match IP address AND port number */
1104 if (find_slot2(remote_addr, &slot) == 2) {
308bcae2
ML
1105 record = get_record(slot);
1106
14c8f076 1107 if (!NCR_ProcessRxKnown(record->data, local_addr, rx_ts, message, length))
308bcae2
ML
1108 return;
1109
1110 if (record->tentative) {
b0838280 1111 /* This was the first good reply from the source */
308bcae2
ML
1112 record->tentative = 0;
1113
d274fe44
ML
1114 if (record->pool_id != INVALID_POOL) {
1115 pool = get_pool(record->pool_id);
8c256323 1116 pool->confirmed_sources++;
308bcae2 1117
8c256323 1118 DEBUG_LOG("pool %s has %d confirmed sources", record->name, pool->confirmed_sources);
308bcae2 1119
62e66bda
ML
1120 /* If the number of sources from the pool reached the configured
1121 maximum, remove the remaining tentative sources */
8c256323 1122 if (pool->confirmed_sources >= pool->max_sources)
d274fe44 1123 remove_pool_sources(record->pool_id, 1, 0);
62e66bda 1124 }
308bcae2 1125 }
88840341 1126 } else {
14c8f076 1127 NCR_ProcessRxUnknown(remote_addr, local_addr, rx_ts, message, length);
8f6a1b53
ML
1128 }
1129}
1130
1131/* ================================================== */
1132
1133void
14c8f076
ML
1134NSR_ProcessTx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
1135 NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length)
8f6a1b53
ML
1136{
1137 SourceRecord *record;
fb4c3f31 1138 int slot;
8f6a1b53 1139
fb4c3f31
ML
1140 /* Must match IP address AND port number */
1141 if (find_slot2(remote_addr, &slot) == 2) {
8f6a1b53 1142 record = get_record(slot);
14c8f076 1143 NCR_ProcessTxKnown(record->data, local_addr, tx_ts, message, length);
8f6a1b53 1144 } else {
14c8f076 1145 NCR_ProcessTxUnknown(remote_addr, local_addr, tx_ts, message, length);
88840341
RC
1146 }
1147}
1148
1149/* ================================================== */
1150
1151static void
d0dfa1de
ML
1152slew_sources(struct timespec *raw,
1153 struct timespec *cooked,
88840341 1154 double dfreq,
88840341 1155 double doffset,
44c9744d 1156 LCL_ChangeType change_type,
88840341
RC
1157 void *anything)
1158{
9e71932c
ML
1159 SourceRecord *record;
1160 unsigned int i;
88840341 1161
9e71932c
ML
1162 for (i = 0; i < ARR_GetSize(records); i++) {
1163 record = get_record(i);
1164 if (record->remote_addr) {
a33a9551 1165 if (change_type == LCL_ChangeUnknownStep) {
9e71932c 1166 NCR_ResetInstance(record->data);
4d7eb2f7 1167 NCR_ResetPoll(record->data);
a33a9551 1168 } else {
9e71932c 1169 NCR_SlewTimes(record->data, cooked, dfreq, doffset);
a33a9551 1170 }
88840341
RC
1171 }
1172 }
88840341
RC
1173}
1174
1175/* ================================================== */
1176
1177int
ce6b8969 1178NSR_SetConnectivity(IPAddr *mask, IPAddr *address, SRC_Connectivity connectivity)
88840341 1179{
9e71932c
ML
1180 SourceRecord *record, *syncpeer;
1181 unsigned int i, any;
88840341 1182
ce6b8969
ML
1183 if (connectivity != SRC_OFFLINE)
1184 NSR_ResolveSources();
1185
88840341 1186 any = 0;
9e71932c
ML
1187 syncpeer = NULL;
1188 for (i = 0; i < ARR_GetSize(records); i++) {
1189 record = get_record(i);
1190 if (record->remote_addr) {
27b3bf48
ML
1191 /* Ignore SRC_MAYBE_ONLINE connectivity change for unspecified unresolved
1192 sources as they would always end up in the offline state */
1193 if ((address->family == IPADDR_UNSPEC &&
1194 (connectivity != SRC_MAYBE_ONLINE || UTI_IsIPReal(&record->remote_addr->ip_addr))) ||
9e71932c 1195 !UTI_CompareIPs(&record->remote_addr->ip_addr, address, mask)) {
88840341 1196 any = 1;
9e71932c
ML
1197 if (NCR_IsSyncPeer(record->data)) {
1198 syncpeer = record;
2ea87490
ML
1199 continue;
1200 }
ce6b8969 1201 NCR_SetConnectivity(record->data, connectivity);
88840341
RC
1202 }
1203 }
1204 }
1205
ce6b8969
ML
1206 /* Set the sync peer last to avoid unnecessary reference switching */
1207 if (syncpeer)
1208 NCR_SetConnectivity(syncpeer->data, connectivity);
2ea87490 1209
88840341
RC
1210 return any;
1211}
1212
1213/* ================================================== */
1214
1215int
8265ff28 1216NSR_ModifyMinpoll(IPAddr *address, int new_minpoll)
88840341 1217{
fb4c3f31 1218 int slot;
88840341 1219
fb4c3f31 1220 if (!find_slot(address, &slot))
88840341 1221 return 0;
fb4c3f31
ML
1222
1223 NCR_ModifyMinpoll(get_record(slot)->data, new_minpoll);
1224 return 1;
88840341
RC
1225}
1226
1227/* ================================================== */
1228
1229int
8265ff28 1230NSR_ModifyMaxpoll(IPAddr *address, int new_maxpoll)
88840341 1231{
fb4c3f31 1232 int slot;
88840341 1233
fb4c3f31 1234 if (!find_slot(address, &slot))
88840341 1235 return 0;
fb4c3f31
ML
1236
1237 NCR_ModifyMaxpoll(get_record(slot)->data, new_maxpoll);
1238 return 1;
88840341
RC
1239}
1240
1241/* ================================================== */
1242
1243int
8265ff28 1244NSR_ModifyMaxdelay(IPAddr *address, double new_max_delay)
88840341 1245{
fb4c3f31 1246 int slot;
88840341 1247
fb4c3f31 1248 if (!find_slot(address, &slot))
88840341 1249 return 0;
fb4c3f31
ML
1250
1251 NCR_ModifyMaxdelay(get_record(slot)->data, new_max_delay);
1252 return 1;
88840341
RC
1253}
1254
1255/* ================================================== */
1256
1257int
8265ff28 1258NSR_ModifyMaxdelayratio(IPAddr *address, double new_max_delay_ratio)
88840341 1259{
fb4c3f31 1260 int slot;
88840341 1261
fb4c3f31 1262 if (!find_slot(address, &slot))
88840341 1263 return 0;
fb4c3f31
ML
1264
1265 NCR_ModifyMaxdelayratio(get_record(slot)->data, new_max_delay_ratio);
1266 return 1;
88840341
RC
1267}
1268
1269/* ================================================== */
1270
6ed5a650
ML
1271int
1272NSR_ModifyMaxdelaydevratio(IPAddr *address, double new_max_delay_dev_ratio)
1273{
fb4c3f31 1274 int slot;
6ed5a650 1275
fb4c3f31 1276 if (!find_slot(address, &slot))
6ed5a650 1277 return 0;
fb4c3f31
ML
1278
1279 NCR_ModifyMaxdelaydevratio(get_record(slot)->data, new_max_delay_dev_ratio);
1280 return 1;
6ed5a650
ML
1281}
1282
1283/* ================================================== */
1284
78300d01
ML
1285int
1286NSR_ModifyMinstratum(IPAddr *address, int new_min_stratum)
1287{
fb4c3f31 1288 int slot;
78300d01 1289
fb4c3f31 1290 if (!find_slot(address, &slot))
78300d01 1291 return 0;
fb4c3f31
ML
1292
1293 NCR_ModifyMinstratum(get_record(slot)->data, new_min_stratum);
1294 return 1;
78300d01
ML
1295}
1296
1297/* ================================================== */
1298
bed5b72c
ML
1299int
1300NSR_ModifyPolltarget(IPAddr *address, int new_poll_target)
1301{
fb4c3f31 1302 int slot;
bed5b72c 1303
fb4c3f31 1304 if (!find_slot(address, &slot))
bed5b72c 1305 return 0;
fb4c3f31
ML
1306
1307 NCR_ModifyPolltarget(get_record(slot)->data, new_poll_target);
1308 return 1;
bed5b72c
ML
1309}
1310
1311/* ================================================== */
1312
88840341
RC
1313int
1314NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples,
8265ff28 1315 IPAddr *mask, IPAddr *address)
88840341 1316{
9e71932c
ML
1317 SourceRecord *record;
1318 unsigned int i;
88840341 1319 int any;
88840341
RC
1320
1321 any = 0;
9e71932c
ML
1322 for (i = 0; i < ARR_GetSize(records); i++) {
1323 record = get_record(i);
1324 if (record->remote_addr) {
8265ff28 1325 if (address->family == IPADDR_UNSPEC ||
9e71932c 1326 !UTI_CompareIPs(&record->remote_addr->ip_addr, address, mask)) {
88840341 1327 any = 1;
9e71932c 1328 NCR_InitiateSampleBurst(record->data, n_good_samples, n_total_samples);
88840341
RC
1329 }
1330 }
1331 }
1332
1333 return any;
1334
1335}
1336
1337/* ================================================== */
1338/* The ip address is assumed to be completed on input, that is how we
1339 identify the source record. */
1340
1341void
d0dfa1de 1342NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
88840341 1343{
fb4c3f31 1344 int slot;
88840341 1345
fb4c3f31 1346 if (find_slot(&report->ip_addr, &slot)) {
9e71932c 1347 NCR_ReportSource(get_record(slot)->data, report, now);
88840341
RC
1348 } else {
1349 report->poll = 0;
1350 report->latest_meas_ago = 0;
1351 }
1352}
1353
79c7384e
ML
1354/* ================================================== */
1355
1356int
1357NSR_GetAuthReport(IPAddr *address, RPT_AuthReport *report)
1358{
fb4c3f31 1359 int slot;
79c7384e 1360
fb4c3f31 1361 if (!find_slot(address, &slot))
79c7384e
ML
1362 return 0;
1363
1364 NCR_GetAuthReport(get_record(slot)->data, report);
1365 return 1;
1366}
1367
535ca64b
ML
1368/* ================================================== */
1369/* The ip address is assumed to be completed on input, that is how we
1370 identify the source record. */
1371
1372int
1373NSR_GetNTPReport(RPT_NTPReport *report)
1374{
fb4c3f31 1375 int slot;
535ca64b 1376
fb4c3f31 1377 if (!find_slot(&report->remote_addr, &slot))
535ca64b
ML
1378 return 0;
1379
1380 NCR_GetNTPReport(get_record(slot)->data, report);
1381 return 1;
1382}
1383
88840341
RC
1384/* ================================================== */
1385
1386void
1387NSR_GetActivityReport(RPT_ActivityReport *report)
1388{
9e71932c
ML
1389 SourceRecord *record;
1390 unsigned int i;
88840341
RC
1391
1392 report->online = 0;
1393 report->offline = 0;
1394 report->burst_online = 0;
1395 report->burst_offline = 0;
d7e3ad17 1396 report->unresolved = 0;
88840341 1397
9e71932c
ML
1398 for (i = 0; i < ARR_GetSize(records); i++) {
1399 record = get_record(i);
d7e3ad17
ML
1400 if (!record->remote_addr)
1401 continue;
1402
1403 if (!UTI_IsIPReal(&record->remote_addr->ip_addr)) {
1404 report->unresolved++;
1405 } else {
9e71932c 1406 NCR_IncrementActivityCounters(record->data, &report->online, &report->offline,
88840341
RC
1407 &report->burst_online, &report->burst_offline);
1408 }
1409 }
88840341
RC
1410}
1411
88840341
RC
1412/* ================================================== */
1413
d690faeb
ML
1414void
1415NSR_DumpAuthData(void)
1416{
1417 SourceRecord *record;
1418 int i;
1419
1420 for (i = 0; i < ARR_GetSize(records); i++) {
1421 record = get_record(i);
1422 if (!record->remote_addr)
1423 continue;
1424 NCR_DumpAuthData(record->data);
1425 }
1426}