From eb9e6701fd44479eb33371da5c73b594d61a1041 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 14 Jan 2021 14:12:54 +0100 Subject: [PATCH] ntp: allow replacement of sources specified by IP address For sources specified by an IP address, keep the original address as the source's name and pass it to the NCR instance. Allow the sources to go through the replacement process if their address has changed. This will be useful with NTS-KE negotiation. The IP-based source names are now provided via cmdmon. This means chronyc -n and -N can show two different addresses for a source. --- doc/chronyc.adoc | 9 ++++----- ntp_sources.c | 40 +++++++++++++++++++++------------------- ntp_sources.h | 4 ++-- nts_ntp_client.c | 2 +- sources.c | 2 +- util.c | 10 ++++++++++ util.h | 1 + 7 files changed, 40 insertions(+), 28 deletions(-) diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index d12d6b3..c442b48 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -78,11 +78,10 @@ This option disables resolving of IP addresses to hostnames, e.g. to avoid slow DNS lookups. Long addresses will not be truncated to fit into the column. *-N*:: -This option enables printing of the original names of NTP sources that were -specified in the configuration file, or *chronyc* commands, and are internally -used by *chronyd*. Without the *-n* and *-N* option, the names of NTP sources -are obtained from reverse DNS lookups and can be different from the original -names. +This option enables printing of original hostnames or IP addresses of NTP +sources that were specified in the configuration file, or *chronyc* commands. +Without the *-n* and *-N* option, the printed hostnames are obtained from +reverse DNS lookups and can be different from the specified hostnames. *-c*:: This option enables printing of reports in a comma-separated values (CSV) diff --git a/ntp_sources.c b/ntp_sources.c index c32c822..63e16de 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -53,7 +53,8 @@ typedef struct { (an IPADDR_ID address means the address is not resolved yet) */ 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 as it was specified + (may be an IP address) */ int pool_id; /* ID of the pool from which was this source added or INVALID_POOL */ int tentative; /* Flag indicating there was no valid response @@ -317,6 +318,9 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, /* Find empty bin & check that we don't have the address already */ if (find_slot2(remote_addr, &slot) != 0) { return NSR_AlreadyInUse; + } else if (!name && !UTI_IsIPReal(&remote_addr->ip_addr)) { + /* Name is required for non-real addresses */ + return NSR_InvalidName; } else { if (remote_addr->ip_addr.family != IPADDR_INET4 && remote_addr->ip_addr.family != IPADDR_INET6 && @@ -332,9 +336,10 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, } record = get_record(slot); - record->data = NCR_CreateInstance(remote_addr, type, params, name); + assert(!name || !UTI_IsStringIP(name)); + record->name = Strdup(name ? name : UTI_IPToString(&remote_addr->ip_addr)); + record->data = NCR_CreateInstance(remote_addr, type, params, record->name); record->remote_addr = NCR_GetRemoteAddress(record->data); - record->name = name ? Strdup(name) : NULL; record->pool_id = pool_id; record->tentative = 1; record->conf_id = conf_id; @@ -400,10 +405,10 @@ change_source_address(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr LOG(severity, "Source %s %s %s (%s)", UTI_IPToString(&old_addr->ip_addr), replacement ? "replaced with" : "changed to", - UTI_IPToString(&new_addr->ip_addr), name ? name : ""); + UTI_IPToString(&new_addr->ip_addr), name); } else { LOG(severity, "Source %s (%s) changed port to %d", - UTI_IPToString(&new_addr->ip_addr), name ? name : "", new_addr->port); + UTI_IPToString(&new_addr->ip_addr), name, new_addr->port); } return NSR_Success; @@ -663,8 +668,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, NTP_Remote_Address remote_addr; int i, new_sources, pool_id; - /* If the name is an IP address, don't bother with full resolving now - or later when trying to replace the source */ + /* If the name is an IP address, add the source with the address directly */ if (UTI_StringToIP(name, &remote_addr.ip_addr)) { remote_addr.port = port; return NSR_AddSource(&remote_addr, type, params, conf_id); @@ -796,8 +800,7 @@ clean_source_record(SourceRecord *record) record->remote_addr = NULL; NCR_DestroyInstance(record->data); - if (record->name) - Free(record->name); + Free(record->name); n_sources--; } @@ -870,7 +873,8 @@ resolve_source_replacement(SourceRecord *record) { struct UnresolvedSource *us; - DEBUG_LOG("trying to replace %s", UTI_IPToString(&record->remote_addr->ip_addr)); + DEBUG_LOG("trying to replace %s (%s)", + UTI_IPToString(&record->remote_addr->ip_addr), record->name); us = MallocNew(struct UnresolvedSource); us->name = Strdup(record->name); @@ -894,6 +898,7 @@ NSR_HandleBadSource(IPAddr *address) static struct timespec last_replacement; struct timespec now; SourceRecord *record; + IPAddr ip_addr; double diff; int slot; @@ -902,8 +907,10 @@ NSR_HandleBadSource(IPAddr *address) record = get_record(slot); - /* Only sources with a name can be replaced */ - if (!record->name) + /* Don't try to replace a source specified by an IP address unless the + address changed since the source was added (e.g. by NTS-KE) */ + if (UTI_StringToIP(record->name, &ip_addr) && + UTI_CompareIPs(&record->remote_addr->ip_addr, &ip_addr, NULL) == 0) return; /* Don't resolve names too frequently */ @@ -928,7 +935,7 @@ NSR_RefreshAddresses(void) for (i = 0; i < ARR_GetSize(records); i++) { record = get_record(i); - if (!record->remote_addr || !record->name) + if (!record->remote_addr) continue; resolve_source_replacement(record); @@ -992,17 +999,12 @@ NSR_GetLocalRefid(IPAddr *address) char * NSR_GetName(IPAddr *address) { - SourceRecord *record; int slot; if (!find_slot(address, &slot)) return NULL; - record = get_record(slot); - if (record->name) - return record->name; - - return UTI_IPToString(&record->remote_addr->ip_addr); + return get_record(slot)->name; } /* ================================================== */ diff --git a/ntp_sources.h b/ntp_sources.h index 81530b1..cd83598 100644 --- a/ntp_sources.h +++ b/ntp_sources.h @@ -98,8 +98,8 @@ extern NSR_Status NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, /* Procedure to get local reference ID corresponding to a source */ extern uint32_t NSR_GetLocalRefid(IPAddr *address); -/* Procedure to get the name of a source. If the source doesn't have a name, - it returns a temporary string containing formatted address. */ +/* Procedure to get the name of a source as it was specified (it may be + an IP address) */ extern char *NSR_GetName(IPAddr *address); /* This routine is called by ntp_io when a new packet arrives off the network */ diff --git a/nts_ntp_client.c b/nts_ntp_client.c index ecc401e..361b76f 100644 --- a/nts_ntp_client.c +++ b/nts_ntp_client.c @@ -119,7 +119,7 @@ NNC_CreateInstance(IPSockAddr *nts_address, const char *name, const IPSockAddr * inst->ntp_address = ntp_address; inst->nts_address = *nts_address; - inst->name = name ? Strdup(name) : NULL; + inst->name = !UTI_IsStringIP(name) ? Strdup(name) : NULL; inst->siv = NULL; inst->nke = NULL; diff --git a/sources.c b/sources.c index 67bc5d8..63647d2 100644 --- a/sources.c +++ b/sources.c @@ -581,7 +581,7 @@ log_selection_source(const char *format, SRC_Instance inst) name = source_to_string(inst); ntp_name = inst->type == SRC_NTP ? NSR_GetName(inst->ip_addr) : NULL; - if (ntp_name && strcmp(name, ntp_name) != 0) + if (ntp_name) snprintf(buf, sizeof (buf), "%s (%s)", name, ntp_name); else snprintf(buf, sizeof (buf), "%s", name); diff --git a/util.c b/util.c index 673ca06..31b655b 100644 --- a/util.c +++ b/util.c @@ -360,6 +360,16 @@ UTI_StringToIP(const char *addr, IPAddr *ip) /* ================================================== */ +int +UTI_IsStringIP(const char *string) +{ + IPAddr ip; + + return UTI_StringToIP(string, &ip); +} + +/* ================================================== */ + int UTI_StringToIdIP(const char *addr, IPAddr *ip) { diff --git a/util.h b/util.h index d52a453..b658061 100644 --- a/util.h +++ b/util.h @@ -109,6 +109,7 @@ extern char *UTI_RefidToString(uint32_t ref_id); extern char *UTI_IPToString(const IPAddr *ip); extern int UTI_StringToIP(const char *addr, IPAddr *ip); +extern int UTI_IsStringIP(const char *string); extern int UTI_StringToIdIP(const char *addr, IPAddr *ip); extern int UTI_IsIPReal(const IPAddr *ip); extern uint32_t UTI_IPToRefid(const IPAddr *ip);