ntp: use async name resolving for NTP sources
Use the new asynchronous call to resolve addresses of NTP servers configured by the server/peer directives. Introduce a callback to be notified when the first resolving attempt ends to correctly finish chronyd initialization (dumpfile reload and reference mode end).
This commit is contained in:
parent
779e40ed66
commit
6ee357d230
4 changed files with 133 additions and 49 deletions
2
conf.c
2
conf.c
|
@ -1186,8 +1186,6 @@ CNF_AddSources(void) {
|
|||
NSR_AddUnresolvedSource(ntp_sources[i].params.name, ntp_sources[i].params.port,
|
||||
ntp_sources[i].type, &ntp_sources[i].params.params);
|
||||
}
|
||||
|
||||
NSR_ResolveSources();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
36
main.c
36
main.c
|
@ -123,20 +123,10 @@ signal_cleanup(int x)
|
|||
/* ================================================== */
|
||||
|
||||
static void
|
||||
post_init_ntp_hook(void *anything)
|
||||
ntp_source_resolving_end(void)
|
||||
{
|
||||
if (ref_mode == REF_ModeInitStepSlew) {
|
||||
/* Remove the initstepslew sources and set normal mode */
|
||||
NSR_RemoveAllSources();
|
||||
ref_mode = REF_ModeNormal;
|
||||
REF_SetMode(ref_mode);
|
||||
}
|
||||
NSR_SetSourceResolvingEndHandler(NULL);
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
LOG_CloseParentFd();
|
||||
|
||||
CNF_AddSources();
|
||||
CNF_AddBroadcasts();
|
||||
if (reload) {
|
||||
/* Note, we want reload to come well after the initialisation from
|
||||
the real time clock - this gives us a fighting chance that the
|
||||
|
@ -159,6 +149,28 @@ post_init_ntp_hook(void *anything)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
post_init_ntp_hook(void *anything)
|
||||
{
|
||||
if (ref_mode == REF_ModeInitStepSlew) {
|
||||
/* Remove the initstepslew sources and set normal mode */
|
||||
NSR_RemoveAllSources();
|
||||
ref_mode = REF_ModeNormal;
|
||||
REF_SetMode(ref_mode);
|
||||
}
|
||||
|
||||
/* Close the pipe to the foreground process so it can exit */
|
||||
LOG_CloseParentFd();
|
||||
|
||||
CNF_AddSources();
|
||||
CNF_AddBroadcasts();
|
||||
|
||||
NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
|
||||
NSR_ResolveSources();
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
reference_mode_end(int result)
|
||||
{
|
||||
|
|
135
ntp_sources.c
135
ntp_sources.c
|
@ -37,7 +37,7 @@
|
|||
#include "logging.h"
|
||||
#include "local.h"
|
||||
#include "memory.h"
|
||||
#include "nameserv.h"
|
||||
#include "nameserv_async.h"
|
||||
#include "sched.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -77,9 +77,14 @@ struct UnresolvedSource {
|
|||
static struct UnresolvedSource *unresolved_sources = NULL;
|
||||
static int resolving_interval = 0;
|
||||
static SCH_TimeoutID resolving_id;
|
||||
static struct UnresolvedSource *resolving_source = NULL;
|
||||
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
||||
|
||||
/* ================================================== */
|
||||
/* Forward prototypes */
|
||||
|
||||
static void resolve_sources(void *arg);
|
||||
|
||||
static void
|
||||
slew_sources(struct timeval *raw,
|
||||
struct timeval *cooked,
|
||||
|
@ -218,42 +223,87 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything)
|
||||
{
|
||||
struct UnresolvedSource *us, **i, *next;
|
||||
NTP_Remote_Address address;
|
||||
|
||||
us = (struct UnresolvedSource *)anything;
|
||||
|
||||
assert(us == resolving_source);
|
||||
|
||||
switch (status) {
|
||||
case DNS_TryAgain:
|
||||
break;
|
||||
case DNS_Success:
|
||||
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(ip_addr));
|
||||
address.ip_addr = *ip_addr;
|
||||
address.port = us->port;
|
||||
NSR_AddSource(&address, us->type, &us->params);
|
||||
break;
|
||||
case DNS_Failure:
|
||||
LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
next = us->next;
|
||||
|
||||
if (status != DNS_TryAgain) {
|
||||
/* Remove the source from the list */
|
||||
for (i = &unresolved_sources; *i; i = &(*i)->next) {
|
||||
if (*i == us) {
|
||||
*i = us->next;
|
||||
Free(us->name);
|
||||
Free(us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolving_source = next;
|
||||
|
||||
if (next) {
|
||||
/* Continue with the next source in the list */
|
||||
DEBUG_LOG(LOGF_NtpSources, "resolving %s", next->name);
|
||||
DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next);
|
||||
} else {
|
||||
/* This was the last source in the list. If some sources couldn't
|
||||
be resolved, try again in exponentially increasing interval. */
|
||||
if (unresolved_sources) {
|
||||
if (resolving_interval < 9)
|
||||
resolving_interval++;
|
||||
resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
|
||||
} else {
|
||||
resolving_interval = 0;
|
||||
}
|
||||
|
||||
/* This round of resolving is done */
|
||||
if (resolving_end_handler)
|
||||
(resolving_end_handler)();
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
resolve_sources(void *arg)
|
||||
{
|
||||
NTP_Remote_Address address;
|
||||
struct UnresolvedSource *us, **i;
|
||||
DNS_Status s;
|
||||
struct UnresolvedSource *us;
|
||||
|
||||
assert(!resolving_source);
|
||||
|
||||
DNS_Reload();
|
||||
|
||||
for (i = &unresolved_sources; *i; ) {
|
||||
us = *i;
|
||||
s = DNS_Name2IPAddress(us->name, &address.ip_addr);
|
||||
if (s == DNS_TryAgain) {
|
||||
i = &(*i)->next;
|
||||
continue;
|
||||
} else if (s == DNS_Success) {
|
||||
address.port = us->port;
|
||||
NSR_AddSource(&address, us->type, &us->params);
|
||||
} else {
|
||||
LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name);
|
||||
}
|
||||
|
||||
*i = us->next;
|
||||
/* Start with the first source in the list, name_resolve_handler
|
||||
will iterate over the rest */
|
||||
us = unresolved_sources;
|
||||
|
||||
Free(us->name);
|
||||
Free(us);
|
||||
}
|
||||
|
||||
if (unresolved_sources) {
|
||||
/* Try again later */
|
||||
if (resolving_interval < 9)
|
||||
resolving_interval++;
|
||||
resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
|
||||
} else {
|
||||
resolving_interval = 0;
|
||||
}
|
||||
resolving_source = us;
|
||||
DEBUG_LOG(LOGF_NtpSources, "resolving %s", us->name);
|
||||
DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -285,14 +335,31 @@ NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParame
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler)
|
||||
{
|
||||
resolving_end_handler = handler;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NSR_ResolveSources(void)
|
||||
{
|
||||
/* Try to resolve unresolved sources now */
|
||||
if (resolving_interval) {
|
||||
SCH_RemoveTimeout(resolving_id);
|
||||
resolving_interval--;
|
||||
resolve_sources(NULL);
|
||||
if (unresolved_sources) {
|
||||
/* Make sure no resolving is currently running */
|
||||
if (!resolving_source) {
|
||||
if (resolving_interval) {
|
||||
SCH_RemoveTimeout(resolving_id);
|
||||
resolving_interval--;
|
||||
}
|
||||
resolve_sources(NULL);
|
||||
}
|
||||
} else {
|
||||
/* No unresolved sources, we are done */
|
||||
if (resolving_end_handler)
|
||||
(resolving_end_handler)();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,14 @@ extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type
|
|||
until it succeeds or fails with a non-temporary error. */
|
||||
extern void NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params);
|
||||
|
||||
/* Procedure to try resolve unresolved sources immediately. */
|
||||
/* Function type for handlers to be called back when an attempt
|
||||
* (possibly unsuccessful) to resolve unresolved sources ends */
|
||||
typedef void (*NSR_SourceResolvingEndHandler)(void);
|
||||
|
||||
/* Set the handler, or NULL to disable the notification */
|
||||
extern void NSR_SetSourceResolvingEndHandler(NSR_SourceResolvingEndHandler handler);
|
||||
|
||||
/* Procedure to start resolving unresolved sources immediately */
|
||||
extern void NSR_ResolveSources(void);
|
||||
|
||||
/* Procedure to start all sources */
|
||||
|
|
Loading…
Reference in a new issue