From: Dave Hart Date: Thu, 20 Jul 2023 16:52:18 +0000 (+0000) Subject: [Bug 3845] accelerate pool clock_sync when IPv6 has only link-local access. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=85271cefcfe750f372ad268eaa3caa3e40f6756d;p=thirdparty%2Fntp.git [Bug 3845] accelerate pool clock_sync when IPv6 has only link-local access. bk: 64b96642erRO19foEJTsoY4uhk7fnA --- diff --git a/ChangeLog b/ChangeLog index 244e0c6ee..b0cdccfe5 100644 --- 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. + * [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. diff --git a/include/ntpd.h b/include/ntpd.h index ad3e30fbb..b560d2986 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -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 */ diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index bb35ffd68..d08b9e6d0 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -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; diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index f2c592384..20271325d 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -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)