From: Dave Hart Date: Mon, 22 Jan 2024 06:54:06 +0000 (+0000) Subject: [Bug 3901] LIB_GETBUF isn't thread-safe. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c508b73cf0d4c8328620f2f8ad5c584a3c437b5;p=thirdparty%2Fntp.git [Bug 3901] LIB_GETBUF isn't thread-safe. [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 --- diff --git a/ChangeLog b/ChangeLog index 25f5ad5a0..767326838 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ --- +* [Bug 3901] LIB_GETBUF isn't thread-safe. +* [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. * [Bug 3872] Ignore restrict mask for hostname. * [Bug 3871] 4.2.8p17 build without hopf6021 refclock enabled fails. Reported by Hans Mayer. Moved NONEMPTY_TRANSLATION_UNIT @@ -49,6 +54,14 @@ * Remove dead code libntp/numtohost.c and its unit tests. * Remove class A, B, C IPv4 distinctions in netof(). * 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. +* Ensure unique association IDs if wrapped. +* Simplify calc_addr_distance(). +* Clamp min/maxpoll in edge cases in newpeer(). +* Quiet local addr change logging when unpeering. +* Correct missing arg for %s printf specifier in + send_blocking_resp_internal(). --- (4.2.8p17) 2023/06/06 Released by Harlan Stenn diff --git a/include/lib_strbuf.h b/include/lib_strbuf.h index 7c79713c4..89da450a5 100644 --- a/include/lib_strbuf.h +++ b/include/lib_strbuf.h @@ -7,14 +7,8 @@ #include #include /* 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 */ diff --git a/include/ntp.h b/include/ntp.h index 9ff5a408f..11fb3c35b 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -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()) diff --git a/libntp/lib/isc/win32/strerror.c b/libntp/lib/isc/win32/strerror.c index 40c5da002..823e9c1b2 100644 --- a/libntp/lib/isc/win32/strerror.c +++ b/libntp/lib/isc/win32/strerror.c @@ -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); } diff --git a/libntp/lib_strbuf.c b/libntp/lib_strbuf.c index 69df900ba..225c430f7 100644 --- a/libntp/lib_strbuf.c +++ b/libntp/lib_strbuf.c @@ -5,25 +5,26 @@ #include #endif +#include #include #include #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 diff --git a/libntp/work_thread.c b/libntp/work_thread.c index e14578bf5..75cc365eb 100644 --- a/libntp/work_thread.c +++ b/libntp/work_thread.c @@ -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 diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index 87a8b0fd7..56015d44c 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -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 a 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]; } } } diff --git a/ntpd/ntp_peer.c b/ntpd/ntp_peer.c index 435b02aea..4252770e4 100644 --- a/ntpd/ntp_peer.c +++ b/ntpd/ntp_peer.c @@ -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); + } } diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 2b5b83462..c50182f8f 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -4539,14 +4539,14 @@ leap_smear_add_offs( */ static void fast_xmit( - struct recvbuf *rbufp, /* receive packet pointer */ + struct recvbuf* rbufp, /* 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 pkt* rpkt; /* 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 diff --git a/ntpd/ntp_util.c b/ntpd/ntp_util.c index c55f3068b..e4d4d1623 100644 --- a/ntpd/ntp_util.c +++ b/ntpd/ntp_util.c @@ -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) { diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index e74c2bc45..97115b403 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -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 */ diff --git a/ports/winnt/ntpd/ntservice.c b/ports/winnt/ntpd/ntservice.c index 1022361cb..9b2807907 100644 --- a/ports/winnt/ntpd/ntservice.c +++ b/ports/winnt/ntpd/ntservice.c @@ -220,6 +220,7 @@ void ntservice_exit(void) { uninit_io_completion_port(); + peer_cleanup(); Sleep( 200 ); //##++ reset_winnt_time();