X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Ftimesync%2Ftimesyncd-manager.c;h=696dd10e69fd0cb0cccae7f8f4213e96bf7f7784;hb=20f8d3cf1be4ad76234ffb85eeae7f9892ee72cd;hp=bb8fcca1df4c0fb1f886c7c60b1fbf56bb363ff8;hpb=874ff7bf4d6fe693542209f127d23cd89adc499b;p=elogind.git diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c index bb8fcca1d..696dd10e6 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); } @@ -136,10 +143,6 @@ static double ts_to_d(const struct timespec *ts) { 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; } @@ -500,11 +503,11 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re .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; @@ -544,8 +547,8 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re 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; } } @@ -574,7 +577,8 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re return manager_connect(m); } - if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC) { + if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC || + ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) { log_debug("Server is not synchronized. Disconnecting."); return manager_connect(m); } @@ -589,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; @@ -612,11 +622,10 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re * 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); @@ -631,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" @@ -646,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, @@ -698,7 +709,7 @@ static int manager_listen_setup(Manager *m) { 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; @@ -755,8 +766,11 @@ void manager_set_server_address(Manager *m, ServerAddress *a) { if (m->current_server_address == a) return; - m->current_server_name = a ? a->name : NULL; m->current_server_address = a; + /* If a is NULL, we are just clearing the address, without + * changing the name. Keep the existing name in that case. */ + if (a) + m->current_server_name = a->name; manager_disconnect(m); @@ -1111,9 +1125,7 @@ int manager_new(Manager **ret) { if (r < 0) return r; - r = manager_network_read_link_servers(m); - if (r < 0) - return r; + manager_network_read_link_servers(m); *ret = m; m = NULL;