timesyncd-manager.c revision 69f0081748fb4be1b7b772815e5c4202cdb88d3d
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Kay Sievers, Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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
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
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***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <stdlib.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <time.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <math.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <arpa/inet.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <netinet/in.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <netinet/ip.h>
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering#include <sys/timerfd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/timex.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <resolv.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/prctl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/types.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <grp.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "missing.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sparse-endian.h"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "socket-util.h"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#include "list.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "ratelimit.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "conf-parser.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-daemon.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "event-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "network-util.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "clock-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "capability.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "timesyncd-conf.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "timesyncd-manager.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "time-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifndef ADJ_SETOFFSET
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* expected accuracy of time synchronization; used to adjust the poll interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_ACCURACY_SEC 0.2
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * "A client MUST NOT under any conditions use a poll interval less
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * than 15 seconds."
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_POLL_INTERVAL_MIN_SEC 32
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_POLL_INTERVAL_MAX_SEC 2048
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*
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 */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_MAX_ADJUST 0.4
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/* NTP protocol, packet header */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_LEAP_PLUSSEC 1
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_LEAP_MINUSSEC 2
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_LEAP_NOTINSYNC 3
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_MODE_CLIENT 3
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_MODE_SERVER 4
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define NTP_FIELD_LEAP(f) (((f) >> 6) & 3)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_FIELD_VERSION(f) (((f) >> 3) & 7)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_FIELD_MODE(f) ((f) & 7)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m))
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen/* Maximum acceptable root distance in seconds. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define NTP_MAX_ROOT_DISTANCE 5.0
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/* Maximum number of missed replies before selecting another source. */
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering#define NTP_MAX_MISSED_REPLIES 2
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/*
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * in seconds relative to 0h on 1 January 1900."
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define OFFSET_1900_1970 2208988800UL
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering#define RETRY_USEC (30*USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define RATELIMIT_BURST 10
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering#define TIMEOUT_USEC (10*USEC_PER_SEC)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersenstruct ntp_ts {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen be32_t sec;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering be32_t frac;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} _packed_;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstruct ntp_ts_short {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering be16_t sec;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen be16_t frac;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen} _packed_;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstruct ntp_msg {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering uint8_t field;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering uint8_t stratum;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int8_t poll;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int8_t precision;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts_short root_delay;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts_short root_dispersion;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering char refid[4];
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts reference_time;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts origin_time;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts recv_time;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts trans_time;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering} _packed_;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic int manager_arm_timer(Manager *m, usec_t next);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_clock_watch_setup(Manager *m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double ntp_ts_short_to_d(const struct ntp_ts_short *ts) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic double ntp_ts_to_d(const struct ntp_ts *ts) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double ts_to_d(const struct timespec *ts) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstatic double square(double d) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return d * d;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poetteringstatic int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering _cleanup_free_ char *pretty = NULL;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering Manager *m = userdata;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(m->current_server_name);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(m->current_server_address);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering server_address_pretty(m->current_server_address, &pretty);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_info("Timed out waiting for reply from %s (%s).", strna(pretty), m->current_server_name->string);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return manager_connect(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_send_request(Manager *m) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering _cleanup_free_ char *pretty = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_msg ntpmsg = {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /*
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * "The client initializes the NTP message header, sends the request
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * to the server, and strips the time of day from the Transmit
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * Timestamp field of the reply. For this purpose, all the NTP
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * header fields are set to 0, except the Mode, VN, and optional
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * Transmit Timestamp fields."
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering .field = NTP_FIELD(0, 4, NTP_MODE_CLIENT),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering };
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ssize_t len;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m->current_server_name);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(m->current_server_address);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /*
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.
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering *
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 */
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert_se(clock_gettime(clock_boottime_or_monotonic(), &m->trans_time_mon) >= 0);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart 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
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering server_address_pretty(m->current_server_address, &pretty);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (len == sizeof(ntpmsg)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->pending = true;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_debug("Sent NTP request to %s (%s).", strna(pretty), m->current_server_name->string);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_debug("Sending NTP request to %s (%s) failed: %m", strna(pretty), m->current_server_name->string);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return manager_connect(m);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* re-arm timer with increasing timeout, in case the packets never arrive back */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (m->retry_interval > 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->retry_interval *= 2;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = manager_arm_timer(m, m->retry_interval);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Failed to rearm timer: %s", strerror(-r));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->missed_replies++;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (m->missed_replies > NTP_MAX_MISSED_REPLIES) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_event_add_time(
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->event,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering &m->event_timeout,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering clock_boottime_or_monotonic(),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering now(clock_boottime_or_monotonic()) + TIMEOUT_USEC, 0,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering manager_timeout, m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_error("Failed to arm timeout timer: %s", strerror(-r));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return 0;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_timer(sd_event_source *source, usec_t usec, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Manager *m = userdata;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return manager_send_request(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_arm_timer(Manager *m, usec_t next) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(m->event_receive);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (next == 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering m->event_timer = sd_event_source_unref(m->event_timer);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return 0;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (m->event_timer) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_event_add_time(
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering m->event,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering &m->event_timer,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering clock_boottime_or_monotonic(),
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering now(clock_boottime_or_monotonic()) + next, 0,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering manager_timer, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers Manager *m = userdata;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(m);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* rearm timer */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_clock_watch_setup(m);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* skip our own jumps */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->jumped) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->jumped = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* resync */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_info("System time changed. Resyncing.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->poll_resync = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_send_request(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* wake up when the system time changes underneath us */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_clock_watch_setup(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct itimerspec its = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .it_value.tv_sec = TIME_T_MAX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(m->clock_watch_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->clock_watch_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->clock_watch_fd < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create timerfd: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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 return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create clock watch event source: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_adjust_clock(Manager *m, double offset, int leap_sec) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct timex tmx = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(m);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /*
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * For small deltas, tell the kernel to gradually adjust the system
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * clock to the NTP time, larger deltas are just directly set.
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (fabs(offset) < NTP_MAX_ADJUST) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.status = STA_PLL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.offset = offset * NSEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.maxerror = 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.esterror = 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug(" adjust (slew): %+.3f sec\n", offset);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering } else {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* ADJ_NANO uses nanoseconds in the microseconds field */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.time.tv_sec = (long)offset;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* the kernel expects -0.3s as {-1, 7000.000.000} */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (tmx.time.tv_usec < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering tmx.time.tv_sec -= 1;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering tmx.time.tv_usec += NSEC_PER_SEC;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering m->jumped = true;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_debug(" adjust (jump): %+.3f sec\n", offset);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /*
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * An unset STA_UNSYNC will enable the kernel's 11-minute mode,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * which syncs the system time periodically to the RTC.
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering *
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * In case the RTC runs in local time, never touch the RTC,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * we have no way to properly handle daylight saving changes and
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * mobile devices moving between time zones.
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (m->rtc_local_time)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.status |= STA_UNSYNC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering switch (leap_sec) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case 1:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.status |= STA_INS;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering break;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case -1:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.status |= STA_DEL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering break;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = clock_adjtime(CLOCK_REALTIME, &tmx);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers touch("/var/lib/systemd/clock");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering m->drift_ppm = tmx.freq / 65536;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug(" status : %04i %s\n"
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",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers tmx.time.tv_sec, (unsigned long long) (tmx.time.tv_usec / NSEC_PER_MSEC),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers tmx.constant,
a6c616024db23fef34152c1432892824a07799ccLennart Poettering (double)tmx.offset / NSEC_PER_SEC,
a6c616024db23fef34152c1432892824a07799ccLennart Poettering tmx.freq, m->drift_ppm);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool manager_sample_spike_detection(Manager *m, double offset, double delay) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned int i, idx_cur, idx_new, idx_min;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers double jitter;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers double j;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->packet_count++;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* ignore initial sample */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->packet_count == 1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* store the current data in our samples array */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering idx_cur = m->samples_idx;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->samples_idx = idx_new;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples[idx_new].offset = offset;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples[idx_new].delay = delay;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers jitter = m->samples_jitter;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers idx_min = i;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering j = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers for (i = 0; i < ELEMENTSOF(m->samples); i++)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers j += square(m->samples[i].offset - m->samples[idx_min].offset);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* ignore samples when resyncing */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->poll_resync)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters /* always accept offset if we are farther off than the round-trip delay */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (fabs(offset) > delay)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering /* we need a few samples before looking at them */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->packet_count < 4)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* do not accept anything worse than the maximum possible error of the best sample */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (fabs(offset) > m->samples[idx_min].delay)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* compare the difference between the current offset to the previous offset and jitter */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void manager_adjust_poll(Manager *m, double offset, bool spike) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->poll_resync) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->poll_resync = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* set to minimal poll interval */
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* increase polling interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->poll_interval_usec *= 2;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* decrease polling interval */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->poll_interval_usec /= 2;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen Manager *m = userdata;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering struct ntp_msg ntpmsg;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec iov = {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .iov_base = &ntpmsg,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .iov_len = sizeof(ntpmsg),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers };
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers union {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct cmsghdr cmsghdr;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers } control;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering union sockaddr_union server_addr;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct msghdr msghdr = {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen .msg_iov = &iov,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen .msg_iovlen = 1,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .msg_control = &control,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .msg_controllen = sizeof(control),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .msg_name = &server_addr,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .msg_namelen = sizeof(server_addr),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct cmsghdr *cmsg;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct timespec *recv_time;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ssize_t len;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering double origin, receive, trans, dest;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering double delay, offset;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen double root_distance;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool spike;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int leap_sec;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(source);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (revents & (EPOLLHUP|EPOLLERR)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_warning("Server connection returned error.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (len < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno == EAGAIN)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_warning("Error receiving message. Disconnecting.");
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return manager_connect(m);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (iov.iov_len < sizeof(struct ntp_msg)) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_warning("Invalid response from server. Disconnecting.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (!m->current_server_name ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !m->current_server_address ||
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Response from unknown server.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering recv_time = NULL;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (cmsg->cmsg_level != SOL_SOCKET)
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering continue;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering switch (cmsg->cmsg_type) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering case SCM_TIMESTAMPNS:
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering recv_time = (struct timespec *) CMSG_DATA(cmsg);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering break;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (!recv_time) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_error("Invalid packet timestamp.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return -EINVAL;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (!m->pending) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Unexpected reply. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering m->missed_replies = 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
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 ||
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poettering log_debug("Invalid reply; not our transmit time. Ignoring.");
a4475f577bd0daf762d6c3b4e58bc484e0cb74afLennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 ||
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) {
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek log_debug("Invalid reply, returned times before epoch. Ignoring.");
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC ||
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Server is not synchronized. Disconnecting.");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return manager_connect(m);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering }
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) {
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering root_distance = ntp_ts_short_to_d(&ntpmsg.root_delay) / 2 + ntp_ts_short_to_d(&ntpmsg.root_dispersion);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (root_distance > NTP_MAX_ROOT_DISTANCE) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Server has too large root distance. Disconnecting.");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* valid packet */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->pending = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->retry_interval = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* announce leap seconds */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering leap_sec = 1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering leap_sec = -1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering leap_sec = 0;
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /*
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * "Timestamp Name ID When Generated
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * ------------------------------------------------------------
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Originate Timestamp T1 time request sent by client
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Receive Timestamp T2 time request received by server
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering * Transmit Timestamp T3 time reply sent by server
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Destination Timestamp T4 time reply received by client
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering *
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * The round-trip delay, d, and system clock offset, t, are defined as:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970;
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering receive = ntp_ts_to_d(&ntpmsg.recv_time);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering trans = ntp_ts_to_d(&ntpmsg.trans_time);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering dest = ts_to_d(recv_time) + OFFSET_1900_1970;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering offset = ((receive - origin) + (trans - dest)) / 2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering delay = (dest - origin) - (trans - receive);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering spike = manager_sample_spike_detection(m, offset, delay);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering manager_adjust_poll(m, offset, spike);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("NTP response:\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " leap : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " version : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " mode : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " stratum : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " precision : %.6f sec (%d)\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " root distance: %.6f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " reference : %.4s\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " origin : %.3f\n"
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering " receive : %.3f\n"
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering " transmit : %.3f\n"
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering " dest : %.3f\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " offset : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " delay : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " packet count : %"PRIu64"\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " jitter : %.3f%s\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " poll interval: " USEC_FMT "\n",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering NTP_FIELD_LEAP(ntpmsg.field),
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering NTP_FIELD_VERSION(ntpmsg.field),
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering NTP_FIELD_MODE(ntpmsg.field),
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering exp2(ntpmsg.precision), ntpmsg.precision,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering root_distance,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering origin - OFFSET_1900_1970,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering receive - OFFSET_1900_1970,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering trans - OFFSET_1900_1970,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering dest - OFFSET_1900_1970,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering offset, delay,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->packet_count,
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering m->samples_jitter, spike ? " spike" : "",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->poll_interval_usec / USEC_PER_SEC);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!spike) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->sync = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_adjust_clock(m, offset, leap_sec);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to call clock_adjtime(): %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_info("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering spike ? " (ignored)" : "");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_arm_timer(m, m->poll_interval_usec);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to rearm timer: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_listen_setup(Manager *m) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering union sockaddr_union addr = {};
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const int tos = IPTOS_LOWDELAY;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const int on = 1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m->server_socket < 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(!m->event_receive);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m->current_server_address);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering if (m->server_socket < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMPNS, &on, sizeof(on));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering (void) setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_begin(Manager *m) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_free_ char *pretty = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
3db729cb8e6822114e9323f4041dcdc080f2fb3cJason A. Donenfeld assert(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_return(m->current_server_name, -EHOSTUNREACH);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_return(m->current_server_address, -EHOSTUNREACH);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->missed_replies = NTP_MAX_MISSED_REPLIES;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (m->poll_interval_usec == 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
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
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_listen_setup(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning("Failed to setup connection socket: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = manager_clock_watch_setup(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return manager_send_request(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringvoid manager_set_server_name(Manager *m, ServerName *n) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering if (m->current_server_name == n)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->current_server_name = n;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->current_server_address = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering manager_disconnect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (n)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Selected server %s.", n->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringvoid manager_set_server_address(Manager *m, ServerAddress *a) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (m->current_server_address == a)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->current_server_address = a;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* If a is NULL, we are just clearing the address, without
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * changing the name. Keep the existing name in that case. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (a)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->current_server_name = a->name;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_disconnect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (a) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen _cleanup_free_ char *pretty = NULL;
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering server_address_pretty(a, &pretty);
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering log_debug("Selected address %s of server %s.", strna(pretty), a->name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering Manager *m = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek assert(q);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek assert(m);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering assert(m->current_server_name);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (ret != 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Try next host */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (; ai; ai = ai->ai_next) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *pretty = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ServerAddress *a;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen assert(ai->ai_addr);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Unsuitable address protocol for %s", m->current_server_name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to add server address: %s", strerror(-r));
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_address_pretty(a, &pretty);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string);
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m->current_server_name->addresses) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering log_error("Failed to find suitable address for host %s.", m->current_server_name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Try next host */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_server_address(m, m->current_server_name->addresses);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_begin(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Manager *m = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringint manager_connect(Manager *m) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_disconnect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_retry = sd_event_source_unref(m->event_retry);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ratelimit_test(&m->ratelimit)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Slowing down attempts to contact servers.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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 if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create retry timer: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If we already are operating on some address, switch to the
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen * next one. */
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen 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);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct addrinfo hints = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .ai_socktype = SOCK_DGRAM,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Hmm, we are through all addresses, let's look for the next host instead */
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ServerName *f;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool restart = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Our current server name list is exhausted,
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering * let's find the next one to iterate. First
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * we try the system list, then the link list.
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * After having processed the link list we
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * jump back to the system list. However, if
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * both lists are empty, we change to the
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering * fallback list. */
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->system_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->link_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->link_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f)
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering f = m->system_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering restart = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->fallback_servers;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_server_name(m, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("No server found.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (restart && !m->exhausted_servers && m->poll_interval_usec) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Waiting after exhausting servers.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + m->poll_interval_usec, 0, manager_retry_connect, m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create retry timer: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->exhausted_servers = true;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering /* Increase the polling interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->poll_interval_usec *= 2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->exhausted_servers = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_server_name(m, f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Tell the resolver to reread /etc/resolv.conf, in
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * case it changed. */
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering res_init();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Flush out any previously resolved addresses */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_flush_addresses(m->current_server_name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Resolving %s...", m->current_server_name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to create resolver: %s", strerror(-r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = manager_begin(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid manager_disconnect(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_timer = sd_event_source_unref(m->event_timer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_receive = sd_event_source_unref(m->event_receive);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->server_socket = safe_close(m->server_socket);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_notifyf(false, "STATUS=Idle.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid manager_flush_server_names(Manager *m, ServerType t) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (t == SERVER_SYSTEM)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (m->system_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_free(m->system_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (t == SERVER_LINK)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (m->link_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_free(m->link_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (t == SERVER_FALLBACK)
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering while (m->fallback_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_free(m->fallback_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid manager_free(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_disconnect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_SYSTEM);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering manager_flush_server_names(m, SERVER_LINK);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen manager_flush_server_names(m, SERVER_FALLBACK);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_event_source_unref(m->event_retry);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_source_unref(m->network_event_source);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_network_monitor_unref(m->network_monitor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_resolve_unref(m->resolve);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_unref(m->event);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering free(m);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering}
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_network_read_link_servers(Manager *m) {
_cleanup_strv_free_ char **ntp = NULL;
ServerName *n, *nx;
char **i;
int r;
assert(m);
r = sd_network_get_ntp(&ntp);
if (r < 0)
goto clear;
LIST_FOREACH(names, n, m->link_servers)
n->marked = true;
STRV_FOREACH(i, ntp) {
bool found = false;
LIST_FOREACH(names, n, m->link_servers)
if (streq(n->string, *i)) {
n->marked = false;
found = true;
break;
}
if (!found) {
r = server_name_new(m, NULL, SERVER_LINK, *i);
if (r < 0)
goto clear;
}
}
LIST_FOREACH_SAFE(names, n, nx, m->link_servers)
if (n->marked)
server_name_free(n);
return 0;
clear:
manager_flush_server_names(m, SERVER_LINK);
return r;
}
static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
bool connected, online;
int r;
assert(m);
sd_network_monitor_flush(m->network_monitor);
manager_network_read_link_servers(m);
/* check if the machine is online */
online = network_is_online();
/* check if the client is currently connected */
connected = m->server_socket >= 0 || m->resolve_query || m->exhausted_servers;
if (connected && !online) {
log_info("No network connectivity, watching for changes.");
manager_disconnect(m);
} else if (!connected && online) {
log_info("Network configuration changed, trying to establish connection.");
if (m->current_server_address)
r = manager_begin(m);
else
r = manager_connect(m);
if (r < 0)
return r;
}
return 0;
}
static int manager_network_monitor_listen(Manager *m) {
int r, fd, events;
assert(m);
r = sd_network_monitor_new(&m->network_monitor, NULL);
if (r < 0)
return r;
fd = sd_network_monitor_get_fd(m->network_monitor);
if (fd < 0)
return fd;
events = sd_network_monitor_get_events(m->network_monitor);
if (events < 0)
return events;
r = sd_event_add_io(m->event, &m->network_event_source, fd, events, manager_network_event_handler, m);
if (r < 0)
return r;
return 0;
}
int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
assert(ret);
m = new0(Manager, 1);
if (!m)
return -ENOMEM;
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;
sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
sd_event_set_watchdog(m->event, true);
r = sd_resolve_default(&m->resolve);
if (r < 0)
return r;
r = sd_resolve_attach_event(m->resolve, m->event, 0);
if (r < 0)
return r;
r = manager_network_monitor_listen(m);
if (r < 0)
return r;
manager_network_read_link_servers(m);
*ret = m;
m = NULL;
return 0;
}