* [Bug 2994] Systems with HAVE_SIGNALED_IO fail to compile. perlinger@ntp.org
* [Bug 2995] Fixes to compile on Windows
+* [Bug 3031] ntp broadcastclient unable to synchronize to an server
+ when the time of server changed. perlinger@ntp.org
+ - Check the initial delay calculation and reject/unpeer the broadcast
+ server if the delay exceeds 50ms. Retry again after the next
+ broadcast packet.
---
(4.2.8p6) 2016/01/20 Released by Harlan Stenn <stenn@ntp.org>
stoa(&ep->bcast), ep->ifnum, ep->name);
close_and_delete_fd_from_list(ep->bfd);
ep->bfd = INVALID_SOCKET;
- ep->flags &= ~INT_BCASTOPEN;
}
+ ep->flags &= ~INT_BCASTOPEN;
ninterfaces--;
mon_clearinterface(ep);
continue;
/* Only IPv4 addresses are valid for broadcast */
- REQUIRE(IS_IPV4(&interf->sin));
+ REQUIRE(IS_IPV4(&interf->bcast));
/* Do we already have the broadcast address open? */
if (interf->flags & INT_BCASTOPEN) {
msyslog(LOG_INFO,
"Listen for broadcasts to %s on interface #%d %s",
stoa(&interf->bcast), interf->ifnum, interf->name);
- } else {
- /* silently ignore EADDRINUSE as we probably opened
- the socket already for an address in the same network */
- if (errno != EADDRINUSE)
- msyslog(LOG_INFO,
- "failed to listen for broadcasts to %s on interface #%d %s",
- stoa(&interf->bcast), interf->ifnum, interf->name);
+ } else switch (errno) {
+ /* Silently ignore EADDRINUSE as we probably
+ * opened the socket already for an address in
+ * the same network */
+ case EADDRINUSE:
+ /* Some systems cannot bind a socket to a broadcast
+ * address, as that is not a valid host address. */
+ case EADDRNOTAVAIL:
+# ifdef SYS_WINNT /*TODO: use for other systems, too? */
+ /* avoid recurrence here -- if we already have a
+ * regular socket, it's quite useless to try this
+ * again.
+ */
+ if (interf->fd != INVALID_SOCKET) {
+ interf->flags |= INT_BCASTOPEN;
+ nif++;
+ }
+# endif
+ break;
+
+ default:
+ msyslog(LOG_INFO,
+ "failed to listen for broadcasts to %s on interface #%d %s",
+ stoa(&interf->bcast), interf->ifnum, interf->name);
+ break;
}
}
set_reuseaddr(0);
stoa(&ep->bcast), ep->ifnum, ep->name);
close_and_delete_fd_from_list(ep->bfd);
ep->bfd = INVALID_SOCKET;
- ep->flags &= ~INT_BCASTOPEN;
}
+ ep->flags &= ~INT_BCASTOPEN;
}
broadcast_client_enabled = ISC_FALSE;
}
#include <unistd.h>
#endif
+/*[Bug 3031] define automatic broadcastdelay cutoff preset */
+#ifndef BDELAY_DEFAULT
+# define BDELAY_DEFAULT (-0.050)
+#endif
+
/*
* This macro defines the authentication state. If x is 1 authentication
* is required; othewise it is optional.
/*
* Determine whether to execute the initial volley.
*/
- if (sys_bdelay != 0) {
+ if (sys_bdelay > 0.0) {
#ifdef AUTOKEY
/*
* If a two-way exchange is not possible,
}
if ( (current_time - peer->timelastrec)
- < (1 << pkt->ppoll)) {
+ < (1u << pkt->ppoll) - 1) {
msyslog(LOG_INFO, "receive: broadcast packet from %s arrived after %ld, not %d seconds!",
stoa(&rbufp->recv_srcadr),
(current_time - peer->timelastrec),
peer->aorg = p_xmt;
peer->borg = peer->dst;
if (t34 < 0 || t34 > 1.) {
+ /* drop all if in the initial volley */
+ if (FLAG_BC_VOL & peer->flags)
+ goto bcc_init_volley_fail;
snprintf(statstr, sizeof(statstr),
"offset %.6f delay %.6f", t21, t34);
report_event(PEVNT_XERR, peer, statstr);
* between the unicast timestamp and the broadcast
* timestamp. This works for both basic and interleaved
* modes.
+ * [Bug 3031] Don't keep this peer when the delay
+ * calculation gives reason to suspect clock steps.
+ * This is assumed for delays > 50ms.
*/
if (FLAG_BC_VOL & peer->flags) {
peer->flags &= ~FLAG_BC_VOL;
peer->delay = fabs(peer->offset - p_offset) * 2;
+ DPRINTF(2, ("broadcast volley: initial delay=%.6f\n",
+ peer->delay));
+ if (peer->delay > fabs(sys_bdelay)) {
+ bcc_init_volley_fail:
+ DPRINTF(2, ("%s", "broadcast volley: initial delay exceeds limit\n"));
+ unpeer(peer);
+ return;
+ }
}
p_del = peer->delay;
p_offset += p_del / 2;
sys_survivors = 0;
sys_manycastserver = 0;
sys_bclient = 0;
- sys_bdelay = 0;
+ sys_bdelay = BDELAY_DEFAULT; /*[Bug 3031] delay cutoff */
sys_authenticate = 1;
sys_stattime = current_time;
orphwait = current_time + sys_orphwait;
break;
case PROTO_BROADDELAY: /* default broadcast delay (bdelay) */
- sys_bdelay = dvalue;
+ sys_bdelay = (dvalue ? dvalue : BDELAY_DEFAULT);
break;
case PROTO_CEILING: /* stratum ceiling (ceiling) */