#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."
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);
}
return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
}
-static double tv_to_d(const struct timeval *tv) {
- return tv->tv_sec + (1.0e-6 * tv->tv_usec);
-}
-
static double square(double d) {
return d * d;
}
.msg_namelen = sizeof(server_addr),
};
struct cmsghdr *cmsg;
- struct timespec now_ts;
- struct timeval *recv_time;
+ struct timespec *recv_time;
ssize_t len;
double origin, receive, trans, dest;
double delay, offset;
+ double root_distance;
bool spike;
int leap_sec;
int r;
continue;
switch (cmsg->cmsg_type) {
- case SCM_TIMESTAMP:
- recv_time = (struct timeval *) CMSG_DATA(cmsg);
+ case SCM_TIMESTAMPNS:
+ recv_time = (struct timespec *) CMSG_DATA(cmsg);
break;
}
}
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;
* The round-trip delay, d, and system clock offset, t, are defined as:
* d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2"
*/
- assert_se(clock_gettime(clock_boottime_or_monotonic(), &now_ts) >= 0);
- origin = tv_to_d(recv_time) - (ts_to_d(&now_ts) - ts_to_d(&m->trans_time_mon)) + OFFSET_1900_1970;
+ origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970;
receive = ntp_ts_to_d(&ntpmsg.recv_time);
trans = ntp_ts_to_d(&ntpmsg.trans_time);
- dest = tv_to_d(recv_time) + OFFSET_1900_1970;
+ dest = ts_to_d(recv_time) + OFFSET_1900_1970;
offset = ((receive - origin) + (trans - dest)) / 2;
delay = (dest - origin) - (trans - receive);
" 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"
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,
if (r < 0)
return -errno;
- r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
+ r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMPNS, &on, sizeof(on));
if (r < 0)
return -errno;