timesyncd-manager.c revision 73c76e6330d31e1d04454fd7408dd56b4eedca9f
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Kay Sievers, Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* expected accuracy of time synchronization; used to adjust the poll interval */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * "A client MUST NOT under any conditions use a poll interval less
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * than 15 seconds."
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * Maximum delta in seconds which the system clock is gradually adjusted
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * (slew) to approach the network time. Deltas larger that this are set by
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * letting the system time jump. The kernel's limit for adjtime is 0.5s.
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/* NTP protocol, packet header */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_FIELD_VERSION(f) (((f) >> 3) & 7)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * in seconds relative to 0h on 1 January 1900."
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_arm_timer(Manager *m, usec_t next);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_clock_watch_setup(Manager *m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double ntp_ts_to_d(const struct ntp_ts *ts) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double ts_to_d(const struct timespec *ts) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic double tv_to_d(const struct timeval *tv) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return tv->tv_sec + (1.0e-6 * tv->tv_usec);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double square(double d) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return d * d;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering server_address_pretty(m->current_server_address, &pretty);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering log_info("Timed out waiting for reply from %s (%s).", strna(pretty), m->current_server_name->string);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_send_request(Manager *m) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * "The client initializes the NTP message header, sends the request
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * to the server, and strips the time of day from the Transmit
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * Timestamp field of the reply. For this purpose, all the NTP
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering * header fields are set to 0, except the Mode, VN, and optional
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * Transmit Timestamp fields."
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering .field = NTP_FIELD(0, 4, NTP_MODE_CLIENT),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * Set transmit timestamp, remember it; the server will send that back
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * as the origin timestamp and we have an indication that this is the
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * matching answer to our request.
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * The actual value does not matter, We do not care about the correct
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * NTP UINT_MAX fraction; we just pass the plain nanosecond value.
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(clock_gettime(clock_boottime_or_monotonic(), &m->trans_time_mon) >= 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering server_address_pretty(m->current_server_address, &pretty);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_debug("Sent NTP request to %s (%s).", strna(pretty), m->current_server_name->string);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering log_debug("Sending NTP request to %s (%s) failed: %m", strna(pretty), m->current_server_name->string);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* re-arm timer with increasing timeout, in case the packets never arrive back */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = manager_arm_timer(m, m->retry_interval);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Failed to rearm timer: %s", strerror(-r));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering now(clock_boottime_or_monotonic()) + TIMEOUT_USEC, 0,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Failed to arm timeout timer: %s", strerror(-r));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_timer(sd_event_source *source, usec_t usec, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_arm_timer(Manager *m, usec_t next) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering m->event_timer = sd_event_source_unref(m->event_timer);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering now(clock_boottime_or_monotonic()) + next, 0,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* rearm timer */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* skip our own jumps */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("System time changed. Resyncing.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* wake up when the system time changes underneath us */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_clock_watch_setup(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->clock_watch_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create timerfd: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (timerfd_settime(m->clock_watch_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to set up timerfd: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create clock watch event source: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * For small deltas, tell the kernel to gradually adjust the system
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * clock to the NTP time, larger deltas are just directly set.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug(" adjust (slew): %+.3f sec\n", offset);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* ADJ_NANO uses nanoseconds in the microseconds field */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* the kernel expects -0.3s as {-1, 7000.000.000} */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug(" adjust (jump): %+.3f sec\n", offset);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * An unset STA_UNSYNC will enable the kernel's 11-minute mode,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * which syncs the system time periodically to the RTC.
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * In case the RTC runs in local time, never touch the RTC,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * we have no way to properly handle daylight saving changes and
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering * mobile devices moving between time zones.
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering " time now : %li.%03llu\n"
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering " constant : %li\n"
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering " offset : %+.3f sec\n"
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering " freq offset : %+li (%i ppm)\n",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
a6c616024db23fef34152c1432892824a07799ccLennart Poettering tmx.time.tv_sec, (unsigned long long) (tmx.time.tv_usec / NSEC_PER_MSEC),
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic bool manager_sample_spike_detection(Manager *m, double offset, double delay) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering unsigned int i, idx_cur, idx_new, idx_min;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* ignore initial sample */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* store the current data in our samples array */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < ELEMENTSOF(m->samples); i++)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers j += square(m->samples[i].offset - m->samples[idx_min].offset);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* ignore samples when resyncing */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* always accept offset if we are farther off than the round-trip delay */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* we need a few samples before looking at them */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* do not accept anything worse than the maximum possible error of the best sample */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* compare the difference between the current offset to the previous offset and jitter */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void manager_adjust_poll(Manager *m, double offset, bool spike) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* set to minimal poll interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* increase polling interval */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* decrease polling interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Server connection returned error.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_warning("Error receiving message. Disconnecting.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Invalid response from server. Disconnecting.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Response from unknown server.");
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering recv_time = (struct timeval *) CMSG_DATA(cmsg);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Unexpected reply. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Invalid reply; not our transmit time. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 ||
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_debug("Invalid reply, returned times before epoch. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC ||
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) {
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poettering log_debug("Server is not synchronized. Disconnecting.");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) {
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field));
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* valid packet */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* announce leap seconds */
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC)
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering * "Timestamp Name ID When Generated
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * ------------------------------------------------------------
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * Originate Timestamp T1 time request sent by client
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Receive Timestamp T2 time request received by server
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Transmit Timestamp T3 time reply sent by server
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Destination Timestamp T4 time reply received by client
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * The round-trip delay, d, and system clock offset, t, are defined as:
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering receive = ntp_ts_to_d(&ntpmsg.recv_time);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering dest = tv_to_d(recv_time) + OFFSET_1900_1970;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering offset = ((receive - origin) + (trans - dest)) / 2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering delay = (dest - origin) - (trans - receive);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering spike = manager_sample_spike_detection(m, offset, delay);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " leap : %u\n"
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering " version : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " mode : %u\n"
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering " stratum : %u\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " precision : %.6f sec (%d)\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " reference : %.4s\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " origin : %.3f\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " receive : %.3f\n"
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering " transmit : %.3f\n"
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering " dest : %.3f\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " offset : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " delay : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " jitter : %.3f%s\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering exp2(ntpmsg.precision), ntpmsg.precision,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->samples_jitter, spike ? " spike" : "",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_adjust_clock(m, offset, leap_sec);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to call clock_adjtime(): %m");
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering log_info("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_arm_timer(m, m->poll_interval_usec);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to rearm timer: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_listen_setup(Manager *m) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_return(m->current_server_name, -EHOSTUNREACH);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_return(m->current_server_address, -EHOSTUNREACH);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering server_address_pretty(m->current_server_address, &pretty);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_info("Using NTP server %s (%s).", strna(pretty), m->current_server_name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_notifyf(false, "STATUS=Using Time Server %s (%s).", strna(pretty), m->current_server_name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning("Failed to setup connection socket: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringvoid manager_set_server_name(Manager *m, ServerName *n) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Selected server %s.", n->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringvoid manager_set_server_address(Manager *m, ServerAddress *a) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->current_server_name = a ? a->name : NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Selected address %s of server %s.", strna(pretty), a->name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) {
a6c616024db23fef34152c1432892824a07799ccLennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Try next host */
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data));
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning("Unsuitable address protocol for %s", m->current_server_name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_error("Failed to add server address: %s", strerror(-r));
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!m->current_server_name->addresses) {
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek log_error("Failed to find suitable address for host %s.", m->current_server_name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Try next host */
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen manager_set_server_address(m, m->current_server_name->addresses);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_retry = sd_event_source_unref(m->event_retry);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Slowing down attempts to contact servers.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create retry timer: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If we already are operating on some address, switch to the
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * next one. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->current_server_address && m->current_server_address->addresses_next)
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen manager_set_server_address(m, m->current_server_address->addresses_next);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Hmm, we are through all addresses, let's look for the next host instead */
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (m->current_server_name && m->current_server_name->names_next)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_server_name(m, m->current_server_name->names_next);
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek /* Our current server name list is exhausted,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * let's find the next one to iterate. First
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * we try the system list, then the link list.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * After having processed the link list we
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * jump back to the system list. However, if
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek * both lists are empty, we change to the
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek * fallback list. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Tell the resolver to reread /etc/resolv.conf, in
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * case it changed. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Flush out any previously resolved addresses */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_flush_addresses(m->current_server_name);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen log_debug("Resolving %s...", m->current_server_name->string);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create resolver: %s", strerror(-r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering m->event_timer = sd_event_source_unref(m->event_timer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_receive = sd_event_source_unref(m->event_receive);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->server_socket = safe_close(m->server_socket);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->clock_watch_fd = safe_close(m->clock_watch_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringvoid manager_flush_server_names(Manager *m, ServerType t) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_SYSTEM);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_LINK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_FALLBACK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_source_unref(m->network_event_source);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_network_monitor_unref(m->network_monitor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_network_read_link_servers(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = server_name_new(m, NULL, SERVER_LINK, *i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_SAFE(names, n, nx, m->link_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_LINK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_network_monitor_flush(m->network_monitor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check if the machine is online */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check if the client is currently connected */
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering connected = m->server_socket >= 0 || m->resolve_query;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_info("No network connectivity, watching for changes.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("Network configuration changed, trying to establish connection.");
assert(m);
if (fd < 0)
return fd;
if (events < 0)
return events;
r = sd_event_add_io(m->event, &m->network_event_source, fd, events, manager_network_event_handler, m);
return -ENOMEM;
r = manager_network_monitor_listen(m);
*ret = m;
m = NULL;