timesyncd: read server settings from a configuration file
Also, allow compiling in a default server list via a configure command line item.
This commit is contained in:
parent
16c058ba01
commit
e8af69739a
29
Makefile.am
29
Makefile.am
|
@ -128,6 +128,7 @@ polkitpolicy_in_files =
|
||||||
polkitpolicy_files =
|
polkitpolicy_files =
|
||||||
dist_udevrules_DATA =
|
dist_udevrules_DATA =
|
||||||
nodist_udevrules_DATA =
|
nodist_udevrules_DATA =
|
||||||
|
nodist_pkgsysconf_DATA =
|
||||||
dist_pkgsysconf_DATA =
|
dist_pkgsysconf_DATA =
|
||||||
dist_pkgdata_DATA =
|
dist_pkgdata_DATA =
|
||||||
dist_dbuspolicy_DATA =
|
dist_dbuspolicy_DATA =
|
||||||
|
@ -4017,7 +4018,17 @@ EXTRA_DIST += \
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
if ENABLE_TIMESYNCD
|
if ENABLE_TIMESYNCD
|
||||||
systemd_timesyncd_SOURCES = \
|
systemd_timesyncd_SOURCES = \
|
||||||
src/timesync/timesyncd.c
|
src/timesync/timesyncd.c \
|
||||||
|
src/timesync/timesyncd.h
|
||||||
|
|
||||||
|
nodist_systemd_timesyncd_SOURCES = \
|
||||||
|
src/timesync/timesyncd-gperf.c
|
||||||
|
|
||||||
|
EXTRA_DIST += \
|
||||||
|
src/timesync/timesyncd-gperf.gperf
|
||||||
|
|
||||||
|
CLEANFILES += \
|
||||||
|
src/timesync/timesyncd-gperf.c
|
||||||
|
|
||||||
systemd_timesyncd_LDADD = \
|
systemd_timesyncd_LDADD = \
|
||||||
libsystemd-label.la \
|
libsystemd-label.la \
|
||||||
|
@ -4034,6 +4045,16 @@ nodist_systemunit_DATA += \
|
||||||
|
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
units/systemd-timesyncd.service.in
|
units/systemd-timesyncd.service.in
|
||||||
|
|
||||||
|
nodist_pkgsysconf_DATA += \
|
||||||
|
src/timesync/timesyncd.conf
|
||||||
|
|
||||||
|
EXTRA_DIST += \
|
||||||
|
src/timesync/timesyncd.conf.in
|
||||||
|
|
||||||
|
CLEANFILES += \
|
||||||
|
src/timesync/timesyncd.conf
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -4763,7 +4784,8 @@ substitutions = \
|
||||||
'|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \
|
'|RC_LOCAL_SCRIPT_PATH_START=$(RC_LOCAL_SCRIPT_PATH_START)|' \
|
||||||
'|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \
|
'|RC_LOCAL_SCRIPT_PATH_STOP=$(RC_LOCAL_SCRIPT_PATH_STOP)|' \
|
||||||
'|PYTHON=$(PYTHON)|' \
|
'|PYTHON=$(PYTHON)|' \
|
||||||
'|PYTHON_BINARY=$(PYTHON_BINARY)|'
|
'|PYTHON_BINARY=$(PYTHON_BINARY)|' \
|
||||||
|
'|NTP_SERVERS=$(NTP_SERVERS)|'
|
||||||
|
|
||||||
SED_PROCESS = \
|
SED_PROCESS = \
|
||||||
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
|
$(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
|
||||||
|
@ -4791,6 +4813,9 @@ src/%.policy.in: src/%.policy.in.in
|
||||||
%.rules: %.rules.in
|
%.rules: %.rules.in
|
||||||
$(SED_PROCESS)
|
$(SED_PROCESS)
|
||||||
|
|
||||||
|
%.conf: %.conf.in
|
||||||
|
$(SED_PROCESS)
|
||||||
|
|
||||||
%.sh: %.sh.in
|
%.sh: %.sh.in
|
||||||
$(SED_PROCESS)
|
$(SED_PROCESS)
|
||||||
$(AM_V_GEN)chmod +x $@
|
$(AM_V_GEN)chmod +x $@
|
||||||
|
|
10
configure.ac
10
configure.ac
|
@ -827,6 +827,15 @@ if test "x$enable_timesyncd" != "xno"; then
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(ENABLE_TIMESYNCD, [test "$have_timesyncd" = "yes"])
|
AM_CONDITIONAL(ENABLE_TIMESYNCD, [test "$have_timesyncd" = "yes"])
|
||||||
|
|
||||||
|
AC_ARG_WITH(ntp-servers,
|
||||||
|
AS_HELP_STRING([--with-ntp-servers=NTPSERVERS],
|
||||||
|
[Space-separated list of default NTP servers]),
|
||||||
|
[NTP_SERVERS="$withval"],
|
||||||
|
[NTP_SERVERS="time1.google.com time2.google.com time3.google.com time4.google.com"])
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(NTP_SERVERS, ["$NTP_SERVERS"], [Default NTP Servers])
|
||||||
|
AC_SUBST(NTP_SERVERS)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
have_localed=no
|
have_localed=no
|
||||||
AC_ARG_ENABLE(localed, AS_HELP_STRING([--disable-localed], [disable locale daemon]))
|
AC_ARG_ENABLE(localed, AS_HELP_STRING([--disable-localed], [disable locale daemon]))
|
||||||
|
@ -1159,6 +1168,7 @@ AC_MSG_RESULT([
|
||||||
hostnamed: ${have_hostnamed}
|
hostnamed: ${have_hostnamed}
|
||||||
timedated: ${have_timedated}
|
timedated: ${have_timedated}
|
||||||
timesyncd: ${have_timesyncd}
|
timesyncd: ${have_timesyncd}
|
||||||
|
default NTP servers: ${NTP_SERVERS}
|
||||||
localed: ${have_localed}
|
localed: ${have_localed}
|
||||||
networkd: ${have_networkd}
|
networkd: ${have_networkd}
|
||||||
coredump: ${have_coredump}
|
coredump: ${have_coredump}
|
||||||
|
|
2
src/timesync/.gitignore
vendored
Normal file
2
src/timesync/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/timesyncd.conf
|
||||||
|
/timesyncd-gperf.c
|
1
src/timesync/Makefile
Symbolic link
1
src/timesync/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../Makefile
|
17
src/timesync/timesyncd-gperf.gperf
Normal file
17
src/timesync/timesyncd-gperf.gperf
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
%{
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "conf-parser.h"
|
||||||
|
#include "timesyncd.h"
|
||||||
|
%}
|
||||||
|
struct ConfigPerfItem;
|
||||||
|
%null_strings
|
||||||
|
%language=ANSI-C
|
||||||
|
%define slot-name section_and_lvalue
|
||||||
|
%define hash-function-name timesyncdd_gperf_hash
|
||||||
|
%define lookup-function-name timesyncd_gperf_lookup
|
||||||
|
%readonly-tables
|
||||||
|
%omit-struct-type
|
||||||
|
%struct-type
|
||||||
|
%includes
|
||||||
|
%%
|
||||||
|
Time.Servers, config_parse_servers, 0, 0
|
|
@ -3,7 +3,7 @@
|
||||||
/***
|
/***
|
||||||
This file is part of systemd.
|
This file is part of systemd.
|
||||||
|
|
||||||
Copyright 2014 Kay Sievers
|
Copyright 2014 Kay Sievers, Lennart Poettering
|
||||||
|
|
||||||
systemd is free software; you can redistribute it and/or modify it
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU Lesser General Public License as published by
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -42,9 +42,11 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "ratelimit.h"
|
#include "ratelimit.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
#include "conf-parser.h"
|
||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
#include "sd-resolve.h"
|
#include "sd-resolve.h"
|
||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
|
#include "timesyncd.h"
|
||||||
|
|
||||||
#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
|
#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
|
||||||
|
|
||||||
|
@ -116,73 +118,6 @@ struct ntp_msg {
|
||||||
struct ntp_ts trans_time;
|
struct ntp_ts trans_time;
|
||||||
} _packed_;
|
} _packed_;
|
||||||
|
|
||||||
typedef struct Manager Manager;
|
|
||||||
typedef struct ServerAddress ServerAddress;
|
|
||||||
typedef struct ServerName ServerName;
|
|
||||||
|
|
||||||
struct ServerAddress {
|
|
||||||
union sockaddr_union sockaddr;
|
|
||||||
socklen_t socklen;
|
|
||||||
LIST_FIELDS(ServerAddress, addresses);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ServerName {
|
|
||||||
char *string;
|
|
||||||
LIST_HEAD(ServerAddress, addresses);
|
|
||||||
LIST_FIELDS(ServerName, names);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Manager {
|
|
||||||
sd_event *event;
|
|
||||||
sd_resolve *resolve;
|
|
||||||
|
|
||||||
LIST_HEAD(ServerName, servers);
|
|
||||||
|
|
||||||
RateLimit ratelimit;
|
|
||||||
|
|
||||||
/* peer */
|
|
||||||
sd_resolve_query *resolve_query;
|
|
||||||
sd_event_source *event_receive;
|
|
||||||
ServerName *current_server_name;
|
|
||||||
ServerAddress *current_server_address;
|
|
||||||
int server_socket;
|
|
||||||
uint64_t packet_count;
|
|
||||||
sd_event_source *event_timeout;
|
|
||||||
|
|
||||||
/* last sent packet */
|
|
||||||
struct timespec trans_time_mon;
|
|
||||||
struct timespec trans_time;
|
|
||||||
usec_t retry_interval;
|
|
||||||
bool pending;
|
|
||||||
|
|
||||||
/* poll timer */
|
|
||||||
sd_event_source *event_timer;
|
|
||||||
usec_t poll_interval_usec;
|
|
||||||
bool poll_resync;
|
|
||||||
|
|
||||||
/* history data */
|
|
||||||
struct {
|
|
||||||
double offset;
|
|
||||||
double delay;
|
|
||||||
} samples[8];
|
|
||||||
unsigned int samples_idx;
|
|
||||||
double samples_jitter;
|
|
||||||
|
|
||||||
/* last change */
|
|
||||||
bool jumped;
|
|
||||||
int drift_ppm;
|
|
||||||
|
|
||||||
/* watch for time changes */
|
|
||||||
sd_event_source *event_clock_watch;
|
|
||||||
int clock_watch_fd;
|
|
||||||
|
|
||||||
/* Retry connections */
|
|
||||||
sd_event_source *event_retry;
|
|
||||||
|
|
||||||
/* Handle SIGINT/SIGTERM */
|
|
||||||
sd_event_source *sigterm, *sigint;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void manager_free(Manager *m);
|
static void manager_free(Manager *m);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||||
#define _cleanup_manager_free_ _cleanup_(manager_freep)
|
#define _cleanup_manager_free_ _cleanup_(manager_freep)
|
||||||
|
@ -974,6 +909,28 @@ static int manager_add_server(Manager *m, const char *server) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int manager_add_server_string(Manager *m, const char *string) {
|
||||||
|
char *w, *state;
|
||||||
|
size_t l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
|
assert(string);
|
||||||
|
|
||||||
|
FOREACH_WORD_QUOTED(w, l, string, state) {
|
||||||
|
char t[l+1];
|
||||||
|
|
||||||
|
memcpy(t, w, l);
|
||||||
|
t[l] = 0;
|
||||||
|
|
||||||
|
r = manager_add_server(m, t);
|
||||||
|
if (r < 0)
|
||||||
|
log_error("Failed to add server %s to configuration, ignoring: %s", t, strerror(-r));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void manager_disconnect(Manager *m) {
|
static void manager_disconnect(Manager *m) {
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
@ -1047,15 +1004,70 @@ static void manager_free(Manager *m) {
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int config_parse_servers(
|
||||||
_cleanup_manager_free_ Manager *m = NULL;
|
const char *unit,
|
||||||
const char *x;
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
Manager *m = userdata;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
manager_flush_names(m);
|
||||||
|
manager_add_server_string(m, rvalue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int manager_parse_config_file(Manager *m) {
|
||||||
|
static const char fn[] = "/etc/systemd/timesyncd.conf";
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
f = fopen(fn, "re");
|
||||||
|
if (!f) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_warning("Failed to open configuration file %s: %m", fn);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = config_parse(NULL, fn, f, "Time\0", config_item_perf_lookup,
|
||||||
|
(void*) timesyncd_gperf_lookup, false, false, m);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning("Failed to parse configuration file: %s", strerror(-r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
_cleanup_manager_free_ Manager *m = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
log_error("This program does not take arguments.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
log_set_target(LOG_TARGET_AUTO);
|
log_set_target(LOG_TARGET_AUTO);
|
||||||
|
log_set_facility(LOG_CRON);
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
|
umask(0022);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
|
assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
|
@ -1064,15 +1076,11 @@ int main(int argc, char *argv[]) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_notify(false, "READY=1");
|
manager_add_server_string(m, NTP_SERVERS);
|
||||||
|
manager_parse_config_file(m);
|
||||||
|
|
||||||
FOREACH_STRING(x, "8.8.8.8", "172.31.0.1", "time1.google.com", "time2.google.com", "time3.google.com", "time4.google.com", "0.fedora.pool.ntp.org") {
|
log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
|
||||||
r = manager_add_server(m, x);
|
sd_notify(false, "READY=1");
|
||||||
if (r < 0) {
|
|
||||||
log_error("Failed to add server %s: %s", x, strerror(-r));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = manager_connect(m);
|
r = manager_connect(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1087,5 +1095,7 @@ int main(int argc, char *argv[]) {
|
||||||
sd_event_get_exit_code(m->event, &r);
|
sd_event_get_exit_code(m->event, &r);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
sd_notify(false, "STATUS=Shutting down...");
|
||||||
|
|
||||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
11
src/timesync/timesyncd.conf.in
Normal file
11
src/timesync/timesyncd.conf.in
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# This file is part of systemd.
|
||||||
|
#
|
||||||
|
# systemd is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# See timesyncd.conf(5) for details
|
||||||
|
|
||||||
|
[Time]
|
||||||
|
#Servers=@NTP_SERVERS@
|
97
src/timesync/timesyncd.h
Normal file
97
src/timesync/timesyncd.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2014 Kay Sievers, Lennart Poettering
|
||||||
|
|
||||||
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
#include "socket-util.h"
|
||||||
|
#include "ratelimit.h"
|
||||||
|
#include "sd-event.h"
|
||||||
|
#include "sd-resolve.h"
|
||||||
|
|
||||||
|
typedef struct Manager Manager;
|
||||||
|
typedef struct ServerAddress ServerAddress;
|
||||||
|
typedef struct ServerName ServerName;
|
||||||
|
|
||||||
|
struct ServerAddress {
|
||||||
|
union sockaddr_union sockaddr;
|
||||||
|
socklen_t socklen;
|
||||||
|
LIST_FIELDS(ServerAddress, addresses);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerName {
|
||||||
|
char *string;
|
||||||
|
LIST_HEAD(ServerAddress, addresses);
|
||||||
|
LIST_FIELDS(ServerName, names);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Manager {
|
||||||
|
sd_event *event;
|
||||||
|
sd_resolve *resolve;
|
||||||
|
|
||||||
|
LIST_HEAD(ServerName, servers);
|
||||||
|
|
||||||
|
RateLimit ratelimit;
|
||||||
|
|
||||||
|
/* peer */
|
||||||
|
sd_resolve_query *resolve_query;
|
||||||
|
sd_event_source *event_receive;
|
||||||
|
ServerName *current_server_name;
|
||||||
|
ServerAddress *current_server_address;
|
||||||
|
int server_socket;
|
||||||
|
uint64_t packet_count;
|
||||||
|
sd_event_source *event_timeout;
|
||||||
|
|
||||||
|
/* last sent packet */
|
||||||
|
struct timespec trans_time_mon;
|
||||||
|
struct timespec trans_time;
|
||||||
|
usec_t retry_interval;
|
||||||
|
bool pending;
|
||||||
|
|
||||||
|
/* poll timer */
|
||||||
|
sd_event_source *event_timer;
|
||||||
|
usec_t poll_interval_usec;
|
||||||
|
bool poll_resync;
|
||||||
|
|
||||||
|
/* history data */
|
||||||
|
struct {
|
||||||
|
double offset;
|
||||||
|
double delay;
|
||||||
|
} samples[8];
|
||||||
|
unsigned int samples_idx;
|
||||||
|
double samples_jitter;
|
||||||
|
|
||||||
|
/* last change */
|
||||||
|
bool jumped;
|
||||||
|
int drift_ppm;
|
||||||
|
|
||||||
|
/* watch for time changes */
|
||||||
|
sd_event_source *event_clock_watch;
|
||||||
|
int clock_watch_fd;
|
||||||
|
|
||||||
|
/* Retry connections */
|
||||||
|
sd_event_source *event_retry;
|
||||||
|
|
||||||
|
/* Handle SIGINT/SIGTERM */
|
||||||
|
sd_event_source *sigterm, *sigint;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, unsigned length);
|
||||||
|
|
||||||
|
int config_parse_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
Loading…
Reference in a new issue