]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3901] LIB_GETBUF isn't thread-safe.
authorDave Hart <hart@ntp.org>
Mon, 22 Jan 2024 06:54:06 +0000 (06:54 +0000)
committerDave Hart <hart@ntp.org>
Mon, 22 Jan 2024 06:54:06 +0000 (06:54 +0000)
[Bug 3900] fast_xmit() selects wrong local addr responding to mcast on
           Windows.
[Bug 3888] ntpd with multiple same-subnet IPs using manycastclient creates
           duplicate associations.
Remove useless pointer to Windows Help from system error messages.
Avoid newlines within Windows error messages.
Ensure unique association IDs if wrapped.
Write frequency file to 6 digits after decimal.
Unpeer on shutdown as long done on POSIX systems.

Simplify calc_addr_distance().
Clamp min/maxpoll in edge cases in newpeer().
Quiet local addr change logginig when unpeering.
Correct missing arg for %s printf specifier in
  send_blocking_resp_internal().

bk: 65ae110eFPxXkBR_6G30Dthy7bfOzQ

12 files changed:
ChangeLog
include/lib_strbuf.h
include/ntp.h
libntp/lib/isc/win32/strerror.c
libntp/lib_strbuf.c
libntp/work_thread.c
ntpd/ntp_io.c
ntpd/ntp_peer.c
ntpd/ntp_proto.c
ntpd/ntp_util.c
ntpq/ntpq-subs.c
ports/winnt/ntpd/ntservice.c

index 25f5ad5a04a4b33ba73cf12471665bcb64b9db89..767326838c591a7ca9a28af1390a9f8b81a780a9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 ---
 
+* [Bug 3901] LIB_GETBUF isn't thread-safe. <hart@ntp.org>
+* [Bug 3900] fast_xmit() selects wrong local addr responding to mcast on
+             Windows. <hart@ntp.org>
+* [Bug 3888] ntpd with multiple same-subnet IPs using manycastclient creates
+             duplicate associations. <hart@ntp.org>
 * [Bug 3872] Ignore restrict mask for hostname. <hart@ntp.org>
 * [Bug 3871] 4.2.8p17 build without hopf6021 refclock enabled fails.
              Reported by Hans Mayer.  Moved NONEMPTY_TRANSLATION_UNIT
 * Remove dead code libntp/numtohost.c and its unit tests. <hart@ntp.org>
 * Remove class A, B, C IPv4 distinctions in netof(). <hart@ntp.org>
 * Use NONEMPTY_COMPILATION_UNIT in more conditionally-compiled files.
+* Remove useless pointer to Windows Help from system error messages.
+* Avoid newlines within Windows error messages. <hart@ntp.org>
+* Ensure unique association IDs if wrapped. <hart@ntp.org>
+* Simplify calc_addr_distance(). <hart@ntp.org>
+* Clamp min/maxpoll in edge cases in newpeer(). <hart@ntp.org>
+* Quiet local addr change logging when unpeering. <hart@ntp.org>
+* Correct missing arg for %s printf specifier in 
+  send_blocking_resp_internal(). <hart@ntp.org>
 
 ---
 (4.2.8p17) 2023/06/06 Released by Harlan Stenn <stenn@ntp.org>
index 7c79713c4aa4bc68f3072ceb6b4727083fbc3bcd..89da450a5547ff07e727ba74bd2fe4fa14fa738c 100644 (file)
@@ -7,14 +7,8 @@
 #include <ntp_types.h>
 #include <ntp_malloc.h>                        /* for zero_mem() */
 
-/*
- * Sizes of things
- */
-#define LIB_NUMBUF     10
 #define        LIB_BUFLENGTH   128
 
-extern char *  lib_stringbuf[LIB_NUMBUF];
-extern int     lib_nextbuf;
 extern int     lib_inited;
 extern int     ipv4_works;
 extern int     ipv6_works;
@@ -22,16 +16,17 @@ extern int  ipv6_works;
 extern void    init_lib(void);
 
 /*
- * Macro to get a pointer to the next buffer
+ * Get a pointer to the next string buffer of LIB_BUFLENGTH octets.
+ * New and modified code should use buf = lib_getbuf() directly to
+ * provide clarity for folks familiar with common C style, but there's
+ * no need to churn the history with a mechanical switch away from
+ * LIB_GETBUF(buf).
  */
-#define        LIB_GETBUF(bufp)                                                \
-       do {                                                            \
-               if (!lib_inited) {                                      \
-                       init_lib();                                     \
-               }                                                       \
-               zero_mem(lib_stringbuf[lib_nextbuf], LIB_BUFLENGTH);    \
-               (bufp) = lib_stringbuf[lib_nextbuf++];                  \
-               lib_nextbuf %= COUNTOF(lib_stringbuf);                  \
+extern char* lib_getbuf(void);
+
+#define        LIB_GETBUF(bufp)                \
+       do {                            \
+               (bufp) = lib_getbuf();  \
        } while (FALSE)
 
 #endif /* LIB_STRBUF_H */
index 9ff5a408f15dfa98dfcfe60a930288d43cc75558..11fb3c35b05a961e18dbe8c3ffa9c9d90e78ef89 100644 (file)
@@ -468,6 +468,7 @@ struct peer {
 #endif
 #define FLAG_TSTAMP_PPS        0x10000 /* PPS source provides absolute timestamp */
 #define FLAG_LOOPNONCE 0x20000 /* Use a nonce for the loopback test */
+#define FLAG_DISABLED  0x40000 /* peer is being torn down */
 
 /*
  * Definitions for the clear() routine.  We use memset() to clear
@@ -703,6 +704,10 @@ struct pkt {
 #define        max(a,b)        (((a) > (b)) ? (a) : (b))
 #define        min3(a,b,c)     min(min((a),(b)), (c))
 
+/* clamp a value within a range */
+#define CLAMP(val, minval, maxval)                             \
+                       max((minval), min((val), (maxval)))
+
 
 /*
  * Configuration items.  These are for the protocol module (proto_config())
index 40c5da002f8c51bcc91b36535120f89e0e5720b3..823e9c1b29e0fcda9d33b503337e60adb868910b 100644 (file)
@@ -88,19 +88,46 @@ isc__strerror(int num, char *buf, size_t size) {
  */
 char *
 FormatError(int error) {
-       LPVOID lpMsgBuf = NULL;
+       char *lpMsgBuf = NULL;
+       char *pch;
+       const char boiler[] =
+               " For information about network troubleshooting, see Windows Help.";
+       size_t last;
+
        FormatMessage( 
                FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                FORMAT_MESSAGE_FROM_SYSTEM | 
-               FORMAT_MESSAGE_IGNORE_INSERTS,
+               (FORMAT_MESSAGE_MAX_WIDTH_MASK - 1),
                NULL,
                error,
                /* Default language */
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-               (LPTSTR) &lpMsgBuf,
+               (LPTSTR)(PVOID)&lpMsgBuf,
                0,
                NULL); 
 
+       /* remove useless boilerplate */
+       pch = strstr(lpMsgBuf, boiler);
+       if (pch != NULL) {
+               *pch = '\0';
+       }
+
+       /* strip any trailing CR/LF */
+       if (lpMsgBuf != NULL) {
+               last = strlen(lpMsgBuf);
+               if (last > 0) {
+                       --last;
+               }
+               while ('\n' == lpMsgBuf[last] ||
+                      '\r' == lpMsgBuf[last]) {
+
+                       lpMsgBuf[last] = '\0';
+                       if (last > 0) {
+                               --last;
+                       }
+               }
+       }
+
        return (lpMsgBuf);
 }
 
index 69df900bae70ab5b61e271e5f25e026b04580f62..225c430f7e0278476787e75e357eebe694856202 100644 (file)
@@ -5,25 +5,26 @@
 #include <config.h>
 #endif
 
+#include <isc/mutex.h>
 #include <isc/net.h>
 #include <isc/result.h>
 
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
-
 #include "lib_strbuf.h"
 
+#define LIB_NUMBUF     10
 
 /*
  * Storage declarations
  */
-static char    lib_stringbuf_storage[LIB_NUMBUF * LIB_BUFLENGTH];
-char *         lib_stringbuf[LIB_NUMBUF];
-int            lib_nextbuf;
-int            lib_inited;
-int            ipv4_works;
-int            ipv6_works;
-int            debug;
+static char            lib_stringbuf_storage[LIB_NUMBUF][LIB_BUFLENGTH];
+static char *          lib_stringbuf[LIB_NUMBUF];
+int                    lib_inited;
+static isc_mutex_t     lib_mutex;
+int                    ipv4_works;
+int                    ipv6_works;
+int                    debug;
 
 /*
  * initialization routine.  Might be needed if the code is ROMized.
@@ -31,18 +32,41 @@ int         debug;
 void
 init_lib(void)
 {
-       u_int           u;
+       u_int   u;
 
-       if (lib_inited)
+       if (lib_inited) {
                return;
+       }
        ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
        ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
        init_systime();
-       /* avoid -Wrestrict warnings by keeping a pointer to each buffer */
-       lib_stringbuf[0] = lib_stringbuf_storage;
-       for (u = 1; u < COUNTOF(lib_stringbuf); u++) {
-               lib_stringbuf[u] = lib_stringbuf[u - 1] + LIB_BUFLENGTH;
+       /*
+        * Avoid -Wrestrict warnings by keeping a pointer to each buffer
+        * so the compiler can see copying from one buffer to another is
+        * not violating restrict qualifiers on, e.g. memcpy() args.
+        */
+       for (u = 0; u < COUNTOF(lib_stringbuf); u++) {
+               lib_stringbuf[u] = lib_stringbuf_storage[u];
        }
-
+       isc_mutex_init(&lib_mutex);
        lib_inited = TRUE;
 }
+
+
+char *
+lib_getbuf(void)
+{
+       static int      lib_nextbuf;
+       int             mybuf;
+
+       if (!lib_inited) {
+               init_lib();
+       }
+       isc_mutex_lock(&lib_mutex);
+       mybuf = lib_nextbuf;
+       lib_nextbuf = (1 + mybuf) % COUNTOF(lib_stringbuf);
+       isc_mutex_unlock(&lib_mutex);
+       zero_mem(lib_stringbuf[mybuf], LIB_BUFLENGTH);
+
+       return lib_stringbuf[mybuf];
+}
\ No newline at end of file
index e14578bf590fbf7983a0a41da486f447d52dab58..75cc365ebbb36c5700ea9edc6433bc6e9b80425c 100644 (file)
@@ -376,8 +376,12 @@ send_blocking_resp_internal(
        {
 #          ifdef WORK_PIPE
                if (1 != write(c->resp_write_pipe, "", 1))
-                       msyslog(LOG_WARNING, "async resolver: %s",
-                               "failed to notify main thread!");
+                       msyslog(LOG_WARNING, "async resolver: blocking_get%sinfo",
+                               " failed to notify main thread!",
+                               (BLOCKING_GETNAMEINFO == resp->rtype)
+                                   ? "name"
+                                   : "addr"
+                               );
 #          else
                tickle_sem(c->responses_pending);
 #          endif
index 87a8b0fd71654468759077ebd178cc36b5536ce2..56015d44c955c9c5784f1ecd70facc617259ca71 100644 (file)
@@ -2641,8 +2641,6 @@ socket_multicast_disable(
 # endif
        struct ip_mreq mreq;
 
-       ZERO(mreq);
-
        if (find_addr_in_list(maddr) == NULL) {
                DPRINTF(4, ("socket_multicast_disable(%s): not found\n",
                            stoa(maddr)));
@@ -2652,6 +2650,7 @@ socket_multicast_disable(
        switch (AF(maddr)) {
 
        case AF_INET:
+               ZERO(mreq);
                mreq.imr_multiaddr = SOCK_ADDR4(maddr);
                mreq.imr_interface = SOCK_ADDR4(&iface->sin);
                if (setsockopt(iface->fd, IPPROTO_IP,
@@ -2675,6 +2674,7 @@ socket_multicast_disable(
                 * for other types of multicast addresses. For now let
                 * the kernel figure it out.
                 */
+               ZERO(mreq6);
                mreq6.ipv6mr_multiaddr = SOCK_ADDR6(maddr);
                mreq6.ipv6mr_interface = iface->ifindex;
 
@@ -2695,9 +2695,9 @@ socket_multicast_disable(
        }
 
        iface->num_mcast--;
-       if (!iface->num_mcast)
+       if (iface->num_mcast <= 0) {
                iface->flags &= ~INT_MCASTOPEN;
-
+       }
        return ISC_TRUE;
 }
 #endif /* MCAST */
@@ -4050,8 +4050,9 @@ select_peerinterface(
                                stoa(srcadr)));
        } else {
                ep = dstadr;
-               if (NULL == ep)
+               if (NULL == ep) {
                        ep = wild;
+               }
        }
        /*
         * If it is a multicast address, findbcastinter() may not find
@@ -4059,16 +4060,19 @@ select_peerinterface(
         * given to us as the wildcard (ANY_INTERFACE_CHOOSE).  Either
         * way, try a little harder.
         */
-       if (wild == ep)
+       if (wild == ep) {
                ep = findinterface(srcadr);
+       }
        /*
         * we do not bind to the wildcard interfaces for output
         * as our (network) source address would be undefined and
         * crypto will not work without knowing the own transmit address
         */
-       if (ep != NULL && INT_WILDCARD & ep->flags)
-               if (!accept_wildcard_if_for_winnt)
+       if (ep != NULL && (INT_WILDCARD & ep->flags)) {
+               if (!accept_wildcard_if_for_winnt) {
                        ep = NULL;
+               }
+       }
 #else  /* SIM follows */
        ep = loopback_interface;
 #endif
@@ -4103,7 +4107,7 @@ findinterface(
 
 /*
  * findlocalinterface - find local interface corresponding to addr,
- * which does not have any of flags set.  If bast is nonzero, addr is
+ * which does not have any of flags set.  If bcast is nonzero, addr is
  * a broadcast address.
  *
  * This code attempts to find the local sending address for an outgoing
@@ -4133,21 +4137,21 @@ findlocalinterface(
        DPRINTF(4, ("Finding interface for addr %s in list of addresses\n",
                    stoa(addr)));
 
-       /* [Bug 3437] The dummy POOL peer comes in with an AF of
-        * zero. This is bound to fail, but on the way to nowhere it
+       /* [Bug 3437] The prototype POOL peer can be AF_UNSPEC.
+        * This is bound to fail, but on the way to nowhere it
         * triggers a security incident on SELinux.
         *
-        * Checking the condition and failing early is probably good
+        * Checking the condition and failing early is probably good
         * advice, and even saves us some syscalls in that case.
         * Thanks to Miroslav Lichvar for finding this.
         */
-       if (AF_UNSPEC == AF(addr))
+       if (AF_UNSPEC == AF(addr)) {
                return NULL;
-
+       }
        s = socket(AF(addr), SOCK_DGRAM, 0);
-       if (INVALID_SOCKET == s)
+       if (INVALID_SOCKET == s) {
                return NULL;
-
+       }
        /*
         * If we are looking for broadcast interface we need to set this
         * socket to allow broadcast
@@ -4188,14 +4192,14 @@ findlocalinterface(
         * See http://bugs.ntp.org/1184 and http://bugs.ntp.org/1683
         * for more background.
         */
-       if (NULL == iface || iface->ignore_packets)
+       if (NULL == iface || iface->ignore_packets) {
                iface = findclosestinterface(&saddr,
                                             flags | INT_LOOPBACK);
-
+       }
        /* Don't use an interface which will ignore replies */
-       if (iface != NULL && iface->ignore_packets)
+       if (iface != NULL && iface->ignore_packets) {
                iface = NULL;
-
+       }
        return iface;
 }
 
@@ -4265,47 +4269,40 @@ calc_addr_distance(
        const sockaddr_u *      a2
        )
 {
-       u_int32 a1val;
-       u_int32 a2val;
-       u_int32 v4dist;
-       int     found_greater;
+       u_char *pdist;
+       u_char *p1;
+       u_char *p2;
+       size_t  cb;
+       int     different;
        int     a1_greater;
-       int     i;
+       u_int   u;
 
        REQUIRE(AF(a1) == AF(a2));
 
        ZERO_SOCK(dist);
        AF(dist) = AF(a1);
 
-       /* v4 can be done a bit simpler */
        if (IS_IPV4(a1)) {
-               a1val = SRCADR(a1);
-               a2val = SRCADR(a2);
-               v4dist = (a1val > a2val)
-                            ? a1val - a2val
-                            : a2val - a1val;
-               SET_ADDR4(dist, v4dist);
-
-               return;
+               pdist = (u_char *)&NSRCADR(dist);
+               p1 =    (u_char *)&NSRCADR(a1);
+               p2 =    (u_char *)&NSRCADR(a2);
+       } else {
+               pdist = (u_char *)&NSRCADR(dist);
+               p1 =    (u_char *)&NSRCADR(a1);
+               p2 =    (u_char *)&NSRCADR(a2);
        }
-
-       found_greater = FALSE;
-       a1_greater = FALSE;     /* suppress pot. uninit. warning */
-       for (i = 0; i < (int)sizeof(NSRCADR6(a1)); i++) {
-               if (!found_greater &&
-                   NSRCADR6(a1)[i] != NSRCADR6(a2)[i]) {
-                       found_greater = TRUE;
-                       a1_greater = (NSRCADR6(a1)[i] > NSRCADR6(a2)[i]);
+       cb = SIZEOF_INADDR(AF(dist));
+       different = FALSE;
+       a1_greater = FALSE;
+       for (u = 0; u < cb; u++) {
+               if (!different && p1[u] != p2[u]) {
+                       a1_greater = (p1[u] > p2[u]);
+                       different = TRUE;
                }
-               if (!found_greater) {
-                       NSRCADR6(dist)[i] = 0;
+               if (a1_greater) {
+                       pdist[u] = p1[u] - p2[u];
                } else {
-                       if (a1_greater)
-                               NSRCADR6(dist)[i] = NSRCADR6(a1)[i] -
-                                                   NSRCADR6(a2)[i];
-                       else
-                               NSRCADR6(dist)[i] = NSRCADR6(a2)[i] -
-                                                   NSRCADR6(a1)[i];
+                       pdist[u] = p2[u] - p1[u];
                }
        }
 }
index 435b02aead655f691bd71205193c17c334963356..4252770e4f2676e254804533bb36e9771293a23f 100644 (file)
@@ -39,7 +39,7 @@
 #define AM_MODES       7       /* number of rows and columns */
 #define NO_PEER                0       /* action when no peer is found */
 
-int AM[AM_MODES][AM_MODES] = {
+const s_char AM[AM_MODES][AM_MODES] = {
 /*                     packet->mode                                        */
 /* peer { UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } */
 /* mode */
@@ -58,7 +58,7 @@ int AM[AM_MODES][AM_MODES] = {
 /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_PROCPKT},
 };
 
-#define MATCH_ASSOC(x, y)      AM[(x)][(y)]
+#define MATCH_ASSOC(x, y) (AM[CLAMP((x), 0, AM_MODES)][CLAMP((y), 0, AM_MODES)])
 
 /*
  * These routines manage the allocation of memory to peer structures
@@ -91,8 +91,8 @@ int   peer_free_count;                /* count of free structures */
  * Association ID.  We initialize this value randomly, then assign a new
  * value every time an association is mobilized.
  */
-static associd_t current_association_ID; /* association ID */
-static associd_t initial_association_ID; /* association ID */
+static associd_t current_association_ID; /* actually next poss. ID */
+static associd_t initial_association_ID;
 
 /*
  * Memory allocation watermarks.
@@ -256,7 +256,7 @@ findexistingpeer_addr(
 
 
 /*
- * findexistingpeer - search by address and return a pointer to a peer.
+ * findexistingpeer - search by name+family or address.
  */
 struct peer *
 findexistingpeer(
@@ -294,7 +294,7 @@ findexistingpeer(
  * enough. Authentication alone does not help here, since it does not
  * protect the UDP layer and leaves us open for a replay attack.
  *
- * So we do not update the adresses and wait until the next interface
+ * So we do not update the addresses and wait until the next interface
  * list update does the right thing for us.
  */
 struct peer *
@@ -347,18 +347,20 @@ findpeer(
                }
 
                /* if an error was returned, exit back right here. */
-               if (*action == AM_ERR)
+               if (*action == AM_ERR) {
                        return NULL;
+               }
 
                /* if a match is found, we stop our search. */
-               if (*action != AM_NOMATCH)
+               if (*action != AM_NOMATCH) {
                        break;
+               }
        }
 
        /* If no matching association is found... */
-       if (NULL == p)
+       if (NULL == p) {
                *action = MATCH_ASSOC(NO_PEER, pkt_mode);
-
+       }
        return p;
 }
 
@@ -543,6 +545,7 @@ unpeer(
 {
        mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd);
        restrict_source(&peer->srcadr, TRUE, 0);
+       peer->flags |= FLAG_DISABLED;
        set_peerdstadr(peer, NULL);
        peer_demobilizations++;
        peer_associations--;
@@ -658,7 +661,7 @@ set_peerdstadr(
                p->dstadr->peercnt--;
                UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
                             struct peer);
-               if (!IS_MCAST(&p->srcadr)) {
+               if (!IS_MCAST(&p->srcadr) &&!(FLAG_DISABLED & p->flags)) {
                        msyslog(LOG_INFO, "%s local addr %s -> %s",
                                stoa(&p->srcadr), latoa(p->dstadr),
                                latoa(dstadr));
@@ -743,14 +746,27 @@ refresh_all_peerinterfaces(void)
        struct peer *p;
 
        /*
-        * this is called when the interface list has changed
-        * give all peers a chance to find a better interface
-        * but only if either they don't have an address already
-        * or if the one they have hasn't worked for a while.
+        * This is called when the interface list has changed.
+        * Give peers a chance to find a better interface.
         */
        for (p = peer_list; p != NULL; p = p->p_link) {
-               if (!(p->dstadr && (p->reach & 0x3)))   // Bug 2849 XOR 2043
-                       peer_refresh_interface(p);
+               /* 
+                * Bug 2849 XOR 2043
+                * Change local address only if the peer doesn't
+                * have a local address already or if the one
+                * they have hasn't worked for a while.
+                */
+               if (p->dstadr != NULL && (p->reach & 0x3)) {
+                       continue;
+               }
+               /*
+                * Do not change the local address of a link-local
+                * peer address.
+                */
+               if (p->dstadr != NULL && is_linklocal(&p->srcadr)) {
+                       continue;
+               }
+               peer_refresh_interface(p);
        }
 }
 
@@ -779,7 +795,6 @@ newpeer(
        u_int           hash;
        int             ip_count = 0;
 
-
        DEBUG_REQUIRE(srcadr);
 
 #ifdef AUTOKEY
@@ -791,7 +806,9 @@ newpeer(
                        return (NULL);
 
                } else if (flags & FLAG_SKEY) {
-                       msyslog(LOG_ERR, "Autokey not configured");
+                       msyslog(LOG_ERR, "Rejecting Autokey with %s,"
+                                        " built without support.",
+                                        stoa(srcadr));
                        return (NULL);
                } 
        }
@@ -832,6 +849,26 @@ newpeer(
                                        cast_flags, &ip_count);
        }
 
+       /*
+        * In any case, do not create an association with a duplicate
+        * remote address (srcadr) except for undefined (zero) address.
+        * Arguably this should be part of the logic above but
+        * [Bug 3888] exposed a situation with manycastclient where
+        * duplicate associations happened.
+        */
+       if (NULL == peer) {
+               for (peer = peer_list;
+                    peer != NULL;
+                    peer = peer->p_link) {
+                       if (   SOCK_EQ(srcadr, &peer->srcadr)
+                           && !SOCK_UNSPEC(srcadr)
+                           && !SOCK_UNSPEC(&peer->srcadr)) {
+                               /* leave peer non-NULL */
+                               break;
+                       }
+               }
+       }
+
        /*
         * If a peer is found, this would be a duplicate and we don't
         * allow that. This avoids duplicate ephemeral (broadcast/
@@ -839,7 +876,8 @@ newpeer(
         * associations.
         */
        if (peer != NULL) {
-               DPRINTF(2, ("newpeer(%s) found existing association\n",
+               DPRINTF(2, ("%s(%s) found existing association\n",
+                       __func__,
                        (hostname)
                            ? hostname
                            : stoa(srcadr)));
@@ -847,7 +885,7 @@ newpeer(
        }
 
 #if 0
-DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
+       DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
                (hostname)
                    ? hostname
                    : stoa(srcadr),
@@ -886,15 +924,19 @@ DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
                peer_preempt++;
 
        /*
-        * Assign an association ID and increment the system variable.
+        * Assign an available association ID.  Zero is reserved.
         */
+       do {
+               while (0 == ++current_association_ID) {
+                       /* EMPTY */
+               }
+       } while (NULL != findpeerbyassoc(current_association_ID));
        peer->associd = current_association_ID;
-       if (++current_association_ID == 0)
-               ++current_association_ID;
 
        peer->srcadr = *srcadr;
-       if (hostname != NULL)
+       if (hostname != NULL) {
                peer->hostname = estrdup(hostname);
+       }
        peer->hmode = hmode;
        peer->version = version;
        peer->flags = flags;
@@ -903,66 +945,57 @@ DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
                       select_peerinterface(peer, srcadr, dstadr));
 
        /*
-        * It is an error to set minpoll less than NTP_MINPOLL or to
-        * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
-        * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
-        * not less than NTP_MINPOLL without complaint. Finally,
-        * minpoll is clamped not greater than maxpoll.
+        * Clamp maxpoll and minpoll within NTP_MINPOLL and NTP_MAXPOLL,
+        * and further clamp minpoll less than or equal maxpoll.
         */
-       if (minpoll == 0)
-               peer->minpoll = NTP_MINDPOLL;
-       else
-               peer->minpoll = min(minpoll, NTP_MAXPOLL);
-       if (maxpoll == 0)
-               peer->maxpoll = NTP_MAXDPOLL;
-       else
-               peer->maxpoll = max(maxpoll, NTP_MINPOLL);
-       if (peer->minpoll > peer->maxpoll)
-               peer->minpoll = peer->maxpoll;
+       peer->maxpoll = CLAMP(maxpoll, NTP_MINPOLL, NTP_MAXPOLL);
+       peer->minpoll = CLAMP(minpoll, NTP_MINPOLL, peer->maxpoll);
 
-       if (peer->dstadr != NULL)
+       if (peer->dstadr != NULL) {
                DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n",
                        stoa(srcadr), peer->dstadr->fd,
                        stoa(&peer->dstadr->sin)));
-       else
-               DPRINTF(3, ("newpeer(%s): local interface currently not bound\n",
+       } else {
+               DPRINTF(3, ("newpeer(%s): local addr unavailable\n",
                        stoa(srcadr))); 
-
+       }
        /*
         * Broadcast needs the socket enabled for broadcast
         */
-       if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL)
+       if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL) {
                enable_broadcast(peer->dstadr, srcadr);
-
+       }
        /*
         * Multicast needs the socket interface enabled for multicast
         */
-       if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL)
+       if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL) {
                enable_multicast_if(peer->dstadr, srcadr);
-
+       }
 #ifdef AUTOKEY
        if (key > NTP_MAXKEY)
                peer->flags |= FLAG_SKEY;
 #endif /* AUTOKEY */
        peer->ttl = ttl;
        peer->keyid = key;
-       if (ident != NULL)
+       if (ident != NULL) {
                peer->ident = estrdup(ident);
+       }
        peer->precision = sys_precision;
        peer->hpoll = peer->minpoll;
-       if (cast_flags & MDF_ACAST)
+       if (cast_flags & MDF_ACAST) {
                peer_clear(peer, "ACST");
-       else if (cast_flags & MDF_POOL)
+       } else if (cast_flags & MDF_POOL) {
                peer_clear(peer, "POOL");
-       else if (cast_flags & MDF_MCAST)
+       } else if (cast_flags & MDF_MCAST) {
                peer_clear(peer, "MCST");
-       else if (cast_flags & MDF_BCAST)
+       } else if (cast_flags & MDF_BCAST) {
                peer_clear(peer, "BCST");
-       else
+       } else {
                peer_clear(peer, "INIT");
-       if (mode_ntpdate)
+       }
+       if (mode_ntpdate) {
                peer_ntpdate++;
-
+       }
        /*
         * Note time on statistics timers.
         */
@@ -978,8 +1011,6 @@ DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
                 * the peer timer, since the clock may have requirements
                 * for this.
                 */
-               if (maxpoll == 0)
-                       peer->maxpoll = peer->minpoll;
                if (!refclock_newpeer(peer)) {
                        /*
                         * Dump it, something screwed up
@@ -1095,8 +1126,9 @@ findmanycastpeer(
        for (peer = peer_list; peer != NULL; peer = peer->p_link)
                if (MDF_SOLICIT_MASK & peer->cast_flags) {
                        NTOHL_FP(&pkt->org, &p_org);
-                       if (L_ISEQU(&p_org, &peer->aorg))
+                       if (L_ISEQU(&p_org, &peer->aorg)) {
                                break;
+                       }
                }
 
        return peer;
@@ -1105,17 +1137,11 @@ findmanycastpeer(
 /* peer_cleanup - clean peer list prior to shutdown */
 void peer_cleanup(void)
 {
-        struct peer *peer;
-        associd_t assoc;
-
-        for (assoc = initial_association_ID; assoc != current_association_ID; assoc++) {
-            if (assoc != 0U) {
-                peer = findpeerbyassoc(assoc);
-                if (peer != NULL)
-                    unpeer(peer);
-            }
-        }
-        peer = findpeerbyassoc(current_association_ID);
-        if (peer != NULL)
-            unpeer(peer);
+       struct peer *peer;
+       struct peer *nextpeer;
+
+       for (peer = peer_list; peer != NULL; peer = nextpeer) {
+               nextpeer = peer->p_link;
+               unpeer(peer);
+       }
 }
index 2b5b834623160e1e5376bc0d89212d4fbafd7672..c50182f8f8ce9f33bb8c8509e04e4fa723aa1d45 100644 (file)
@@ -4539,14 +4539,14 @@ leap_smear_add_offs(
  */
 static void
 fast_xmit(
-       struct recvbuf *rbufp,  /* receive packet pointer */
+       struct recvbufrbufp,  /* receive packet pointer */
        int     xmode,          /* receive mode */  /* XXX: HMS: really? */
        keyid_t xkeyid,         /* transmit key ID */
        int     flags           /* restrict mask */
-       )
+)
 {
        struct pkt xpkt;        /* transmit packet structure */
-       struct pkt *rpkt;       /* receive packet structure */
+       struct pktrpkt;       /* receive packet structure */
        l_fp    xmt_tx, xmt_ty;
        size_t  sendlen;
 #ifdef AUTOKEY
@@ -4560,13 +4560,26 @@ fast_xmit(
         * the system minimum poll (ntp_minpoll). This is for KoD rate
         * control and not strictly specification compliant, but doesn't
         * break anything.
-        *
-        * If the gazinta was from a multicast address, the gazoutta
-        * must go out another way.
         */
        rpkt = &rbufp->recv_pkt;
-       if (rbufp->dstadr->flags & INT_MCASTOPEN)
+       /*
+        * If the packet was received on an endpoint open only on
+        * a multicast address, the response needs to go out from
+        * a unicast endpoint.
+        */
+#ifndef MULTICAST_NONEWSOCKET
+       if (rbufp->dstadr->flags & INT_MCASTOPEN) {
                rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
+               if (NULL == rbufp->dstadr ||
+                   ANY_INTERFACE_CHOOSE(&rbufp->recv_srcadr) /* wildcard */
+                     == rbufp->dstadr) {
+                       DPRINTF(2, ("No unicast local address found for"
+                                   " reply to %s mcast.",
+                                   stoa(&rbufp->recv_srcadr)));
+                       return;
+               }
+       }
+#endif
 
        /*
         * If this is a kiss-o'-death (KoD) packet, show leap
index c55f3068b9b77b5437227c3709c5fe2fb6cd2f2e..e4d4d162319a4c0c4cdea32cfe31539b92513793 100644 (file)
@@ -265,12 +265,10 @@ write_stats(void)
                 * the frequncy file. This minimizes the file writes to
                 * nonvolaile storage.
                 */
-#ifdef DEBUG
-               if (debug)
-                       printf("write_stats: frequency %.6lf thresh %.6lf, freq %.6lf\n",
+               DPRINTF(1, ("write_stats: frequency %.6f thresh %.6f, freq %.6f\n",
                            (prev_drift_comp - drift_comp) * 1e6, wander_resid *
-                           1e6, drift_comp * 1e6);
-#endif
+                           1e6, drift_comp * 1e6));
+
                if (fabs(prev_drift_comp - drift_comp) < wander_resid) {
                        wander_resid *= 0.5;
                        return;
@@ -282,7 +280,7 @@ write_stats(void)
                            stats_temp_file);
                        return;
                }
-               fprintf(fp, "%.3f\n", drift_comp * 1e6);
+               fprintf(fp, "%.6f\n", drift_comp * 1e6);
                (void)fclose(fp);
                /* atomic */
 #ifdef SYS_WINNT
@@ -469,7 +467,7 @@ stats_config(
                        loop_config(LOOP_FREQ, old_drift);
                        prev_drift_comp = drift_comp;
                        msyslog(LOG_INFO,
-                               "initial drift restored to %f",
+                               "initial drift restored to %.6f",
                                old_drift);
                }
                if (NULL != fp) {
index e74c2bc45e02c8497bacb58dba4ad867b1a43f29..97115b403ac9af49096d66d25296191a228f6459 100644 (file)
@@ -2461,7 +2461,7 @@ fetch_nonce(
                return FALSE;
        }
 
-       if ((size_t)rsize <= sizeof(nonce_eq) - 1 ||
+       if (rsize <= sizeof(nonce_eq) - 1 ||
            strncmp(rdata, nonce_eq, sizeof(nonce_eq) - 1)) {
                xprintf(stderr, "unexpected nonce response format: %.*s\n",
                        (int)rsize, rdata); /* cast is wobbly */
index 1022361cb35d2d7c5e4c6a93e2bfcdc21bd526c2..9b2807907b8cfc1fec29e076603eb8ba5eebb143 100644 (file)
@@ -220,6 +220,7 @@ void
 ntservice_exit(void)
 {
        uninit_io_completion_port();
+       peer_cleanup();
        Sleep( 200 );   //##++ 
 
        reset_winnt_time();