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,
|
NSR_AddUnresolvedSource(ntp_sources[i].params.name, ntp_sources[i].params.port,
|
||||||
ntp_sources[i].type, &ntp_sources[i].params.params);
|
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
|
static void
|
||||||
post_init_ntp_hook(void *anything)
|
ntp_source_resolving_end(void)
|
||||||
{
|
{
|
||||||
if (ref_mode == REF_ModeInitStepSlew) {
|
NSR_SetSourceResolvingEndHandler(NULL);
|
||||||
/* 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();
|
|
||||||
if (reload) {
|
if (reload) {
|
||||||
/* Note, we want reload to come well after the initialisation from
|
/* Note, we want reload to come well after the initialisation from
|
||||||
the real time clock - this gives us a fighting chance that the
|
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
|
static void
|
||||||
reference_mode_end(int result)
|
reference_mode_end(int result)
|
||||||
{
|
{
|
||||||
|
|
135
ntp_sources.c
135
ntp_sources.c
|
@ -37,7 +37,7 @@
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "nameserv.h"
|
#include "nameserv_async.h"
|
||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
@ -77,9 +77,14 @@ struct UnresolvedSource {
|
||||||
static struct UnresolvedSource *unresolved_sources = NULL;
|
static struct UnresolvedSource *unresolved_sources = NULL;
|
||||||
static int resolving_interval = 0;
|
static int resolving_interval = 0;
|
||||||
static SCH_TimeoutID resolving_id;
|
static SCH_TimeoutID resolving_id;
|
||||||
|
static struct UnresolvedSource *resolving_source = NULL;
|
||||||
|
static NSR_SourceResolvingEndHandler resolving_end_handler = NULL;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Forward prototypes */
|
/* Forward prototypes */
|
||||||
|
|
||||||
|
static void resolve_sources(void *arg);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slew_sources(struct timeval *raw,
|
slew_sources(struct timeval *raw,
|
||||||
struct timeval *cooked,
|
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
|
static void
|
||||||
resolve_sources(void *arg)
|
resolve_sources(void *arg)
|
||||||
{
|
{
|
||||||
NTP_Remote_Address address;
|
struct UnresolvedSource *us;
|
||||||
struct UnresolvedSource *us, **i;
|
|
||||||
DNS_Status s;
|
assert(!resolving_source);
|
||||||
|
|
||||||
DNS_Reload();
|
DNS_Reload();
|
||||||
|
|
||||||
for (i = &unresolved_sources; *i; ) {
|
/* Start with the first source in the list, name_resolve_handler
|
||||||
us = *i;
|
will iterate over the rest */
|
||||||
s = DNS_Name2IPAddress(us->name, &address.ip_addr);
|
us = unresolved_sources;
|
||||||
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;
|
|
||||||
|
|
||||||
Free(us->name);
|
resolving_source = us;
|
||||||
Free(us);
|
DEBUG_LOG(LOGF_NtpSources, "resolving %s", us->name);
|
||||||
}
|
DNS_Name2IPAddressAsync(us->name, name_resolve_handler, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
@ -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
|
void
|
||||||
NSR_ResolveSources(void)
|
NSR_ResolveSources(void)
|
||||||
{
|
{
|
||||||
/* Try to resolve unresolved sources now */
|
/* Try to resolve unresolved sources now */
|
||||||
if (resolving_interval) {
|
if (unresolved_sources) {
|
||||||
SCH_RemoveTimeout(resolving_id);
|
/* Make sure no resolving is currently running */
|
||||||
resolving_interval--;
|
if (!resolving_source) {
|
||||||
resolve_sources(NULL);
|
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. */
|
until it succeeds or fails with a non-temporary error. */
|
||||||
extern void NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params);
|
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);
|
extern void NSR_ResolveSources(void);
|
||||||
|
|
||||||
/* Procedure to start all sources */
|
/* Procedure to start all sources */
|
||||||
|
|
Loading…
Reference in a new issue