ntp: create sources for unresolved addresses
Rework the ntp_sources code to create sources for addresses that are not resolved yet using the new identifiers.
This commit is contained in:
parent
84902d0e00
commit
d7e3ad17ff
1 changed files with 95 additions and 71 deletions
166
ntp_sources.c
166
ntp_sources.c
|
@ -48,7 +48,9 @@
|
|||
particular sources */
|
||||
typedef struct {
|
||||
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
|
||||
means this slot in table is in use */
|
||||
means this slot in table is in use
|
||||
(an IPADDR_ID address means the address
|
||||
is not resolved yet) */
|
||||
NCR_Instance data; /* Data for the protocol engine for this source */
|
||||
char *name; /* Name of the source, may be NULL */
|
||||
int pool; /* Number of the pool from which was this source
|
||||
|
@ -67,21 +69,21 @@ static int n_sources;
|
|||
/* Flag indicating new sources will be started automatically when added */
|
||||
static int auto_start_sources = 0;
|
||||
|
||||
/* Source with unknown address (which may be resolved later) */
|
||||
/* Last assigned address ID */
|
||||
static uint32_t last_address_id = 0;
|
||||
|
||||
/* Source scheduled for name resolving (first resolving or replacement) */
|
||||
struct UnresolvedSource {
|
||||
/* Current address of the source (IDADDR_ID is used for a single source
|
||||
with unknown address and IPADDR_UNSPEC for a pool of sources */
|
||||
NTP_Remote_Address address;
|
||||
/* ID of the pool if not a single source */
|
||||
int pool;
|
||||
/* Name to be resolved */
|
||||
char *name;
|
||||
int port;
|
||||
/* Flag indicating addresses should be used in a random order */
|
||||
int random_order;
|
||||
int replacement;
|
||||
union {
|
||||
struct {
|
||||
NTP_Source_Type type;
|
||||
SourceParameters params;
|
||||
int pool;
|
||||
int max_new_sources;
|
||||
} new_source;
|
||||
NTP_Remote_Address replace_source;
|
||||
};
|
||||
/* Next unresolved source in the list */
|
||||
struct UnresolvedSource *next;
|
||||
};
|
||||
|
||||
|
@ -101,7 +103,7 @@ static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
|||
|
||||
/* Pool of sources with the same name */
|
||||
struct SourcePool {
|
||||
/* Number of sources added from this pool (ignoring tentative sources) */
|
||||
/* Number of non-tentative sources with known address */
|
||||
int sources;
|
||||
/* Maximum number of sources */
|
||||
int max_sources;
|
||||
|
@ -116,6 +118,7 @@ static ARR_Instance pools;
|
|||
static void resolve_sources(void *arg);
|
||||
static void rehash_records(void);
|
||||
static void clean_source_record(SourceRecord *record);
|
||||
static void remove_pool_sources(int pool, int tentative, int unresolved);
|
||||
|
||||
static void
|
||||
slew_sources(struct timespec *raw,
|
||||
|
@ -211,7 +214,8 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
|
|||
*found = 0;
|
||||
|
||||
if (remote_addr->ip_addr.family != IPADDR_INET4 &&
|
||||
remote_addr->ip_addr.family != IPADDR_INET6)
|
||||
remote_addr->ip_addr.family != IPADDR_INET6 &&
|
||||
remote_addr->ip_addr.family != IPADDR_ID)
|
||||
return;
|
||||
|
||||
hash = UTI_IPToHash(&remote_addr->ip_addr);
|
||||
|
@ -295,7 +299,8 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, So
|
|||
return NSR_AlreadyInUse;
|
||||
} else {
|
||||
if (remote_addr->ip_addr.family != IPADDR_INET4 &&
|
||||
remote_addr->ip_addr.family != IPADDR_INET6) {
|
||||
remote_addr->ip_addr.family != IPADDR_INET6 &&
|
||||
remote_addr->ip_addr.family != IPADDR_ID) {
|
||||
return NSR_InvalidAF;
|
||||
} else {
|
||||
n_sources++;
|
||||
|
@ -313,7 +318,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, So
|
|||
record->pool = pool;
|
||||
record->tentative = 1;
|
||||
|
||||
if (auto_start_sources)
|
||||
if (auto_start_sources && UTI_IsIPReal(&remote_addr->ip_addr))
|
||||
NCR_StartInstance(record->data);
|
||||
|
||||
return NSR_Success;
|
||||
|
@ -329,6 +334,7 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
|||
int slot1, slot2, found;
|
||||
SourceRecord *record;
|
||||
struct SourcePool *pool;
|
||||
LOG_Severity severity;
|
||||
char *name;
|
||||
|
||||
find_slot(old_addr, &slot1, &found);
|
||||
|
@ -342,6 +348,9 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
|||
record = get_record(slot1);
|
||||
NCR_ChangeRemoteAddress(record->data, new_addr);
|
||||
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
||||
if (!UTI_IsIPReal(&old_addr->ip_addr) && UTI_IsIPReal(&new_addr->ip_addr) &&
|
||||
auto_start_sources)
|
||||
NCR_StartInstance(record->data);
|
||||
|
||||
if (!record->tentative) {
|
||||
record->tentative = 1;
|
||||
|
@ -357,7 +366,9 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
|||
/* The hash table must be rebuilt for the new address */
|
||||
rehash_records();
|
||||
|
||||
LOG(LOGS_INFO, "Source %s replaced with %s (%s)", UTI_IPToString(&old_addr->ip_addr),
|
||||
severity = UTI_IsIPReal(&old_addr->ip_addr) ? LOGS_INFO : LOGS_DEBUG;
|
||||
|
||||
LOG(severity, "Source %s replaced with %s (%s)", UTI_IPToString(&old_addr->ip_addr),
|
||||
UTI_IPToString(&new_addr->ip_addr), name ? name : "");
|
||||
|
||||
return NSR_Success;
|
||||
|
@ -368,31 +379,42 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
|||
static void
|
||||
process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs)
|
||||
{
|
||||
NTP_Remote_Address address;
|
||||
int i, added;
|
||||
NTP_Remote_Address old_addr, new_addr;
|
||||
SourceRecord *record;
|
||||
unsigned short first = 0;
|
||||
int i, j;
|
||||
|
||||
if (us->random_order)
|
||||
UTI_GetRandomBytes(&first, sizeof (first));
|
||||
|
||||
for (i = added = 0; i < n_addrs; i++) {
|
||||
address.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs];
|
||||
address.port = us->port;
|
||||
for (i = 0; i < n_addrs; i++) {
|
||||
new_addr.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs];
|
||||
|
||||
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&address.ip_addr));
|
||||
DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
|
||||
|
||||
if (us->replacement) {
|
||||
if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse)
|
||||
break;
|
||||
if (us->pool != INVALID_POOL) {
|
||||
/* In the pool resolving mode, try to replace all sources from
|
||||
the pool which don't have a real address yet */
|
||||
for (j = 0; j < ARR_GetSize(records); j++) {
|
||||
record = get_record(j);
|
||||
if (!record->remote_addr || record->pool != us->pool ||
|
||||
UTI_IsIPReal(&record->remote_addr->ip_addr))
|
||||
continue;
|
||||
old_addr = *record->remote_addr;
|
||||
new_addr.port = old_addr.port;
|
||||
if (replace_source(&old_addr, &new_addr) != NSR_AlreadyInUse)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (add_source(&address, us->name, us->new_source.type, &us->new_source.params,
|
||||
us->new_source.pool) == NSR_Success)
|
||||
added++;
|
||||
|
||||
if (added >= us->new_source.max_new_sources)
|
||||
new_addr.port = us->address.port;
|
||||
if (replace_source(&us->address, &new_addr) != NSR_AlreadyInUse)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove pool sources that didn't get an address */
|
||||
if (us->pool != INVALID_POOL)
|
||||
remove_pool_sources(us->pool, 0, 1);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -424,8 +446,8 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *any
|
|||
next = us->next;
|
||||
|
||||
/* Remove the source from the list on success or failure, replacements
|
||||
are removed on any status */
|
||||
if (us->replacement || status != DNS_TryAgain) {
|
||||
of known addresses are removed on any status */
|
||||
if (status != DNS_TryAgain || UTI_IsIPReal(&us->address.ip_addr)) {
|
||||
for (i = &unresolved_sources; *i; i = &(*i)->next) {
|
||||
if (*i == us) {
|
||||
*i = us->next;
|
||||
|
@ -511,7 +533,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
|
|||
struct UnresolvedSource *us;
|
||||
struct SourcePool *sp;
|
||||
NTP_Remote_Address remote_addr;
|
||||
int i;
|
||||
int i, new_sources;
|
||||
|
||||
/* If the name is an IP address, don't bother with full resolving now
|
||||
or later when trying to replace the source */
|
||||
|
@ -528,25 +550,34 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
|
|||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
us->name = Strdup(name);
|
||||
us->port = port;
|
||||
us->random_order = 0;
|
||||
us->replacement = 0;
|
||||
us->new_source.type = type;
|
||||
us->new_source.params = *params;
|
||||
|
||||
remote_addr.ip_addr.family = IPADDR_ID;
|
||||
remote_addr.ip_addr.addr.id = ++last_address_id;
|
||||
remote_addr.port = port;
|
||||
|
||||
if (!pool) {
|
||||
us->new_source.pool = INVALID_POOL;
|
||||
us->new_source.max_new_sources = 1;
|
||||
us->pool = INVALID_POOL;
|
||||
us->address = remote_addr;
|
||||
new_sources = 1;
|
||||
} else {
|
||||
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
||||
sp->sources = 0;
|
||||
sp->max_sources = params->max_sources;
|
||||
us->new_source.pool = ARR_GetSize(pools) - 1;
|
||||
us->new_source.max_new_sources = MAX_POOL_SOURCES;
|
||||
sp->max_sources = CLAMP(1, params->max_sources, MAX_POOL_SOURCES);
|
||||
us->pool = ARR_GetSize(pools) - 1;
|
||||
us->address.ip_addr.family = IPADDR_UNSPEC;
|
||||
new_sources = MIN(2 * sp->max_sources, MAX_POOL_SOURCES);
|
||||
}
|
||||
|
||||
append_unresolved_source(us);
|
||||
|
||||
for (i = 0; i < new_sources; i++) {
|
||||
if (i > 0)
|
||||
remote_addr.ip_addr.addr.id = ++last_address_id;
|
||||
if (add_source(&remote_addr, name, type, params, us->pool) != NSR_Success)
|
||||
return NSR_TooManySources;
|
||||
}
|
||||
|
||||
return NSR_UnresolvedName;
|
||||
}
|
||||
|
||||
|
@ -584,10 +615,12 @@ NSR_ResolveSources(void)
|
|||
|
||||
void NSR_StartSources(void)
|
||||
{
|
||||
NTP_Remote_Address *addr;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||
if (!get_record(i)->remote_addr)
|
||||
addr = get_record(i)->remote_addr;
|
||||
if (!addr || !UTI_IsIPReal(&addr->ip_addr))
|
||||
continue;
|
||||
NCR_StartInstance(get_record(i)->data);
|
||||
}
|
||||
|
@ -671,14 +704,13 @@ resolve_source_replacement(SourceRecord *record)
|
|||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
us->name = Strdup(record->name);
|
||||
us->port = record->remote_addr->port;
|
||||
/* If there never was a valid reply from this source (e.g. it was a bad
|
||||
replacement), ignore the order of addresses from the resolver to not get
|
||||
stuck to a pair of addresses if the order doesn't change, or a group of
|
||||
IPv4/IPv6 addresses if the resolver prefers inaccessible IP family */
|
||||
us->random_order = record->tentative;
|
||||
us->replacement = 1;
|
||||
us->replace_source = *record->remote_addr;
|
||||
us->pool = INVALID_POOL;
|
||||
us->address = *record->remote_addr;
|
||||
|
||||
append_unresolved_source(us);
|
||||
NSR_ResolveSources();
|
||||
|
@ -740,7 +772,7 @@ NSR_RefreshAddresses(void)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void remove_tentative_pool_sources(int pool)
|
||||
static void remove_pool_sources(int pool, int tentative, int unresolved)
|
||||
{
|
||||
SourceRecord *record;
|
||||
unsigned int i, removed;
|
||||
|
@ -748,10 +780,14 @@ static void remove_tentative_pool_sources(int pool)
|
|||
for (i = removed = 0; i < ARR_GetSize(records); i++) {
|
||||
record = get_record(i);
|
||||
|
||||
if (!record->remote_addr || record->pool != pool || !record->tentative)
|
||||
if (!record->remote_addr || record->pool != pool)
|
||||
continue;
|
||||
|
||||
DEBUG_LOG("removing tentative source %s",
|
||||
if ((tentative && !record->tentative) ||
|
||||
(unresolved && UTI_IsIPReal(&record->remote_addr->ip_addr)))
|
||||
continue;
|
||||
|
||||
DEBUG_LOG("removing %ssource %s", tentative ? "tentative " : "",
|
||||
UTI_IPToString(&record->remote_addr->ip_addr));
|
||||
|
||||
clean_source_record(record);
|
||||
|
@ -837,7 +873,7 @@ NSR_ProcessRx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr,
|
|||
/* If the number of sources from the pool reached the configured
|
||||
maximum, remove the remaining tentative sources */
|
||||
if (pool->sources >= pool->max_sources)
|
||||
remove_tentative_pool_sources(record->pool);
|
||||
remove_pool_sources(record->pool, 1, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -922,17 +958,6 @@ NSR_SetConnectivity(IPAddr *mask, IPAddr *address, SRC_Connectivity connectivity
|
|||
if (syncpeer)
|
||||
NCR_SetConnectivity(syncpeer->data, connectivity);
|
||||
|
||||
if (address->family == IPADDR_UNSPEC) {
|
||||
struct UnresolvedSource *us;
|
||||
|
||||
for (us = unresolved_sources; us; us = us->next) {
|
||||
if (us->replacement)
|
||||
continue;
|
||||
any = 1;
|
||||
us->new_source.params.connectivity = connectivity;
|
||||
}
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
|
@ -1143,26 +1168,25 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
|
|||
{
|
||||
SourceRecord *record;
|
||||
unsigned int i;
|
||||
struct UnresolvedSource *us;
|
||||
|
||||
report->online = 0;
|
||||
report->offline = 0;
|
||||
report->burst_online = 0;
|
||||
report->burst_offline = 0;
|
||||
report->unresolved = 0;
|
||||
|
||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||
record = get_record(i);
|
||||
if (record->remote_addr) {
|
||||
if (!record->remote_addr)
|
||||
continue;
|
||||
|
||||
if (!UTI_IsIPReal(&record->remote_addr->ip_addr)) {
|
||||
report->unresolved++;
|
||||
} else {
|
||||
NCR_IncrementActivityCounters(record->data, &report->online, &report->offline,
|
||||
&report->burst_online, &report->burst_offline);
|
||||
}
|
||||
}
|
||||
|
||||
report->unresolved = 0;
|
||||
|
||||
for (us = unresolved_sources; us; us = us->next) {
|
||||
report->unresolved++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue