+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
/* expected accuracy of time synchronization; used to adjust the poll interval */
#define NTP_ACCURACY_SEC 0.2
-/*
- * "A client MUST NOT under any conditions use a poll interval less
- * than 15 seconds."
- */
-#define NTP_POLL_INTERVAL_MIN_SEC 32
-#define NTP_POLL_INTERVAL_MAX_SEC 2048
-
/*
* Maximum delta in seconds which the system clock is gradually adjusted
- * (slew) to approach the network time. Deltas larger that this are set by
+ * (slewed) to approach the network time. Deltas larger that this are set by
* letting the system time jump. The kernel's limit for adjtime is 0.5s.
*/
#define NTP_MAX_ADJUST 0.4
#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
+/* Default of maximum acceptable root distance in microseconds. */
+#define NTP_MAX_ROOT_DISTANCE (5 * USEC_PER_SEC)
/* Maximum number of missed replies before selecting another source. */
#define NTP_MAX_MISSED_REPLIES 2
/* re-arm timer with increasing timeout, in case the packets never arrive back */
if (m->retry_interval > 0) {
- if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
+ if (m->retry_interval < m->poll_interval_max_usec)
m->retry_interval *= 2;
} else
- m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
+ m->retry_interval = m->poll_interval_min_usec;
r = manager_arm_timer(m, m->retry_interval);
if (r < 0)
tmx.esterror = 0;
log_debug(" adjust (slew): %+.3f sec", offset);
} else {
- tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET;
+ tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
/* ADJ_NANO uses nanoseconds in the microseconds field */
tmx.time.tv_sec = (long)offset;
tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
+ tmx.maxerror = 0;
+ tmx.esterror = 0;
/* the kernel expects -0.3s as {-1, 7000.000.000} */
if (tmx.time.tv_usec < 0) {
return -errno;
/* If touch fails, there isn't much we can do. Maybe it'll work next time. */
- (void) touch("/var/lib/systemd/clock");
+ (void) touch("/var/lib/systemd/timesync/clock");
m->drift_ppm = tmx.freq / 65536;
log_debug(" status : %04i %s\n"
- " time now : %li.%03"PRI_USEC"\n"
- " constant : %li\n"
+ " time now : %"PRI_TIME".%03"PRI_USEC"\n"
+ " constant : %"PRI_TIMEX"\n"
" offset : %+.3f sec\n"
- " freq offset : %+li (%i ppm)\n",
+ " freq offset : %+"PRI_TIMEX" (%i ppm)\n",
tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC,
tmx.constant,
assert(m);
if (m->poll_resync) {
- m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
+ m->poll_interval_usec = m->poll_interval_min_usec;
m->poll_resync = false;
return;
}
/* set to minimal poll interval */
if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
- m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
+ m->poll_interval_usec = m->poll_interval_min_usec;
return;
}
/* increase polling interval */
if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
- if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
+ if (m->poll_interval_usec < m->poll_interval_max_usec)
m->poll_interval_usec *= 2;
return;
}
/* decrease polling interval */
if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
- if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
+ if (m->poll_interval_usec > m->poll_interval_min_usec)
m->poll_interval_usec /= 2;
return;
}
.msg_namelen = sizeof(server_addr),
};
struct cmsghdr *cmsg;
- struct timespec *recv_time;
+ struct timespec *recv_time = NULL;
ssize_t len;
double origin, receive, trans, dest;
double delay, offset;
return 0;
}
- recv_time = NULL;
CMSG_FOREACH(cmsg, &msghdr) {
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
/* check our "time cookie" (we just stored nanoseconds in the fraction field) */
if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
- be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
+ be32toh(ntpmsg.origin_time.frac) != (unsigned long) m->trans_time.tv_nsec) {
log_debug("Invalid reply; not our transmit time. Ignoring.");
return 0;
}
}
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) {
+ if (root_distance > (double) m->max_root_distance_usec / (double) USEC_PER_SEC) {
log_debug("Server has too large root distance. Disconnecting.");
return manager_connect(m);
}
m->good = false;
m->missed_replies = NTP_MAX_MISSED_REPLIES;
if (m->poll_interval_usec == 0)
- m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
+ m->poll_interval_usec = m->poll_interval_min_usec;
server_address_pretty(m->current_server_address, &pretty);
log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
m->exhausted_servers = true;
/* Increase the polling interval */
- if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
+ if (m->poll_interval_usec < m->poll_interval_max_usec)
m->poll_interval_usec *= 2;
return 0;
_cleanup_strv_free_ char **ntp = NULL;
ServerName *n, *nx;
char **i;
+ bool changed = false;
int r;
assert(m);
r = server_name_new(m, NULL, SERVER_LINK, *i);
if (r < 0)
goto clear;
+
+ changed = true;
}
}
LIST_FOREACH_SAFE(names, n, nx, m->link_servers)
- if (n->marked)
+ if (n->marked) {
server_name_free(n);
+ changed = true;
+ }
- return 0;
+ return changed;
clear:
manager_flush_server_names(m, SERVER_LINK);
static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
- bool connected, online;
+ bool changed, connected, online;
int r;
assert(m);
sd_network_monitor_flush(m->network_monitor);
- manager_network_read_link_servers(m);
+ changed = !!manager_network_read_link_servers(m);
/* check if the machine is online */
online = network_is_online();
log_info("No network connectivity, watching for changes.");
manager_disconnect(m);
- } else if (!connected && online) {
+ } else if (!connected && online && changed) {
log_info("Network configuration changed, trying to establish connection.");
if (m->current_server_address)
assert(m);
r = sd_network_monitor_new(&m->network_monitor, NULL);
+ if (r == -ENOENT) {
+ log_info("systemd does not appear to be running, not listening for systemd-networkd events.");
+ return 0;
+ }
if (r < 0)
return r;
if (!m)
return -ENOMEM;
+ m->max_root_distance_usec = NTP_MAX_ROOT_DISTANCE;
+ m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
+ m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC;
+
m->server_socket = m->clock_watch_fd = -1;
RATELIMIT_INIT(m->ratelimit, RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST);
- r = manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS);
- if (r < 0)
- return r;
-
r = sd_event_default(&m->event);
if (r < 0)
return r;
manager_network_read_link_servers(m);
- *ret = m;
- m = NULL;
+ *ret = TAKE_PTR(m);
return 0;
}