timesyncd.c revision 72c0a2c255b172ebbb2a2b7dab7c9aec4c9582d9
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering/***
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering This file is part of systemd.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Copyright 2014 Kay Sievers, Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is free software; you can redistribute it and/or modify it
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering under the terms of the GNU Lesser General Public License as published by
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering (at your option) any later version.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering systemd is distributed in the hope that it will be useful, but
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering Lesser General Public License for more details.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering You should have received a copy of the GNU Lesser General Public License
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering***/
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "sd-event.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "sd-daemon.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "capability.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "clock-util.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "network-util.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "signal-util.h"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering#include "timesyncd-manager.h"
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer#include "timesyncd-conf.h"
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poetteringstatic int load_clock_timestamp(uid_t uid, gid_t gid) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_close_ int fd = -1;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering usec_t min = TIME_EPOCH * USEC_PER_SEC;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering usec_t ct;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering int r;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* Let's try to make sure that the clock is always
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * monotonically increasing, by saving the clock whenever we
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * have a new NTP time, or when we shut down, and restoring it
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * when we start again. This is particularly helpful on
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * systems lacking a battery backed RTC. We also will adjust
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering * the time to at least the build time of systemd. */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering fd = open("/var/lib/systemd/clock", O_RDWR|O_CLOEXEC, 0644);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (fd >= 0) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering struct stat st;
2b6bf07dd23bb467099d213c97b3875c5e453491Zbigniew Jędrzejewski-Szmek usec_t stamp;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* check if the recorded time is later than the compiled-in one */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = fstat(fd, &st);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (r >= 0) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering stamp = timespec_load(&st.st_mtim);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (stamp > min)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering min = stamp;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering }
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* Try to fix the access mode, so that we can still
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering touch the file after dropping priviliges */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering fchmod(fd, 0644);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering fchown(fd, uid, gid);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering } else
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* create stamp file with the compiled-in date */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering touch_file("/var/lib/systemd/clock", true, min, uid, gid, 0644);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering ct = now(CLOCK_REALTIME);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (ct < min) {
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering struct timespec ts;
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering char date[FORMAT_TIMESTAMP_MAX];
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s",
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering format_timestamp(date, sizeof(date), min));
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_error_errno(errno, "Failed to restore system clock: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering }
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering return 0;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering}
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poetteringint main(int argc, char *argv[]) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering const char *user = "systemd-timesync";
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering uid_t uid;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering gid_t gid;
d2e54fae5ca7a0f71b5ac8b356a589ff0a09ea0aKay Sievers int r;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering log_set_target(LOG_TARGET_AUTO);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_set_facility(LOG_CRON);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_parse_environment();
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_open();
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering umask(0022);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (argc != 1) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_error("This program does not take arguments.");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = -EINVAL;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering goto finish;
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering }
90b2de37b80603168f4e9c9c81cff7eea4efa21aZbigniew Jędrzejewski-Szmek
90b2de37b80603168f4e9c9c81cff7eea4efa21aZbigniew Jędrzejewski-Szmek r = get_user_creds(&user, &uid, &gid, NULL, NULL);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (r < 0) {
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering log_error_errno(r, "Cannot resolve user name %s: %m", user);
90b2de37b80603168f4e9c9c81cff7eea4efa21aZbigniew Jędrzejewski-Szmek goto finish;
90b2de37b80603168f4e9c9c81cff7eea4efa21aZbigniew Jędrzejewski-Szmek }
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = load_clock_timestamp(uid, gid);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering if (r < 0)
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering goto finish;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (r < 0)
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen goto finish;
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen /* We need one process for ourselves, plus one thread for the asynchronous resolver */
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen if (setrlimit(RLIMIT_NPROC, &RLIMIT_MAKE_CONST(2)) < 0)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_warning_errno(errno, "Failed to lower RLIMIT_NPROC to 2: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering
cc3773810855956bad92337cee8fa193584ab62eLennart Poettering r = manager_new(&m);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (r < 0) {
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to allocate manager: %m");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering goto finish;
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen }
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen if (clock_is_localtime() > 0) {
88231eb62cafc8bb51406919c8cf6019dc1ac916Thomas Hindoe Paaboel Andersen log_info("The system is configured to read the RTC time in the local time zone. "
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering "This mode can not be fully supported. All system time to RTC updates are disabled.");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering m->rtc_local_time = true;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering }
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering r = manager_parse_config_file(m);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering log_warning_errno(r, "Failed to parse configuration file: %m");
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_debug("systemd-timesyncd running as pid %lu", (unsigned long) getpid());
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering sd_notify(false,
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering "READY=1\n"
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering "STATUS=Daemon is running");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (network_is_online()) {
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = manager_connect(m);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering goto finish;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering }
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = sd_event_loop(m->event);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0) {
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering log_error_errno(r, "Failed to run event loop: %m");
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering goto finish;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering }
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering /* if we got an authoritative time, store it in the file system */
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering if (m->sync)
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering touch("/var/lib/systemd/clock");
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering sd_event_get_exit_code(m->event, &r);
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poetteringfinish:
c7b5eb98e8eeafe63a079ee3c51e9670872437aeLennart Poettering sd_notify(false,
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "STOPPING=1\n"
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering "STATUS=Shutting down...");
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
eecd1362f7f4de432483b5d77c56726c3621a83aLennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering}
f8e2fb7b14e53f5a4bcfd66d26910af1dee185c6Lennart Poettering