Zbigniew Jędrzejewski-Szmek 62fe94
From 3af0442c52090f34ae7a1c8e6b6587c540c06896 Mon Sep 17 00:00:00 2001
Michal Schmidt d962ba
From: Miroslav Lichvar <mlichvar@redhat.com>
Michal Schmidt d962ba
Date: Wed, 27 Aug 2014 16:47:20 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] timesyncd: check root distance
Michal Schmidt d962ba
Michal Schmidt d962ba
NTPv4 servers don't reply with unsynchronized status when they lost
Michal Schmidt d962ba
synchronization, they only keep increasing the root dispersion and it's
Michal Schmidt d962ba
up to the client to decide at which point they no longer consider it
Michal Schmidt d962ba
synchronized.
Michal Schmidt d962ba
Michal Schmidt d962ba
Ignore replies with root distance over 5 seconds.
Michal Schmidt d962ba
---
Michal Schmidt d962ba
 src/timesync/timesyncd-manager.c | 16 ++++++++++++++++
Michal Schmidt d962ba
 1 file changed, 16 insertions(+)
Michal Schmidt d962ba
Michal Schmidt d962ba
diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 2b0580cf01..9b8b7d3eb6 100644
Michal Schmidt d962ba
--- a/src/timesync/timesyncd-manager.c
Michal Schmidt d962ba
+++ b/src/timesync/timesyncd-manager.c
Michal Schmidt d962ba
@@ -89,6 +89,9 @@
Michal Schmidt d962ba
 #define NTP_FIELD_MODE(f)               ((f) & 7)
Michal Schmidt d962ba
 #define NTP_FIELD(l, v, m)              (((l) << 6) | ((v) << 3) | (m))
Michal Schmidt d962ba
 
Michal Schmidt d962ba
+/* Maximum acceptable root distance in seconds. */
Michal Schmidt d962ba
+#define NTP_MAX_ROOT_DISTANCE           5.0
Michal Schmidt d962ba
+
Michal Schmidt d962ba
 /*
Michal Schmidt d962ba
  * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
Michal Schmidt d962ba
  * in seconds relative to 0h on 1 January 1900."
Michal Schmidt d962ba
@@ -128,6 +131,10 @@ struct ntp_msg {
Michal Schmidt d962ba
 static int manager_arm_timer(Manager *m, usec_t next);
Michal Schmidt d962ba
 static int manager_clock_watch_setup(Manager *m);
Michal Schmidt d962ba
 
Michal Schmidt d962ba
+static double ntp_ts_short_to_d(const struct ntp_ts_short *ts) {
Michal Schmidt d962ba
+        return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0);
Michal Schmidt d962ba
+}
Michal Schmidt d962ba
+
Michal Schmidt d962ba
 static double ntp_ts_to_d(const struct ntp_ts *ts) {
Michal Schmidt d962ba
         return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX);
Michal Schmidt d962ba
 }
Michal Schmidt d962ba
@@ -500,6 +507,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
Michal Schmidt d962ba
         ssize_t len;
Michal Schmidt d962ba
         double origin, receive, trans, dest;
Michal Schmidt d962ba
         double delay, offset;
Michal Schmidt d962ba
+        double root_distance;
Michal Schmidt d962ba
         bool spike;
Michal Schmidt d962ba
         int leap_sec;
Michal Schmidt d962ba
         int r;
Michal Schmidt d962ba
@@ -585,6 +593,12 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
Michal Schmidt d962ba
                 return manager_connect(m);
Michal Schmidt d962ba
         }
Michal Schmidt d962ba
 
Michal Schmidt d962ba
+        root_distance = ntp_ts_short_to_d(&ntpmsg.root_delay) / 2 + ntp_ts_short_to_d(&ntpmsg.root_dispersion);
Michal Schmidt d962ba
+        if (root_distance > NTP_MAX_ROOT_DISTANCE) {
Michal Schmidt d962ba
+                log_debug("Server has too large root distance. Disconnecting.");
Michal Schmidt d962ba
+                return manager_connect(m);
Michal Schmidt d962ba
+        }
Michal Schmidt d962ba
+
Michal Schmidt d962ba
         /* valid packet */
Michal Schmidt d962ba
         m->pending = false;
Michal Schmidt d962ba
         m->retry_interval = 0;
Michal Schmidt d962ba
@@ -626,6 +640,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
Michal Schmidt d962ba
                   "  mode         : %u\n"
Michal Schmidt d962ba
                   "  stratum      : %u\n"
Michal Schmidt d962ba
                   "  precision    : %.6f sec (%d)\n"
Michal Schmidt d962ba
+                  "  root distance: %.6f sec\n"
Michal Schmidt d962ba
                   "  reference    : %.4s\n"
Michal Schmidt d962ba
                   "  origin       : %.3f\n"
Michal Schmidt d962ba
                   "  receive      : %.3f\n"
Michal Schmidt d962ba
@@ -641,6 +656,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
Michal Schmidt d962ba
                   NTP_FIELD_MODE(ntpmsg.field),
Michal Schmidt d962ba
                   ntpmsg.stratum,
Michal Schmidt d962ba
                   exp2(ntpmsg.precision), ntpmsg.precision,
Michal Schmidt d962ba
+                  root_distance,
Michal Schmidt d962ba
                   ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a",
Michal Schmidt d962ba
                   origin - OFFSET_1900_1970,
Michal Schmidt d962ba
                   receive - OFFSET_1900_1970,