]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3845] accelerate pool clock_sync when IPv6 has only link-local access.
authorDave Hart <hart@ntp.org>
Thu, 20 Jul 2023 16:52:18 +0000 (16:52 +0000)
committerDave Hart <hart@ntp.org>
Thu, 20 Jul 2023 16:52:18 +0000 (16:52 +0000)
bk: 64b96642erRO19foEJTsoY4uhk7fnA

ChangeLog
include/ntpd.h
ntpd/ntp_io.c
ntpd/ntp_proto.c

index 244e0c6ee1600d6e47221000269f5e0dea64fe80..b0cdccfe5d5dd721c9e729752ff42b796bd042ad 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
 ---
 
 * [Bug 3846] Use -Wno-format-truncation by default.
+* [Bug 3845] accelerate pool clock_sync when IPv6 has only link-local access.
+             <hart@ntp.org>
 * [Bug 3841] 4.2.8p17 build break w/ gcc 12 -Wformat-security without -Wformat
              Need to remove --Wformat-security when removing -Wformat to
              silence numerous libopts warnings.  <hart@ntp.org>
index ad3e30fbb8899616471a4ca6a387c2dac83905cf..b560d29864376237e2bfc99b82b70aab40b933ec 100644 (file)
@@ -381,7 +381,9 @@ extern volatile u_long handler_pkts;        /* number of pkts received by handler */
 extern u_long  io_timereset;           /* time counters were reset */
 
 /* ntp_io.c */
-extern  int    disable_dynamic_updates;
+extern int     disable_dynamic_updates;/* scan interfaces once only */
+extern int     nonlocal_v4_addr_up;    /* should we try IPv4 pool? */
+extern int     nonlocal_v6_addr_up;    /* should we try IPv6 pool? */
 extern u_int   sys_ifnum;              /* next .ifnum to assign */
 extern endpt * any_interface;          /* IPv4 wildcard */
 extern endpt * any6_interface;         /* IPv6 wildcard */
index bb35ffd685116c85b0354375262720b50c7bd177..d08b9e6d022ec29ab10fc4c2565d662dd7634e5a 100644 (file)
@@ -182,6 +182,8 @@ u_int sys_ifnum;                    /* next .ifnum to assign */
 int ninterfaces;                       /* Total number of interfaces */
 
 int disable_dynamic_updates;           /* scan interfaces once only */
+int nonlocal_v4_addr_up;               /* should we try IPv4 pool? */
+int nonlocal_v6_addr_up;               /* should we try IPv6 pool? */
 
 #ifdef REFCLOCK
 /*
@@ -210,7 +212,7 @@ static int  update_interfaces(u_short, interface_receiver_t,
 static void    remove_interface(endpt *);
 static endpt * create_interface(u_short, endpt *);
 
-static int     is_wildcard_addr        (const sockaddr_u *);
+static inline int is_wildcard_addr(const sockaddr_u *psau);
 
 /*
  * Multicast functions
@@ -305,6 +307,11 @@ endpt *            mc6_list;       /* IPv6 mcast-capable unicast endpts */
 static endpt * wildipv4;
 static endpt * wildipv6;
 
+static struct in_addr  rfc3927;
+static struct in_addr  rfc3927_mask;
+#define                IS_AUTOCONF(addr4)                                      \
+       ((NSRCADR(addr4) & rfc3927_mask.s_addr) != rfc3927.s_addr)
+
 #ifdef SYS_WINNT
 int accept_wildcard_if_for_winnt;
 #else
@@ -465,6 +472,8 @@ init_io(void)
 #elif defined(HAVE_SIGNALED_IO)
        (void) set_signal(input_handler);
 #endif
+       rfc3927.s_addr = 0xa9fe0000;            /* 169.254. */
+       rfc3927_mask.s_addr = 0xffff0000;       /* 169.254. */
 }
 
 
@@ -743,7 +752,7 @@ interface_enumerate(
 /*
  * do standard initialization of interface structure
  */
-static void
+static inline void
 init_interface(
        endpt *ep
        )
@@ -1759,6 +1768,7 @@ update_interfaces(
        endpt                   enumep;
        endpt *                 ep;
        endpt *                 next_ep;
+       struct in6_addr *       psrcadr6;
 
        DPRINTF(3, ("update_interfaces(%d)\n", port));
 
@@ -1769,6 +1779,7 @@ update_interfaces(
         */
 
        new_interface_found = FALSE;
+       nonlocal_v4_addr_up = nonlocal_v6_addr_up = FALSE;
        iter = NULL;
        result = isc_interfaceiter_create(mctx, &iter);
 
@@ -1854,6 +1865,26 @@ update_interfaces(
                if (!is_valid(&enumep.sin, isc_if.name))
                        continue;
 
+               /*
+                * Keep track of having non-linklocal connectivity
+                * for IPv4 and IPv6 so we don't solicit pool hosts
+                * when it can't work.
+                */
+               if (!(INT_LOOPBACK & enumep.flags)) {
+                       if (IS_IPV6(&enumep.sin)) {
+                               psrcadr6 = &enumep.sin.sa6.sin6_addr;
+                               if (   !IN6_IS_ADDR_LINKLOCAL(psrcadr6)
+                                   && !IN6_IS_ADDR_SITELOCAL(psrcadr6)) {
+               
+                                       nonlocal_v6_addr_up = TRUE;
+                               }
+                       } else {        /* ipv4 */
+                               /* rfc3927 are link-local 169.254.0.0/16 */
+                               if (IS_AUTOCONF(&enumep.sin)) {
+                                       nonlocal_v4_addr_up = TRUE;
+                               }
+                       }
+               }
                /*
                 * map to local *address* in order to map all duplicate
                 * interfaces to an endpt structure with the appropriate
@@ -2017,8 +2048,8 @@ update_interfaces(
 #ifdef MCAST
        /*
         * Check multicast interfaces and try to join multicast groups if
-         * not joined yet.
-         */
+        * not joined yet.
+        */
        for (ep = ep_list; ep != NULL; ep = ep->elink) {
                remaddr_t *entry;
 
index f2c59238432ae6979a31933df972624d42116260..20271325dde9451477c1c3f6af4ade81d103ea55 100644 (file)
@@ -4808,6 +4808,7 @@ pool_xmit(
        struct interface *      lcladr;
        sockaddr_u *            rmtadr;
        r4addr                  r4a;
+       u_short                 af;
        u_short                 restrict_mask;
        struct peer *           p;
        l_fp                    xmt_tx;
@@ -4819,6 +4820,16 @@ pool_xmit(
                        free(pool->addrs);
                        pool->addrs = NULL;
                }
+               af = AF(&pool->srcadr);
+               if (   (AF_INET == af && !nonlocal_v4_addr_up)
+                   || (AF_INET6 == af && !nonlocal_v6_addr_up)
+                   || (   AF_UNSPEC == af
+                       && !nonlocal_v4_addr_up
+                       && !nonlocal_v6_addr_up)) {
+
+                       /* POOL DNS query would be useless [Bug 3845] */
+                       return;
+               }
                ZERO(hints);
                hints.ai_family = AF(&pool->srcadr);
                hints.ai_socktype = SOCK_DGRAM;
@@ -4843,8 +4854,13 @@ pool_xmit(
 
        do {
                /* copy_addrinfo_list ai_addr points to a sockaddr_u */
-               rmtadr = (sockaddr_u *)(void *)pool->ai->ai_addr;
+               rmtadr = (sockaddr_u*)(void*)pool->ai->ai_addr;
                pool->ai = pool->ai->ai_next;
+               /* do not solicit when hopeless [Bug 3845] */
+               if (   (IS_IPV4(rmtadr) && !nonlocal_v4_addr_up)
+                   || (IS_IPV6(rmtadr) && !nonlocal_v6_addr_up)) {
+                       continue;
+               }
                p = findexistingpeer(rmtadr, NULL, NULL, MODE_CLIENT, 0, NULL);
        } while (p != NULL && pool->ai != NULL);
        if (p != NULL)