From: Dave Hart Date: Sat, 29 Jul 2023 21:54:29 +0000 (+0000) Subject: [Bug 3851] Drop pool server when no local address can reach it. X-Git-Tag: NTP_4_2_8P18_RC1~38^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a98168a46cbbee200ac3c60e3b660c1dc4b851f;p=thirdparty%2Fntp.git [Bug 3851] Drop pool server when no local address can reach it. bk: 64c58a95RRDfqzSTmGqYHPhQ7X8vjw --- diff --git a/ChangeLog b/ChangeLog index b0cdccfe5..dcdf94e4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ --- -* [Bug 3846] Use -Wno-format-truncation by default. +* [Bug 3851] Drop pool server when no local address can reach it. + +* [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 diff --git a/include/ntp.h b/include/ntp.h index 258ddd613..a066d6ee7 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -463,9 +463,9 @@ struct peer { #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 */ @@ -804,7 +804,7 @@ struct mon_data { #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 diff --git a/include/ntpd.h b/include/ntpd.h index b560d2986..23880945f 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -128,7 +128,8 @@ extern void io_unsetbclient (void); 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 diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index d08b9e6d0..36cd776b1 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -307,10 +307,10 @@ 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 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; @@ -472,8 +472,6 @@ 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. */ } @@ -1561,13 +1559,11 @@ sau_from_netaddr( 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; } } @@ -1590,6 +1586,30 @@ is_wildcard_addr( } +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 @@ -1768,7 +1788,6 @@ update_interfaces( endpt enumep; endpt * ep; endpt * next_ep; - struct in6_addr * psrcadr6; DPRINTF(3, ("update_interfaces(%d)\n", port)); @@ -1870,19 +1889,12 @@ update_interfaces( * 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; } } /* diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 20271325d..b55e00295 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -472,7 +472,16 @@ transmit( 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. @@ -636,6 +645,7 @@ receive( 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 */ @@ -1450,11 +1460,15 @@ receive( 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++; @@ -4108,9 +4122,9 @@ peer_xmit( 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);