]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: support per-source IP family restriction
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 5 Feb 2024 13:06:52 +0000 (14:06 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 7 Feb 2024 09:23:36 +0000 (10:23 +0100)
Add a new parameter to the NSR_AddSourceByName() function to allow
individual sources to be limited to IPv4 or IPv6 addresses. This doesn't
change the options passed to the resolver. It's just an additional
filter in the processing of resolved addresses following the -4/-6
command-line option of chronyd.

cmdmon.c
conf.c
ntp_sources.c
ntp_sources.h
stubs.c
test/unit/ntp_sources.c

index 9adc9d6edb3cb7460cbd2b1f55761899f0a38e55..d2199a72d715950d216752b45246fc4194f62932 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -789,7 +789,7 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message)
                       NTP_EF_FLAG_EXP_NET_CORRECTION : 0);
   params.sel_options = convert_addsrc_select_options(ntohl(rx_message->data.ntp_source.flags));
 
-  status = NSR_AddSourceByName(name, port, pool, type, &params, NULL);
+  status = NSR_AddSourceByName(name, IPADDR_UNSPEC, port, pool, type, &params, NULL);
   switch (status) {
     case NSR_Success:
       break;
diff --git a/conf.c b/conf.c
index fa74459440cad84eb363e7f931ccd708e306b8e6..9bae265128c40688c05e8ac5e74b2f2a18226f8b 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -1728,8 +1728,9 @@ reload_source_dirs(void)
       /* Add new sources */
       if (pass == 1 && d > 0) {
         source = &new_sources[j];
-        s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool,
-                                source->type, &source->params.params, &new_ids[j]);
+        s = NSR_AddSourceByName(source->params.name, IPADDR_UNSPEC, source->params.port,
+                                source->pool, source->type, &source->params.params,
+                                &new_ids[j]);
 
         if (s == NSR_UnresolvedName) {
           unresolved++;
@@ -1842,8 +1843,8 @@ CNF_AddSources(void)
   for (i = 0; i < ARR_GetSize(ntp_sources); i++) {
     source = (NTP_Source *)ARR_GetElement(ntp_sources, i);
 
-    s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool,
-                            source->type, &source->params.params, NULL);
+    s = NSR_AddSourceByName(source->params.name, IPADDR_UNSPEC, source->params.port,
+                            source->pool, source->type, &source->params.params, NULL);
     if (s != NSR_Success && s != NSR_UnresolvedName)
       LOG(LOGS_ERR, "Could not add source %s", source->params.name);
 
index d8bd2d832053526c072cc6cc491a46f129eccdcd..590e5e054c1e486b5e871627da256e829242c112 100644 (file)
@@ -61,6 +61,8 @@ typedef struct {
                                    (may be an IP address) */
   IPAddr resolved_addr;         /* Address resolved from the name, which can be
                                    different from remote_addr (e.g. NTS-KE) */
+  int family;                   /* IP family of acceptable resolved addresses
+                                   (IPADDR_UNSPEC if any) */
   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
@@ -98,6 +100,8 @@ struct UnresolvedSource {
   int pool_id;
   /* Name to be resolved */
   char *name;
+  /* Address family to filter resolved addresses */
+  int family;
   /* Flag indicating addresses should be used in a random order */
   int random_order;
   /* Flag indicating current address should be replaced only if it is
@@ -353,7 +357,7 @@ log_source(SourceRecord *record, int addition, int once_per_pool)
 
 /* Procedure to add a new source */
 static NSR_Status
-add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
+add_source(NTP_Remote_Address *remote_addr, char *name, int family, NTP_Source_Type type,
            SourceParameters *params, int pool_id, uint32_t conf_id)
 {
   SourceRecord *record;
@@ -391,6 +395,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
       record->data = NCR_CreateInstance(remote_addr, type, params, record->name);
       record->remote_addr = NCR_GetRemoteAddress(record->data);
       record->resolved_addr = remote_addr->ip_addr;
+      record->family = family;
       record->pool_id = pool_id;
       record->tentative = 1;
       record->conf_id = conf_id;
@@ -552,6 +557,10 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs
 
     DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr));
 
+    /* Skip addresses not from the requested family */
+    if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.family)
+      continue;
+
     if (us->pool_id != INVALID_POOL) {
       /* In the pool resolving mode, try to replace a source from
          the pool which does not have a real address yet */
@@ -768,14 +777,14 @@ NSR_Status
 NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
               SourceParameters *params, uint32_t *conf_id)
 {
-  return add_source(remote_addr, NULL, type, params, INVALID_POOL,
+  return add_source(remote_addr, NULL, IPADDR_UNSPEC, type, params, INVALID_POOL,
                     get_next_conf_id(conf_id));
 }
 
 /* ================================================== */
 
 NSR_Status
-NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
+NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type,
                     SourceParameters *params, uint32_t *conf_id)
 {
   struct UnresolvedSource *us;
@@ -787,7 +796,9 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
   /* 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 add_source(&remote_addr, name, type, params, INVALID_POOL,
+    if (family != IPADDR_UNSPEC && family != remote_addr.ip_addr.family)
+      return NSR_InvalidAF;
+    return add_source(&remote_addr, name, IPADDR_UNSPEC, type, params, INVALID_POOL,
                       get_next_conf_id(conf_id));
   }
 
@@ -799,6 +810,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
 
   us = MallocNew(struct UnresolvedSource);
   us->name = Strdup(name);
+  us->family = family;
   us->random_order = 0;
   us->refreshment = 0;
 
@@ -835,7 +847,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
   for (i = 0; i < new_sources; i++) {
     if (i > 0)
       remote_addr.ip_addr.addr.id = ++last_address_id;
-    if (add_source(&remote_addr, name, type, params, us->pool_id, cid) != NSR_Success)
+    if (add_source(&remote_addr, name, family, type, params, us->pool_id, cid) != NSR_Success)
       return NSR_TooManySources;
   }
 
@@ -1026,6 +1038,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment)
 
   us = MallocNew(struct UnresolvedSource);
   us->name = Strdup(record->name);
+  us->family = record->family;
   /* Ignore the order of addresses from the resolver to not get
      stuck with a pair of unreachable or otherwise unusable servers
      (e.g. falsetickers) in case the order doesn't change, or a group
index 5aeb1a3da9daf9fabf403bd151f0aaf6e0fdf138..79daf1db5d507b97053c21221ceb3a00afc028e9 100644 (file)
@@ -55,9 +55,12 @@ extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type
 
 /* Procedure to add a new server, peer source, or pool of servers specified by
    name instead of address.  The name is resolved in exponentially increasing
-   intervals until it succeeds or fails with a non-temporary error.  If the
-   name is an address, it is equivalent to NSR_AddSource(). */
-extern NSR_Status NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
+   intervals until it succeeds or fails with a non-temporary error.  The
+   specified family filters resolved addresses.  If the name is an address
+   and its family does not conflict with the specified family, it is equivalent
+   to NSR_AddSource(). */
+extern NSR_Status NSR_AddSourceByName(char *name, int family, int port, int pool,
+                                      NTP_Source_Type type,
                                       SourceParameters *params, uint32_t *conf_id);
 
 extern const char *NSR_StatusToString(NSR_Status status);
diff --git a/stubs.c b/stubs.c
index b729c2f6a6dc69391c84eb21e5da38e7f8de4edd..044d17ed9081b6ba638df9da275194ffc0429fc9 100644 (file)
--- a/stubs.c
+++ b/stubs.c
@@ -201,7 +201,7 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
 }
 
 NSR_Status
-NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
+NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type,
                     SourceParameters *params, uint32_t *conf_id)
 {
   return NSR_TooManySources;
index e3d7c4d5d3386880325ed351193c0a55af05395f..a9bdbad519e41e9f9a0359916097b0192c528bf3 100644 (file)
@@ -125,7 +125,7 @@ void
 test_unit(void)
 {
   char source_line[] = "127.0.0.1 offline", conf[] = "port 0", name[64];
-  int i, j, k, slot, found, pool, prev_n;
+  int i, j, k, family, slot, found, pool, prev_n;
   uint32_t hash = 0, conf_id;
   NTP_Remote_Address addrs[256], addr;
   NTP_Local_Address local_addr;
@@ -216,7 +216,7 @@ test_unit(void)
 
   TEST_CHECK(n_sources == 0);
 
-  status = NSR_AddSourceByName("a b", 0, 0, 0, &source.params, &conf_id);
+  status = NSR_AddSourceByName("a b", IPADDR_UNSPEC, 0, 0, 0, &source.params, &conf_id);
   TEST_CHECK(status == NSR_InvalidName);
 
   local_addr.ip_addr.family = IPADDR_INET4;
@@ -228,11 +228,13 @@ test_unit(void)
   for (i = 0; i < 500; i++) {
     for (j = 0; j < 20; j++) {
       snprintf(name, sizeof (name), "ntp%d.example.net", (int)(random() % 10));
+      family = random() % 2 ? IPADDR_UNSPEC : random() % 2 ? IPADDR_INET4 : IPADDR_INET6;
       pool = random() % 2;
       prev_n = n_sources;
 
       DEBUG_LOG("%d/%d adding source %s pool=%d", i, j, name, pool);
-      status = NSR_AddSourceByName(name, 0, pool, random() % 2 ? NTP_SERVER : NTP_PEER,
+      status = NSR_AddSourceByName(name, family, 0, pool,
+                                   random() % 2 ? NTP_SERVER : NTP_PEER,
                                    &source.params, &conf_id);
       TEST_CHECK(status == NSR_UnresolvedName);
 
@@ -242,11 +244,13 @@ test_unit(void)
       for (us = unresolved_sources; us->next; us = us->next)
         ;
       TEST_CHECK(strcmp(us->name, name) == 0);
+      TEST_CHECK(us->family == family);
       if (pool) {
         TEST_CHECK(us->address.ip_addr.family == IPADDR_UNSPEC && us->pool_id >= 0);
       } else {
         TEST_CHECK(strcmp(NSR_GetName(&us->address.ip_addr), name) == 0);
         TEST_CHECK(find_slot2(&us->address, &slot) == 2);
+        TEST_CHECK(get_record(slot)->family == family);
       }
 
       if (random() % 2) {