From: Miroslav Lichvar Date: Fri, 25 Apr 2014 14:58:21 +0000 (+0200) Subject: ntp: use async name resolving for NTP sources X-Git-Tag: 1.30-pre1~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ee357d2304dec43ca6decad222710ba3fa46571;p=thirdparty%2Fchrony.git 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). --- diff --git a/conf.c b/conf.c index 3a176e11..e19c5d95 100644 --- a/conf.c +++ b/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(); } /* ================================================== */ diff --git a/main.c b/main.c index 4de36697..acaaf0d1 100644 --- a/main.c +++ b/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); - } - - /* Close the pipe to the foreground process so it can exit */ - LOG_CloseParentFd(); + NSR_SetSourceResolvingEndHandler(NULL); - 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) { diff --git a/ntp_sources.c b/ntp_sources.c index 7836bfa5..1dc57543 100644 --- a/ntp_sources.c +++ b/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, @@ -219,45 +224,90 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam /* ================================================== */ static void -resolve_sources(void *arg) +name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything) { + struct UnresolvedSource *us, **i, *next; NTP_Remote_Address address; - struct UnresolvedSource *us, **i; - DNS_Status s; - DNS_Reload(); + us = (struct UnresolvedSource *)anything; - 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) { + 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); - } else { + break; + case DNS_Failure: LOG(LOGS_WARN, LOGF_NtpSources, "Invalid host %s", us->name); - } - - *i = us->next; + break; + default: + assert(0); + } + + next = us->next; - Free(us->name); - Free(us); + 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; + } + } } - if (unresolved_sources) { - /* Try again later */ - if (resolving_interval < 9) - resolving_interval++; - resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL); + 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 { - resolving_interval = 0; + /* 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) +{ + struct UnresolvedSource *us; + + assert(!resolving_source); + + DNS_Reload(); + + /* Start with the first source in the list, name_resolve_handler + will iterate over the rest */ + us = unresolved_sources; + + resolving_source = us; + DEBUG_LOG(LOGF_NtpSources, "resolving %s", us->name); + DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us); +} + +/* ================================================== */ + /* Procedure to add a new server or peer source, but instead of an IP address only a name is provided */ void @@ -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)(); } } diff --git a/ntp_sources.h b/ntp_sources.h index cb25e5f4..e6cb39f5 100644 --- a/ntp_sources.h +++ b/ntp_sources.h @@ -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 */