]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: allow replacement of sources specified by IP address
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 14 Jan 2021 13:12:54 +0000 (14:12 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 14 Jan 2021 17:17:48 +0000 (18:17 +0100)
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
ntp_sources.c
ntp_sources.h
nts_ntp_client.c
sources.c
util.c
util.h

index d12d6b3e1092f993eecca723c0411c0ca73e006f..c442b48dffb9592d64a66b10a855f1bd84f593f6 100644 (file)
@@ -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)
index c32c82260f248486681788537479278cc31b04e2..63e16de39a59eb937bb35454aff6a75d690355c3 100644 (file)
@@ -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;
 }
 
 /* ================================================== */
index 81530b154ea3d7633250f4c99464c56847e69ed8..cd83598fec4fc46476e22070b8b16e8f5b0732de 100644 (file)
@@ -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 */
index ecc401e883fbddb1f1cc3465119b452a8f4d283a..361b76fe71605a9b3b7391d9e148336c1f351cb0 100644 (file)
@@ -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;
 
index 67bc5d87e79148d1dab81235d114775cbfcbd5f3..63647d26bd3b7c2e83962ae32840798c372a622c 100644 (file)
--- 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 673ca0694d0224a756df8b3af6fdf0693b235a75..31b655bc64c27f50c3b7ffe10cc82048a82704fc 100644 (file)
--- 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 d52a4537f37c5b38190bb33323586b70ca501ab7..b658061af866ccd67f58a944345d9b52cd06bc61 100644 (file)
--- 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);