---
-* [Bug 3846] Use -Wno-format-truncation by default.
+* [Bug 3851] Drop pool server when no local address can reach it.
+ <hart@ntp.org>
+* [Bug 3846] Use -Wno-format-truncation by default. <hart@ntp.org>
* [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
#define FLAG_XLEAVE 0x1000 /* interleaved protocol */
#define FLAG_XB 0x2000 /* interleaved broadcast */
#define FLAG_XBOGUS 0x4000 /* interleaved bogus packet */
-#ifdef OPENSSL
+#ifdef AUTOKEY
# define FLAG_ASSOC 0x8000 /* autokey request */
-#endif /* OPENSSL */
+#endif
#define FLAG_TSTAMP_PPS 0x10000 /* PPS source provides absolute timestamp */
#define FLAG_LOOPNONCE 0x20000 /* Use a nonce for the loopback test */
#define MDF_POOL 0x08 /* pool client solicitor */
#define MDF_ACAST 0x10 /* manycast client solicitor */
#define MDF_BCLNT 0x20 /* eph. broadcast/multicast client */
-#define MDF_UCLNT 0x40 /* preemptible manycast or pool client */
+#define MDF_PCLNT 0x40 /* preemptible pool client */
/*
* In the context of struct peer in ntpd, three of the cast_flags bits
* represent configured associations which never receive packets, and
extern void io_multicast_add(sockaddr_u *);
extern void io_multicast_del(sockaddr_u *);
extern void sendpkt (sockaddr_u *, struct interface *, int, struct pkt *, int);
-#ifdef DEBUG
+extern isc_boolean_t is_linklocal(sockaddr_u *psau);
+#ifdef DEBUG_TIMING
extern void collect_timing (struct recvbuf *, const char *, int, l_fp *);
#endif
#ifdef HAVE_SIGNALED_IO
static endpt * wildipv4;
static endpt * wildipv6;
-static struct in_addr rfc3927;
-static struct in_addr rfc3927_mask;
+#define RFC3927_ADDR 0xa9fe0000 /* 169.254. */
+#define RFC3927_MASK 0xffff0000
#define IS_AUTOCONF(addr4) \
- ((NSRCADR(addr4) & rfc3927_mask.s_addr) != rfc3927.s_addr)
+ ((SRCADR(addr4) & RFC3927_MASK) == RFC3927_ADDR)
#ifdef SYS_WINNT
int accept_wildcard_if_for_winnt;
#elif defined(HAVE_SIGNALED_IO)
(void) set_signal(input_handler);
#endif
- rfc3927.s_addr = 0xa9fe0000; /* 169.254. */
- rfc3927_mask.s_addr = 0xffff0000; /* 169.254. */
}
switch (pna->family) {
case AF_INET:
- memcpy(&psau->sa4.sin_addr, &pna->type.in,
- sizeof(psau->sa4.sin_addr));
+ psau->sa4.sin_addr = pna->type.in;
break;
case AF_INET6:
- memcpy(&psau->sa6.sin6_addr, &pna->type.in6,
- sizeof(psau->sa6.sin6_addr));
+ psau->sa6.sin6_addr = pna->type.in6;
break;
}
}
}
+isc_boolean_t
+is_linklocal(
+ sockaddr_u * psau
+)
+{
+ struct in6_addr * p6addr;
+
+ if (IS_IPV6(psau)) {
+ p6addr = &psau->sa6.sin6_addr;
+ if ( IN6_IS_ADDR_LINKLOCAL(p6addr)
+ || IN6_IS_ADDR_SITELOCAL(p6addr)) {
+
+ return TRUE;
+ }
+ } else if (IS_IPV4(psau)) {
+ /* autoconf are link-local 169.254.0.0/16 */
+ if (IS_AUTOCONF(psau)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
/*
* enable/disable re-use of wildcard address socket
endpt enumep;
endpt * ep;
endpt * next_ep;
- struct in6_addr * psrcadr6;
DPRINTF(3, ("update_interfaces(%d)\n", port));
* for IPv4 and IPv6 so we don't solicit pool hosts
* when it can't work.
*/
- if (!(INT_LOOPBACK & enumep.flags)) {
+ if ( !(INT_LOOPBACK & enumep.flags)
+ && !is_linklocal(&enumep.sin)) {
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;
- }
+ nonlocal_v6_addr_up = TRUE;
+ } else {
+ nonlocal_v4_addr_up = TRUE;
}
}
/*
return;
}
- /*
+ /* [Bug 3851] drop pool servers which can no longer be reached. */
+ if (MDF_PCLNT & peer->cast_flags) {
+ if ( (IS_IPV6(&peer->srcadr) && !nonlocal_v6_addr_up)
+ || !nonlocal_v4_addr_up) {
+ unpeer(peer);
+ return;
+ }
+ }
+
+ /*
* In unicast modes the dance is much more intricate. It is
* designed to back off whenever possible to minimize network
* traffic.
keyid_t skeyid = 0; /* key IDs */
u_int32 opcode = 0; /* extension field opcode */
sockaddr_u *dstadr_sin; /* active runway */
+ u_char cast_flags; /* MDF_* flags for newpeer() */
struct peer *peer2; /* aux peer structure pointer */
endpt *match_ep; /* newpeer() local address */
l_fp p_org; /* origin timestamp */
sys_declined++;
return; /* no help */
}
+ cast_flags = MDF_UCAST;
+ if (MDF_POOL & peer2->cast_flags) {
+ cast_flags |= MDF_PCLNT;
+ }
peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr,
r4a.ippeerlimit, MODE_CLIENT, hisversion,
peer2->minpoll, peer2->maxpoll,
(FLAG_PREEMPT | (POOL_FLAG_PMASK & peer2->flags)),
- (MDF_UCAST | MDF_UCLNT), 0, skeyid, sys_ident);
+ cast_flags, 0, skeyid, sys_ident);
if (NULL == peer) {
DPRINTF(2, ("receive: AM_MANYCAST drop: duplicate\n"));
sys_declined++;
keyid_t xkeyid = 0; /* transmit key ID */
l_fp xmt_tx, xmt_ty;
- if (!peer->dstadr) /* drop peers without interface */
+ if (!peer->dstadr) { /* can't send */
return;
-
+ }
xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, peer->version,
peer->hmode);
xpkt.stratum = STRATUM_TO_PKT(sys_stratum);