]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3851] Drop pool server when no local address can reach it.
authorDave Hart <hart@ntp.org>
Sat, 29 Jul 2023 21:54:29 +0000 (21:54 +0000)
committerDave Hart <hart@ntp.org>
Sat, 29 Jul 2023 21:54:29 +0000 (21:54 +0000)
bk: 64c58a95RRDfqzSTmGqYHPhQ7X8vjw

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

index b0cdccfe5d5dd721c9e729752ff42b796bd042ad..dcdf94e4a064d2c63655c3c4e6f3a0f8d9d3d2e9 100644 (file)
--- 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.
+             <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
index 258ddd6138f71ba4aaeb3194f80420fd0cbad97b..a066d6ee782a5ddca5cd0c198ba12ec24f7d7cbd 100644 (file)
@@ -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
index b560d29864376237e2bfc99b82b70aab40b933ec..23880945ff38d18e4505f2f209a9dec66c5e71b5 100644 (file)
@@ -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
index d08b9e6d022ec29ab10fc4c2565d662dd7634e5a..36cd776b1f1ec12d3c3714e2ad04f2433f257cde 100644 (file)
@@ -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;
                        }
                }
                /*
index 20271325dde9451477c1c3f6af4ade81d103ea55..b55e0029519f0332f2a4e567043bf0921af16a7f 100644 (file)
@@ -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);