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