Add delayed name resolving for servers and peers
Resolving is retried in increasing intervals (maximum is one hour) until it succeeds or fails with a non-temporary error. Unresolved sources are included in the activity report as offline sources and the online command can be used to retry it immediately. This could be improved by resolving in a separate thread/process to avoid blocking.
This commit is contained in:
parent
3d260d41b3
commit
aa91c608f4
6 changed files with 137 additions and 19 deletions
7
client.c
7
client.c
|
@ -902,6 +902,13 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||
status = CPS_ParseNTPSourceAdd(line, &data);
|
||||
switch (status) {
|
||||
case CPS_Success:
|
||||
/* Don't retry name resolving */
|
||||
if (data.ip_addr.family == IPADDR_UNSPEC) {
|
||||
Free(data.name);
|
||||
fprintf(stderr, "Invalid host/IP address\n");
|
||||
break;
|
||||
}
|
||||
|
||||
msg->data.ntp_source.port = htonl((unsigned long) data.port);
|
||||
UTI_IPHostToNetwork(&data.ip_addr, &msg->data.ntp_source.ip_addr);
|
||||
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
|
||||
|
|
12
cmdparse.c
12
cmdparse.c
|
@ -33,6 +33,7 @@
|
|||
#include "sysincl.h"
|
||||
|
||||
#include "cmdparse.h"
|
||||
#include "memory.h"
|
||||
#include "nameserv.h"
|
||||
|
||||
#define MAXLEN 2047
|
||||
|
@ -66,6 +67,10 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
s = DNS_Name2IPAddress(hostname, &src->ip_addr);
|
||||
if (s == DNS_Success) {
|
||||
ok = 1;
|
||||
src->name = NULL;
|
||||
} else if (s == DNS_TryAgain) {
|
||||
ok = 1;
|
||||
src->ip_addr.family = IPADDR_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,6 +165,13 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
} while (!done);
|
||||
}
|
||||
|
||||
if (ok && src->ip_addr.family == IPADDR_UNSPEC) {
|
||||
n = strlen(hostname);
|
||||
src->name = MallocArray(char, n + 1);
|
||||
strncpy(src->name, hostname, n);
|
||||
src->name[n] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
IPAddr ip_addr;
|
||||
char *name;
|
||||
unsigned short port;
|
||||
SourceParameters params;
|
||||
} CPS_NTP_Source;
|
||||
|
|
32
conf.c
32
conf.c
|
@ -262,9 +262,7 @@ static int line_number;
|
|||
|
||||
typedef struct {
|
||||
NTP_Source_Type type;
|
||||
IPAddr ip_addr;
|
||||
unsigned short port;
|
||||
SourceParameters params;
|
||||
CPS_NTP_Source params;
|
||||
} NTP_Source;
|
||||
|
||||
#define MAX_NTP_SOURCES 64
|
||||
|
@ -355,23 +353,14 @@ CNF_ReadFile(const char *filename)
|
|||
static void
|
||||
parse_source(const char *line, NTP_Source_Type type)
|
||||
{
|
||||
int i;
|
||||
NTP_Source s;
|
||||
CPS_Status status;
|
||||
CPS_NTP_Source params;
|
||||
|
||||
s.type = type;
|
||||
status = CPS_ParseNTPSourceAdd(line, ¶ms);
|
||||
ntp_sources[n_ntp_sources].type = type;
|
||||
status = CPS_ParseNTPSourceAdd(line, &ntp_sources[n_ntp_sources].params);
|
||||
|
||||
switch (status) {
|
||||
case CPS_Success:
|
||||
s.port = params.port;
|
||||
s.ip_addr = params.ip_addr;
|
||||
s.params = params.params;
|
||||
|
||||
i = n_ntp_sources++;
|
||||
ntp_sources[i] = s;
|
||||
|
||||
n_ntp_sources++;
|
||||
break;
|
||||
case CPS_BadOption:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unrecognized subcommand at line %d", line_number);
|
||||
|
@ -1191,11 +1180,16 @@ CNF_AddSources(void) {
|
|||
int i;
|
||||
|
||||
for (i=0; i<n_ntp_sources; i++) {
|
||||
server.ip_addr = ntp_sources[i].ip_addr;
|
||||
memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
|
||||
server.port = ntp_sources[i].port;
|
||||
if (ntp_sources[i].params.ip_addr.family != IPADDR_UNSPEC) {
|
||||
server.ip_addr = ntp_sources[i].params.ip_addr;
|
||||
memset(&server.local_ip_addr, 0, sizeof (server.local_ip_addr));
|
||||
server.port = ntp_sources[i].params.port;
|
||||
|
||||
NSR_AddSource(&server, ntp_sources[i].type, &ntp_sources[i].params);
|
||||
NSR_AddSource(&server, ntp_sources[i].type, &ntp_sources[i].params.params);
|
||||
} else {
|
||||
NSR_AddUnresolvedSource(ntp_sources[i].params.name, ntp_sources[i].params.port,
|
||||
ntp_sources[i].type, &ntp_sources[i].params.params);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#include "util.h"
|
||||
#include "logging.h"
|
||||
#include "local.h"
|
||||
#include "memory.h"
|
||||
#include "nameserv.h"
|
||||
#include "sched.h"
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
|
@ -60,6 +63,19 @@ static int n_sources;
|
|||
/* The largest number of sources we want to have stored in the hash table */
|
||||
#define MAX_SOURCES 64
|
||||
|
||||
/* Source with unknown address (which may be resolved later) */
|
||||
struct UnresolvedSource {
|
||||
char *name;
|
||||
int port;
|
||||
NTP_Source_Type type;
|
||||
SourceParameters params;
|
||||
struct UnresolvedSource *next;
|
||||
};
|
||||
|
||||
static struct UnresolvedSource *unresolved_sources = NULL;
|
||||
static int resolving_interval = 0;
|
||||
static SCH_TimeoutID resolving_id;
|
||||
|
||||
/* ================================================== */
|
||||
/* Forward prototypes */
|
||||
static void
|
||||
|
@ -203,6 +219,75 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
resolve_sources(void *arg)
|
||||
{
|
||||
NTP_Remote_Address address;
|
||||
struct UnresolvedSource *us, **i;
|
||||
DNS_Status s;
|
||||
|
||||
memset(&address.local_ip_addr, 0, sizeof (address.local_ip_addr));
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Procedure to add a new server or peer source, but instead of an IP address
|
||||
only a name is provided */
|
||||
void
|
||||
NSR_AddUnresolvedSource(char *name, int port, NTP_Source_Type type, SourceParameters *params)
|
||||
{
|
||||
struct UnresolvedSource *us, **i;
|
||||
|
||||
us = MallocNew(struct UnresolvedSource);
|
||||
|
||||
us->name = name;
|
||||
us->port = port;
|
||||
us->type = type;
|
||||
us->params = *params;
|
||||
us->next = NULL;
|
||||
|
||||
for (i = &unresolved_sources; *i; i = &(*i)->next)
|
||||
;
|
||||
*i = us;
|
||||
|
||||
if (!resolving_interval) {
|
||||
resolving_interval = 2;
|
||||
resolving_id = SCH_AddTimeoutByDelay(7 * (1 << resolving_interval), resolve_sources, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Procedure to remove a source. We don't bother whether the port
|
||||
address is matched - we're only interested in removing a record for
|
||||
the right IP address. Thus the caller can specify the port number
|
||||
|
@ -311,6 +396,13 @@ NSR_TakeSourcesOnline(IPAddr *mask, IPAddr *address)
|
|||
}
|
||||
}
|
||||
|
||||
if (resolving_interval) {
|
||||
/* Try to resolve any unresolved sources now */
|
||||
SCH_RemoveTimeout(resolving_id);
|
||||
resolving_interval--;
|
||||
resolve_sources(NULL);
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
|
@ -472,6 +564,7 @@ void
|
|||
NSR_GetActivityReport(RPT_ActivityReport *report)
|
||||
{
|
||||
int i;
|
||||
struct UnresolvedSource *us;
|
||||
|
||||
report->online = 0;
|
||||
report->offline = 0;
|
||||
|
@ -484,6 +577,12 @@ NSR_GetActivityReport(RPT_ActivityReport *report)
|
|||
&report->burst_online, &report->burst_offline);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add unresolved sources to offline count */
|
||||
for (us = unresolved_sources; us; us = us->next) {
|
||||
report->offline++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@ typedef enum {
|
|||
/* Procedure to add a new server or peer source. */
|
||||
extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params);
|
||||
|
||||
/* Procedure to add a new server or peer source with currently unknown address.
|
||||
The name will be periodically resolved in exponentially increasing intervals
|
||||
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 remove a source */
|
||||
extern NSR_Status NSR_RemoveSource(NTP_Remote_Address *remote_addr);
|
||||
|
||||
|
|
Loading…
Reference in a new issue