---
+* [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>
#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;
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 */
#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
#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())
*/
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);
}
#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.
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
{
# 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
# 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)));
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,
* 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;
}
iface->num_mcast--;
- if (!iface->num_mcast)
+ if (iface->num_mcast <= 0) {
iface->flags &= ~INT_MCASTOPEN;
-
+ }
return ISC_TRUE;
}
#endif /* MCAST */
stoa(srcadr)));
} else {
ep = dstadr;
- if (NULL == ep)
+ if (NULL == ep) {
ep = wild;
+ }
}
/*
* If it is a multicast address, findbcastinter() may not find
* 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
/*
* 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
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
* 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;
}
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];
}
}
}
#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 */
/*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
* 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.
/*
- * findexistingpeer - search by address and return a pointer to a peer.
+ * findexistingpeer - search by name+family or address.
*/
struct peer *
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 *
}
/* 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;
}
{
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--;
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));
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);
}
}
u_int hash;
int ip_count = 0;
-
DEBUG_REQUIRE(srcadr);
#ifdef AUTOKEY
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);
}
}
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/
* 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)));
}
#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),
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;
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.
*/
* 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
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;
/* 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);
+ }
}
*/
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
* 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
* 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;
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
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) {
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 */
ntservice_exit(void)
{
uninit_io_completion_port();
+ peer_cleanup();
Sleep( 200 ); //##++
reset_winnt_time();