]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3031] ntp broadcastclient unable to synchronize to an server when the time of...
authorJuergen Perlinger <perlinger@ntp.org>
Wed, 30 Mar 2016 17:28:04 +0000 (17:28 +0000)
committerJuergen Perlinger <perlinger@ntp.org>
Wed, 30 Mar 2016 17:28:04 +0000 (17:28 +0000)
 - Check the initial delay calculation and reject/unpeer the broadcast server if the delay exceeds
   the cutoff limit. (default 50ms)
   Retry again after the next broadcast packet.

bk: 56fc0ca4-oKtZEsIKgTkzDu3mqUHRg

ChangeLog
ntpd/ntp_io.c
ntpd/ntp_proto.c

index c70fe8fc563cf0a16def01a652b989e8bc667f06..c67a28f5ed84bbcf5141b9f55476d4c4ba05793f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,11 @@
 
 * [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>
index 95229d6a7f022d0cd6b9b8939f4985434c5e4982..8050bb3afa562d1dcc64391c2effa3dddd6b6904 100644 (file)
@@ -1013,8 +1013,8 @@ remove_interface(
                        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);
@@ -2565,7 +2565,7 @@ io_setbclient(void)
                        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) {
@@ -2593,13 +2593,31 @@ io_setbclient(void)
                        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);
@@ -2639,8 +2657,8 @@ io_unsetbclient(void)
                                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;
 }
index ad454099f8b924a16ca84cf3fd162a1d8ab58e61..d757b5bf284922df6941498d5d0ee63ece8413ed 100644 (file)
 #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.
@@ -1144,7 +1149,7 @@ receive(
                /*
                 * 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,
@@ -1339,7 +1344,7 @@ receive(
                        }
 
                        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),
@@ -1958,6 +1963,9 @@ process_packet(
                        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);
@@ -1983,10 +1991,21 @@ process_packet(
                 * 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;
@@ -4333,7 +4352,7 @@ init_proto(void)
        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;
@@ -4426,7 +4445,7 @@ proto_config(
                break;
 
        case PROTO_BROADDELAY:  /* default broadcast delay (bdelay) */
-               sys_bdelay = dvalue;
+               sys_bdelay = (dvalue ? dvalue : BDELAY_DEFAULT);
                break;
 
        case PROTO_CEILING:     /* stratum ceiling (ceiling) */