timesyncd-manager.c revision 73c76e6330d31e1d04454fd7408dd56b4eedca9f
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"
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart 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"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "clock-util.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "capability.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "timesyncd-conf.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "timesyncd-manager.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
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/*
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * in seconds relative to 0h on 1 January 1900."
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen */
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering#define OFFSET_1900_1970 2208988800UL
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define RETRY_USEC (30*USEC_PER_SEC)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define RATELIMIT_BURST 10
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define TIMEOUT_USEC (10*USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstruct ntp_ts {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen be32_t sec;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen be32_t frac;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen} _packed_;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstruct ntp_ts_short {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen be16_t sec;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen be16_t frac;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} _packed_;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstruct ntp_msg {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint8_t field;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering uint8_t stratum;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int8_t poll;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int8_t precision;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts_short root_delay;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering struct ntp_ts_short root_dispersion;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart 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_;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart 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_to_d(const struct ntp_ts *ts) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double ts_to_d(const struct timespec *ts) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic double tv_to_d(const struct timeval *tv) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return tv->tv_sec + (1.0e-6 * tv->tv_usec);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic double square(double d) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return d * d;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering _cleanup_free_ char *pretty = NULL;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering Manager *m = userdata;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(m);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(m->current_server_name);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(m->current_server_address);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering server_address_pretty(m->current_server_address, &pretty);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering log_info("Timed out waiting for reply from %s (%s).", strna(pretty), m->current_server_name->string);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return manager_connect(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int manager_send_request(Manager *m) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart 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
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * to the server, and strips the time of day from the Transmit
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * Timestamp field of the reply. For this purpose, all the NTP
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering * header fields are set to 0, except the Mode, VN, and optional
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * Transmit Timestamp fields."
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering .field = NTP_FIELD(0, 4, NTP_MODE_CLIENT),
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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.
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart 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 */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(clock_gettime(clock_boottime_or_monotonic(), &m->trans_time_mon) >= 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering server_address_pretty(m->current_server_address, &pretty);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering 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 {
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering log_debug("Sending NTP request to %s (%s) failed: %m", strna(pretty), m->current_server_name->string);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return manager_connect(m);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* re-arm timer with increasing timeout, in case the packets never arrive back */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (m->retry_interval > 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->retry_interval *= 2;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering } else
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = manager_arm_timer(m, m->retry_interval);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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 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);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_error("Failed to arm timeout timer: %s", strerror(-r));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart 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);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering Manager *m = userdata;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(m);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* rearm timer */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering manager_clock_watch_setup(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* skip our own jumps */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->jumped) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->jumped = false;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* resync */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("System time changed. Resyncing.");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering m->poll_resync = true;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_send_request(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* wake up when the system time changes underneath us */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_clock_watch_setup(Manager *m) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart 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;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /*
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * For small deltas, tell the kernel to gradually adjust the system
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * clock to the NTP time, larger deltas are just directly set.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fabs(offset) < NTP_MAX_ADJUST) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.time.tv_sec -= 1;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.time.tv_usec += NSEC_PER_SEC;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering m->jumped = true;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_debug(" adjust (jump): %+.3f sec\n", offset);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /*
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * An unset STA_UNSYNC will enable the kernel's 11-minute mode,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * which syncs the system time periodically to the RTC.
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering *
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * In case the RTC runs in local time, never touch the RTC,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * we have no way to properly handle daylight saving changes and
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering * mobile devices moving between time zones.
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (m->rtc_local_time)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering tmx.status |= STA_UNSYNC;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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)
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek return r;
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering 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",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync",
a6c616024db23fef34152c1432892824a07799ccLennart Poettering tmx.time.tv_sec, (unsigned long long) (tmx.time.tv_usec / NSEC_PER_MSEC),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers tmx.constant,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering (double)tmx.offset / NSEC_PER_SEC,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering tmx.freq, m->drift_ppm);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic bool manager_sample_spike_detection(Manager *m, double offset, double delay) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering unsigned int i, idx_cur, idx_new, idx_min;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering double jitter;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers double j;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a6c616024db23fef34152c1432892824a07799ccLennart Poettering assert(m);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->packet_count++;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* ignore initial sample */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->packet_count == 1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* store the current data in our samples array */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers idx_cur = m->samples_idx;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples_idx = idx_new;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->samples[idx_new].offset = offset;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples[idx_new].delay = delay;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering jitter = m->samples_jitter;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering idx_min = i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers j = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < ELEMENTSOF(m->samples); i++)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers j += square(m->samples[i].offset - m->samples[idx_min].offset);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* ignore samples when resyncing */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (m->poll_resync)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* always accept offset if we are farther off than the round-trip delay */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (fabs(offset) > delay)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return false;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* we need a few samples before looking at them */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->packet_count < 4)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return false;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* do not accept anything worse than the maximum possible error of the best sample */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (fabs(offset) > m->samples[idx_min].delay)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return true;
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* compare the difference between the current offset to the previous offset and jitter */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void manager_adjust_poll(Manager *m, double offset, bool spike) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (m->poll_resync) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->poll_resync = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* set to minimal poll interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* increase polling interval */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers m->poll_interval_usec *= 2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* decrease polling interval */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m->poll_interval_usec /= 2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
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;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct ntp_msg ntpmsg;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct iovec iov = {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen .iov_base = &ntpmsg,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen .iov_len = sizeof(ntpmsg),
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen };
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen union {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct cmsghdr cmsghdr;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen } control;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen union sockaddr_union server_addr;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering struct msghdr msghdr = {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering .msg_iov = &iov,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .msg_iovlen = 1,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .msg_control = &control,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .msg_controllen = sizeof(control),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .msg_name = &server_addr,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers .msg_namelen = sizeof(server_addr),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct cmsghdr *cmsg;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers struct timeval *recv_time;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ssize_t len;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering double origin, receive, trans, dest;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen double delay, offset;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool spike;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int leap_sec;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(source);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (revents & (EPOLLHUP|EPOLLERR)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Server connection returned error.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (len < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (errno == EAGAIN)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_warning("Error receiving message. Disconnecting.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return manager_connect(m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (iov.iov_len < sizeof(struct ntp_msg)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Invalid response from server. Disconnecting.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m->current_server_name ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !m->current_server_address ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Response from unknown server.");
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return 0;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering recv_time = NULL;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cmsg->cmsg_level != SOL_SOCKET)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering continue;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering switch (cmsg->cmsg_type) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case SCM_TIMESTAMP:
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering recv_time = (struct timeval *) CMSG_DATA(cmsg);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (!recv_time) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_error("Invalid packet timestamp.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return -EINVAL;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart 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 /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering log_debug("Invalid reply; not our transmit time. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return 0;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering m->event_timeout = sd_event_source_unref(m->event_timeout);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 ||
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering log_debug("Invalid reply, returned times before epoch. Ignoring.");
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return manager_connect(m);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC ||
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) {
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poettering log_debug("Server is not synchronized. Disconnecting.");
a4475f577bd0daf762d6c3b4e58bc484e0cb74afLennart Poettering return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) {
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field));
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek return manager_connect(m);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek }
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field));
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen return manager_connect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* valid packet */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering m->pending = false;
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering m->retry_interval = 0;
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* announce leap seconds */
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart 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;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /*
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering * "Timestamp Name ID When Generated
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * ------------------------------------------------------------
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * Originate Timestamp T1 time request sent by client
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Receive Timestamp T2 time request received by server
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Transmit Timestamp T3 time reply sent by server
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * Destination Timestamp T4 time reply received by client
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * The round-trip delay, d, and system clock offset, t, are defined as:
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering receive = ntp_ts_to_d(&ntpmsg.recv_time);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering trans = ntp_ts_to_d(&ntpmsg.trans_time);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering dest = tv_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
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart 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"
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering " version : %u\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " mode : %u\n"
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering " stratum : %u\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " precision : %.6f sec (%d)\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " reference : %.4s\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " origin : %.3f\n"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering " receive : %.3f\n"
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering " transmit : %.3f\n"
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering " dest : %.3f\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " offset : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " delay : %+.3f sec\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " 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 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,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->samples_jitter, spike ? " spike" : "",
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering m->poll_interval_usec / USEC_PER_SEC);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart 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
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering log_info("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart 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;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_listen_setup(Manager *m) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering union sockaddr_union addr = {};
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const int tos = IPTOS_LOWDELAY;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const int on = 1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(m);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(m->server_socket < 0);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(!m->event_receive);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(m->current_server_address);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (m->server_socket < 0)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart 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_TIMESTAMP, &on, sizeof(on));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 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) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering _cleanup_free_ char *pretty = NULL;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 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->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 }
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart 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);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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);
3db729cb8e6822114e9323f4041dcdc080f2fb3cJason A. Donenfeld}
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_name = a ? a->name : NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering m->current_server_address = a;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering manager_disconnect(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (a) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_free_ char *pretty = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering server_address_pretty(a, &pretty);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Selected address %s of server %s.", strna(pretty), a->name->string);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering Manager *m = userdata;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(q);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(m->current_server_name);
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (ret != 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Try next host */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return manager_connect(m);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering }
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering for (; ai; ai = ai->ai_next) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering _cleanup_free_ char *pretty = NULL;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering ServerAddress *a;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(ai->ai_addr);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data));
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_warning("Unsuitable address protocol for %s", m->current_server_name->string);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering continue;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (r < 0) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_error("Failed to add server address: %s", strerror(-r));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering server_address_pretty(a, &pretty);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!m->current_server_name->addresses) {
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek log_error("Failed to find suitable address for host %s.", m->current_server_name->string);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Try next host */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return manager_connect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen manager_set_server_address(m, m->current_server_name->addresses);
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering return manager_begin(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering Manager *m = userdata;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek return manager_connect(m);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek}
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poetteringint manager_connect(Manager *m) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering int r;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart 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);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen 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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * next one. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->current_server_address && m->current_server_address->addresses_next)
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen manager_set_server_address(m, m->current_server_address->addresses_next);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct addrinfo hints = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering .ai_socktype = SOCK_DGRAM,
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Hmm, we are through all addresses, let's look for the next host instead */
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (m->current_server_name && m->current_server_name->names_next)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_set_server_name(m, m->current_server_name->names_next);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ServerName *f;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek /* Our current server name list is exhausted,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * let's find the next one to iterate. First
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * we try the system list, then the link list.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * After having processed the link list we
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * jump back to the system list. However, if
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek * both lists are empty, we change to the
601185b43da638b1c74153deae01dbd518680889Zbigniew Jędrzejewski-Szmek * fallback list. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->system_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->link_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->link_servers;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (!f)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering f = m->system_servers;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!f)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering f = m->fallback_servers;
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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 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. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen log_debug("Resolving %s...", m->current_server_name->string);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen 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}
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringvoid manager_disconnect(Manager *m) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(m);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering m->resolve_query = sd_resolve_query_unref(m->resolve_query);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart 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);
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart 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);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (t == SERVER_FALLBACK)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (m->fallback_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_free(m->fallback_servers);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poetteringvoid manager_free(Manager *m) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (!m)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_disconnect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_SYSTEM);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_LINK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_FALLBACK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_source_unref(m->event_retry);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_source_unref(m->network_event_source);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_network_monitor_unref(m->network_monitor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_resolve_unref(m->resolve);
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering sd_event_unref(m->event);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_network_read_link_servers(Manager *m) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_strv_free_ char **ntp = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ServerName *n, *nx;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_network_get_ntp(&ntp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto clear;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH(names, n, m->link_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n->marked = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH(i, ntp) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool found = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH(names, n, m->link_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(n->string, *i)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n->marked = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering found = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!found) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = server_name_new(m, NULL, SERVER_LINK, *i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto clear;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FOREACH_SAFE(names, n, nx, m->link_servers)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (n->marked)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_name_free(n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringclear:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_flush_server_names(m, SERVER_LINK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Manager *m = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool connected, online;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_network_monitor_flush(m->network_monitor);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering manager_network_read_link_servers(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check if the machine is online */
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering online = network_is_online();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* check if the client is currently connected */
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering connected = m->server_socket >= 0 || m->resolve_query;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (connected && !online) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_info("No network connectivity, watching for changes.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen manager_disconnect(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else if (!connected && online) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("Network configuration changed, trying to establish connection.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (m->current_server_address)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = manager_begin(m);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering else
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering r = manager_connect(m);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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;
}