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 */
|
particular sources */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NTP_Remote_Address *remote_addr; /* The address of this source, non-NULL
|
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 */
|
NCR_Instance data; /* Data for the protocol engine for this source */
|
||||||
char *name; /* Name of the source, may be NULL */
|
char *name; /* Name of the source, may be NULL */
|
||||||
int pool; /* Number of the pool from which was this source
|
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 */
|
/* Flag indicating new sources will be started automatically when added */
|
||||||
static int auto_start_sources = 0;
|
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 {
|
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;
|
char *name;
|
||||||
int port;
|
/* Flag indicating addresses should be used in a random order */
|
||||||
int random_order;
|
int random_order;
|
||||||
int replacement;
|
/* Next unresolved source in the list */
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
NTP_Source_Type type;
|
|
||||||
SourceParameters params;
|
|
||||||
int pool;
|
|
||||||
int max_new_sources;
|
|
||||||
} new_source;
|
|
||||||
NTP_Remote_Address replace_source;
|
|
||||||
};
|
|
||||||
struct UnresolvedSource *next;
|
struct UnresolvedSource *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,7 +103,7 @@ static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
||||||
|
|
||||||
/* Pool of sources with the same name */
|
/* Pool of sources with the same name */
|
||||||
struct SourcePool {
|
struct SourcePool {
|
||||||
/* Number of sources added from this pool (ignoring tentative sources) */
|
/* Number of non-tentative sources with known address */
|
||||||
int sources;
|
int sources;
|
||||||
/* Maximum number of sources */
|
/* Maximum number of sources */
|
||||||
int max_sources;
|
int max_sources;
|
||||||
|
@ -116,6 +118,7 @@ static ARR_Instance pools;
|
||||||
static void resolve_sources(void *arg);
|
static void resolve_sources(void *arg);
|
||||||
static void rehash_records(void);
|
static void rehash_records(void);
|
||||||
static void clean_source_record(SourceRecord *record);
|
static void clean_source_record(SourceRecord *record);
|
||||||
|
static void remove_pool_sources(int pool, int tentative, int unresolved);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slew_sources(struct timespec *raw,
|
slew_sources(struct timespec *raw,
|
||||||
|
@ -211,7 +214,8 @@ find_slot(NTP_Remote_Address *remote_addr, int *slot, int *found)
|
||||||
*found = 0;
|
*found = 0;
|
||||||
|
|
||||||
if (remote_addr->ip_addr.family != IPADDR_INET4 &&
|
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;
|
return;
|
||||||
|
|
||||||
hash = UTI_IPToHash(&remote_addr->ip_addr);
|
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;
|
return NSR_AlreadyInUse;
|
||||||
} else {
|
} else {
|
||||||
if (remote_addr->ip_addr.family != IPADDR_INET4 &&
|
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;
|
return NSR_InvalidAF;
|
||||||
} else {
|
} else {
|
||||||
n_sources++;
|
n_sources++;
|
||||||
|
@ -313,7 +318,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, So
|
||||||
record->pool = pool;
|
record->pool = pool;
|
||||||
record->tentative = 1;
|
record->tentative = 1;
|
||||||
|
|
||||||
if (auto_start_sources)
|
if (auto_start_sources && UTI_IsIPReal(&remote_addr->ip_addr))
|
||||||
NCR_StartInstance(record->data);
|
NCR_StartInstance(record->data);
|
||||||
|
|
||||||
return NSR_Success;
|
return NSR_Success;
|
||||||
|
@ -329,6 +334,7 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
||||||
int slot1, slot2, found;
|
int slot1, slot2, found;
|
||||||
SourceRecord *record;
|
SourceRecord *record;
|
||||||
struct SourcePool *pool;
|
struct SourcePool *pool;
|
||||||
|
LOG_Severity severity;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
find_slot(old_addr, &slot1, &found);
|
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);
|
record = get_record(slot1);
|
||||||
NCR_ChangeRemoteAddress(record->data, new_addr);
|
NCR_ChangeRemoteAddress(record->data, new_addr);
|
||||||
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
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) {
|
if (!record->tentative) {
|
||||||
record->tentative = 1;
|
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 */
|
/* The hash table must be rebuilt for the new address */
|
||||||
rehash_records();
|
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 : "");
|
UTI_IPToString(&new_addr->ip_addr), name ? name : "");
|
||||||
|
|
||||||
return NSR_Success;
|
return NSR_Success;
|
||||||
|
@ -368,31 +379,42 @@ replace_source(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr)
|
||||||
static void
|
static void
|
||||||
process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs)
|
process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs)
|
||||||
{
|
{
|
||||||
NTP_Remote_Address address;
|
NTP_Remote_Address old_addr, new_addr;
|
||||||
int i, added;
|
SourceRecord *record;
|
||||||
unsigned short first = 0;
|
unsigned short first = 0;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
if (us->random_order)
|
if (us->random_order)
|
||||||
UTI_GetRandomBytes(&first, sizeof (first));
|
UTI_GetRandomBytes(&first, sizeof (first));
|
||||||
|
|
||||||
for (i = added = 0; i < n_addrs; i++) {
|
for (i = 0; i < n_addrs; i++) {
|
||||||
address.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs];
|
new_addr.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs];
|
||||||
address.port = us->port;
|
|
||||||
|
|
||||||
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 (us->pool != INVALID_POOL) {
|
||||||
if (replace_source(&us->replace_source, &address) != NSR_AlreadyInUse)
|
/* In the pool resolving mode, try to replace all sources from
|
||||||
break;
|
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 {
|
} else {
|
||||||
if (add_source(&address, us->name, us->new_source.type, &us->new_source.params,
|
new_addr.port = us->address.port;
|
||||||
us->new_source.pool) == NSR_Success)
|
if (replace_source(&us->address, &new_addr) != NSR_AlreadyInUse)
|
||||||
added++;
|
|
||||||
|
|
||||||
if (added >= us->new_source.max_new_sources)
|
|
||||||
break;
|
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;
|
next = us->next;
|
||||||
|
|
||||||
/* Remove the source from the list on success or failure, replacements
|
/* Remove the source from the list on success or failure, replacements
|
||||||
are removed on any status */
|
of known addresses are removed on any status */
|
||||||
if (us->replacement || status != DNS_TryAgain) {
|
if (status != DNS_TryAgain || UTI_IsIPReal(&us->address.ip_addr)) {
|
||||||
for (i = &unresolved_sources; *i; i = &(*i)->next) {
|
for (i = &unresolved_sources; *i; i = &(*i)->next) {
|
||||||
if (*i == us) {
|
if (*i == us) {
|
||||||
*i = us->next;
|
*i = us->next;
|
||||||
|
@ -511,7 +533,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, Source
|
||||||
struct UnresolvedSource *us;
|
struct UnresolvedSource *us;
|
||||||
struct SourcePool *sp;
|
struct SourcePool *sp;
|
||||||
NTP_Remote_Address remote_addr;
|
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
|
/* If the name is an IP address, don't bother with full resolving now
|
||||||
or later when trying to replace the source */
|
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 = MallocNew(struct UnresolvedSource);
|
||||||
us->name = Strdup(name);
|
us->name = Strdup(name);
|
||||||
us->port = port;
|
|
||||||
us->random_order = 0;
|
us->random_order = 0;
|
||||||
us->replacement = 0;
|
|
||||||
us->new_source.type = type;
|
remote_addr.ip_addr.family = IPADDR_ID;
|
||||||
us->new_source.params = *params;
|
remote_addr.ip_addr.addr.id = ++last_address_id;
|
||||||
|
remote_addr.port = port;
|
||||||
|
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
us->new_source.pool = INVALID_POOL;
|
us->pool = INVALID_POOL;
|
||||||
us->new_source.max_new_sources = 1;
|
us->address = remote_addr;
|
||||||
|
new_sources = 1;
|
||||||
} else {
|
} else {
|
||||||
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
sp = (struct SourcePool *)ARR_GetNewElement(pools);
|
||||||
sp->sources = 0;
|
sp->sources = 0;
|
||||||
sp->max_sources = params->max_sources;
|
sp->max_sources = CLAMP(1, params->max_sources, MAX_POOL_SOURCES);
|
||||||
us->new_source.pool = ARR_GetSize(pools) - 1;
|
us->pool = ARR_GetSize(pools) - 1;
|
||||||
us->new_source.max_new_sources = MAX_POOL_SOURCES;
|
us->address.ip_addr.family = IPADDR_UNSPEC;
|
||||||
|
new_sources = MIN(2 * sp->max_sources, MAX_POOL_SOURCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
append_unresolved_source(us);
|
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;
|
return NSR_UnresolvedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,10 +615,12 @@ NSR_ResolveSources(void)
|
||||||
|
|
||||||
void NSR_StartSources(void)
|
void NSR_StartSources(void)
|
||||||
{
|
{
|
||||||
|
NTP_Remote_Address *addr;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(records); 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;
|
continue;
|
||||||
NCR_StartInstance(get_record(i)->data);
|
NCR_StartInstance(get_record(i)->data);
|
||||||
}
|
}
|
||||||
|
@ -671,14 +704,13 @@ resolve_source_replacement(SourceRecord *record)
|
||||||
|
|
||||||
us = MallocNew(struct UnresolvedSource);
|
us = MallocNew(struct UnresolvedSource);
|
||||||
us->name = Strdup(record->name);
|
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
|
/* 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
|
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
|
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 */
|
IPv4/IPv6 addresses if the resolver prefers inaccessible IP family */
|
||||||
us->random_order = record->tentative;
|
us->random_order = record->tentative;
|
||||||
us->replacement = 1;
|
us->pool = INVALID_POOL;
|
||||||
us->replace_source = *record->remote_addr;
|
us->address = *record->remote_addr;
|
||||||
|
|
||||||
append_unresolved_source(us);
|
append_unresolved_source(us);
|
||||||
NSR_ResolveSources();
|
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;
|
SourceRecord *record;
|
||||||
unsigned int i, removed;
|
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++) {
|
for (i = removed = 0; i < ARR_GetSize(records); i++) {
|
||||||
record = get_record(i);
|
record = get_record(i);
|
||||||
|
|
||||||
if (!record->remote_addr || record->pool != pool || !record->tentative)
|
if (!record->remote_addr || record->pool != pool)
|
||||||
continue;
|
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));
|
UTI_IPToString(&record->remote_addr->ip_addr));
|
||||||
|
|
||||||
clean_source_record(record);
|
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
|
/* If the number of sources from the pool reached the configured
|
||||||
maximum, remove the remaining tentative sources */
|
maximum, remove the remaining tentative sources */
|
||||||
if (pool->sources >= pool->max_sources)
|
if (pool->sources >= pool->max_sources)
|
||||||
remove_tentative_pool_sources(record->pool);
|
remove_pool_sources(record->pool, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -922,17 +958,6 @@ NSR_SetConnectivity(IPAddr *mask, IPAddr *address, SRC_Connectivity connectivity
|
||||||
if (syncpeer)
|
if (syncpeer)
|
||||||
NCR_SetConnectivity(syncpeer->data, connectivity);
|
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;
|
return any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,26 +1168,25 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
|
||||||
{
|
{
|
||||||
SourceRecord *record;
|
SourceRecord *record;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct UnresolvedSource *us;
|
|
||||||
|
|
||||||
report->online = 0;
|
report->online = 0;
|
||||||
report->offline = 0;
|
report->offline = 0;
|
||||||
report->burst_online = 0;
|
report->burst_online = 0;
|
||||||
report->burst_offline = 0;
|
report->burst_offline = 0;
|
||||||
|
report->unresolved = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARR_GetSize(records); i++) {
|
for (i = 0; i < ARR_GetSize(records); i++) {
|
||||||
record = get_record(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,
|
NCR_IncrementActivityCounters(record->data, &report->online, &report->offline,
|
||||||
&report->burst_online, &report->burst_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