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 */
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
/*
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
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
#elif defined(HAVE_SIGNALED_IO)
(void) set_signal(input_handler);
#endif
+ rfc3927.s_addr = 0xa9fe0000; /* 169.254. */
+ rfc3927_mask.s_addr = 0xffff0000; /* 169.254. */
}
/*
* do standard initialization of interface structure
*/
-static void
+static inline void
init_interface(
endpt *ep
)
endpt enumep;
endpt * ep;
endpt * next_ep;
+ struct in6_addr * psrcadr6;
DPRINTF(3, ("update_interfaces(%d)\n", port));
*/
new_interface_found = FALSE;
+ nonlocal_v4_addr_up = nonlocal_v6_addr_up = FALSE;
iter = NULL;
result = isc_interfaceiter_create(mctx, &iter);
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
#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;
struct interface * lcladr;
sockaddr_u * rmtadr;
r4addr r4a;
+ u_short af;
u_short restrict_mask;
struct peer * p;
l_fp xmt_tx;
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;
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)