diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml index c8d74ddef2..9a37d89a40 100644 --- a/man/systemd-timedated.service.xml +++ b/man/systemd-timedated.service.xml @@ -61,13 +61,34 @@ systemd-timedated provides. + + Environment + + + + $SYSTEMD_TIMEDATED_NTP_SERVICES + + Colon-separated list of unit names of NTP client services. + If not set, then + systemd-timesyncd.service8 + is used. See the entries of NTP related commands of + timedatectl1 + for details about this. + + Example: + SYSTEMD_TIMEDATED_NTP_SERVICES=ntpd.service:chronyd.service:systemd-timesyncd.service + + + + See Also systemd1, timedatectl1, localtime5, - hwclock8 + hwclock8, + systemd-timesyncd8 diff --git a/man/timedatectl.xml b/man/timedatectl.xml index e8d9cb84b9..02b86b6641 100644 --- a/man/timedatectl.xml +++ b/man/timedatectl.xml @@ -156,28 +156,11 @@ set-ntp [BOOL] - Takes a boolean argument. Controls whether - network time synchronization is active and enabled (if - available). This enables and starts, or disables and stops the - systemd-timesyncd.service unit. It does - not affect the state of any other, unrelated network time - synchronization services that might be installed on the - system. This command is hence mostly equivalent to: - systemctl enable --now - systemd-timesyncd.service and systemctl - disable --now systemd-timesyncd.service, but is - protected by a different access policy. - - Note that even if time synchronization is turned off - with this command, another unrelated system service might - still synchronize the clock with the network. Also note that, - strictly speaking, - systemd-timesyncd.service does more than - just network time synchronization, as it ensures a monotonic - clock on systems without RTC even if no network is - available. See - systemd-timesyncd.service8 - for details about this. + Takes a boolean argument. Controls whether network time synchronization is active + and enabled (if available). If the argument is true, this enables and starts the first existed + service listed in the environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES + of systemd-timedated.service. If the argument is false, then this disables and + stops the all services listed in $SYSTEMD_TIMEDATED_NTP_SERVICES. @@ -197,13 +180,13 @@ Examples Show current settings: $ timedatectl - Local time: Thu 2017-09-21 16:08:56 CEST - Universal time: Thu 2017-09-21 14:08:56 UTC - RTC time: Thu 2017-09-21 14:08:56 - Time zone: Europe/Warsaw (CEST, +0200) - System clock synchronized: yes -systemd-timesyncd.service active: yes - RTC in local TZ: no + Local time: Thu 2017-09-21 16:08:56 CEST + Universal time: Thu 2017-09-21 14:08:56 UTC + RTC time: Thu 2017-09-21 14:08:56 + Time zone: Europe/Warsaw (CEST, +0200) +System clock synchronized: yes + NTP service: active + RTC in local TZ: no Enable network time synchronization: diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 4dce12e1c6..9d9765e568 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -59,6 +59,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index de46c36242..239c96bc1c 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -55,6 +55,7 @@ #define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy" #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" +#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport" #define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess" diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index c096fb5f0d..9a803d1221 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -36,19 +36,19 @@ typedef struct StatusInfo { usec_t rtc_time; bool rtc_local; - bool ntp_enabled; bool ntp_capable; + bool ntp_active; bool ntp_synced; } StatusInfo; static void print_status_info(const StatusInfo *i) { + const char *old_tz = NULL, *tz; + bool have_time = false; char a[LINE_MAX]; struct tm tm; time_t sec; - bool have_time = false; - const char *old_tz = NULL, *tz; - int r; size_t n; + int r; assert(i); @@ -74,13 +74,13 @@ static void print_status_info(const StatusInfo *i) { if (have_time) { n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)); - printf(" Local time: %s\n", n > 0 ? a : "n/a"); + printf(" Local time: %s\n", n > 0 ? a : "n/a"); n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)); - printf(" Universal time: %s\n", n > 0 ? a : "n/a"); + printf(" Universal time: %s\n", n > 0 ? a : "n/a"); } else { - printf(" Local time: %s\n", "n/a"); - printf(" Universal time: %s\n", "n/a"); + printf(" Local time: %s\n", "n/a"); + printf(" Universal time: %s\n", "n/a"); } if (i->rtc_time > 0) { @@ -88,9 +88,9 @@ static void print_status_info(const StatusInfo *i) { rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC); n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)); - printf(" RTC time: %s\n", n > 0 ? a : "n/a"); + printf(" RTC time: %s\n", n > 0 ? a : "n/a"); } else - printf(" RTC time: %s\n", "n/a"); + printf(" RTC time: %s\n", "n/a"); if (have_time) n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm)); @@ -105,13 +105,13 @@ static void print_status_info(const StatusInfo *i) { else tzset(); - printf(" Time zone: %s (%s)\n" - " System clock synchronized: %s\n" - "systemd-timesyncd.service active: %s\n" - " RTC in local TZ: %s\n", + printf(" Time zone: %s (%s)\n" + "System clock synchronized: %s\n" + " NTP service: %s\n" + " RTC in local TZ: %s\n", strna(i->timezone), have_time && n > 0 ? a : "n/a", yes_no(i->ntp_synced), - i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a", + i->ntp_capable ? (i->ntp_active ? "active" : "inactive") : "n/a", yes_no(i->rtc_local)); if (i->rtc_local) @@ -127,13 +127,13 @@ static void print_status_info(const StatusInfo *i) { static int show_status(int argc, char **argv, void *userdata) { StatusInfo info = {}; static const struct bus_properties_map map[] = { - { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, - { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, - { "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) }, + { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, + { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, + { "NTP", "b", NULL, offsetof(StatusInfo, ntp_active) }, { "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) }, - { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) }, - { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) }, - { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) }, + { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) }, + { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) }, + { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) }, {} }; diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index e50ce47b62..f479b0ab7f 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -21,33 +21,170 @@ #include "def.h" #include "fileio-label.h" #include "fs-util.h" +#include "hashmap.h" +#include "list.h" #include "path-util.h" #include "selinux-util.h" +#include "string-util.h" #include "strv.h" +#include "unit-def.h" +#include "unit-name.h" #include "user-util.h" #include "util.h" #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" -static BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = { - SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", EOPNOTSUPP), - SD_BUS_ERROR_MAP_END -}; +typedef struct UnitStatusInfo { + char *name; + char *load_state; + char *unit_file_state; + char *active_state; + + LIST_FIELDS(struct UnitStatusInfo, units); +} UnitStatusInfo; typedef struct Context { char *zone; bool local_rtc; - bool can_ntp; - bool use_ntp; Hashmap *polkit_registry; + + LIST_HEAD(UnitStatusInfo, units); } Context; +static void unit_status_info_clear(UnitStatusInfo *p) { + assert(p); + + p->load_state = mfree(p->load_state); + p->unit_file_state = mfree(p->unit_file_state); + p->active_state = mfree(p->active_state); +} + +static void unit_status_info_free(UnitStatusInfo *p) { + assert(p); + + unit_status_info_clear(p); + free(p->name); + free(p); +} + static void context_free(Context *c) { + UnitStatusInfo *p; + assert(c); free(c->zone); bus_verify_polkit_async_registry_free(c->polkit_registry); + + while ((p = c->units)) { + LIST_REMOVE(units, c->units, p); + unit_status_info_free(p); + } +} + +static int context_add_ntp_service(Context *c, const char *s) { + _cleanup_free_ char *name = NULL; + UnitStatusInfo *u; + + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) + return -EINVAL; + + /* Do not add this if it is already listed */ + LIST_FOREACH(units, u, c->units) + if (streq(u->name, s)) + return 0; + + u = new0(UnitStatusInfo, 1); + if (!u) + return -ENOMEM; + + u->name = strdup(s); + if (!u->name) { + free(u); + return -ENOMEM; + } + + LIST_APPEND(units, c->units, u); + + return 0; +} + +static int context_parse_ntp_services(Context *c) { + const char *env, *p; + int r; + + assert(c); + + env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES"); + if (!env) { + r = context_add_ntp_service(c, "systemd-timesyncd.service"); + if (r < 0) + log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m"); + + return 0; + } + + for (p = env;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, ":", 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_error("Invalid syntax, ignoring: %s", env); + break; + } + + r = context_add_ntp_service(c, word); + if (r < 0) + log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word); + } + + return 0; +} + +static int context_ntp_service_is_active(Context *c) { + UnitStatusInfo *info; + int count = 0; + + assert(c); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + LIST_FOREACH(units, info, c->units) + count += streq_ptr(info->active_state, "active"); + + return count; +} + +static int context_ntp_service_is_enabled(Context *c) { + UnitStatusInfo *info; + int count = 0; + + assert(c); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + LIST_FOREACH(units, info, c->units) + count += STRPTR_IN_SET(info->unit_file_state, "enabled", "enabled-runtime"); + + return count; +} + +static int context_ntp_service_exists(Context *c) { + UnitStatusInfo *info; + int count = 0; + + assert(c); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + LIST_FOREACH(units, info, c->units) + count += streq_ptr(info->load_state, "loaded"); + + return count; } static int context_read_data(Context *c) { @@ -163,81 +300,95 @@ static int context_write_data_local_rtc(Context *c) { return write_string_file_atomic_label("/etc/adjtime", w); } -static int context_read_ntp(Context *c, sd_bus *bus) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - const char *s; +static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) { + static const struct bus_properties_map map[] = { + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) }, + { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) }, + {} + }; + static sd_bus_message *_m = NULL; + UnitStatusInfo *u; int r; assert(c); assert(bus); - r = sd_bus_call_method( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "GetUnitFileState", - &error, - &reply, - "s", - "systemd-timesyncd.service"); + /* Suppress multiple call of context_update_ntp_status() within single DBus transaction. */ + if (m && m == _m) + return 0; - if (r < 0) { - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND) || - sd_bus_error_has_name(&error, "org.freedesktop.systemd1.LoadFailed") || - sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit")) - return 0; + _m = m; - return r; + LIST_FOREACH(units, u, c->units) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *path = NULL; + + unit_status_info_clear(u); + + path = unit_dbus_path_from_name(u->name); + if (!path) + return -ENOMEM; + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + path, + map, + BUS_MAP_STRDUP, + &error, + NULL, + u); + if (r < 0) + return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); } - r = sd_bus_message_read(reply, "s", &s); - if (r < 0) - return r; - - c->can_ntp = true; - c->use_ntp = STR_IN_SET(s, "enabled", "enabled-runtime"); - return 0; } -static int context_start_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { +static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) { int r; + assert(u); assert(bus); assert(error); + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + if (streq(u->active_state, "active") == start) + return 0; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - enabled ? "StartUnit" : "StopUnit", + start ? "StartUnit" : "StopUnit", error, NULL, "ss", - "systemd-timesyncd.service", + u->name, "replace"); - if (r < 0) { - if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND) || - sd_bus_error_has_name(error, "org.freedesktop.systemd1.LoadFailed") || - sd_bus_error_has_name(error, "org.freedesktop.systemd1.NoSuchUnit")) - return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported."); - + if (r < 0) return r; - } return 0; } -static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { +static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool enable) { int r; + assert(u); assert(bus); assert(error); - if (enabled) + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + if (streq(u->unit_file_state, "enabled") == enable) + return 0; + + if (enable) r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -247,7 +398,7 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { error, NULL, "asbb", 1, - "systemd-timesyncd.service", + u->name, false, true); else r = sd_bus_call_method( @@ -259,15 +410,10 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { error, NULL, "asb", 1, - "systemd-timesyncd.service", + u->name, false); - - if (r < 0) { - if (sd_bus_error_has_name(error, SD_BUS_ERROR_FILE_NOT_FOUND)) - return sd_bus_error_set_const(error, "org.freedesktop.timedate1.NoNTPSupport", "NTP not supported."); - + if (r < 0) return r; - } r = sd_bus_call_method( bus, @@ -278,9 +424,8 @@ static int context_enable_ntp(sd_bus *bus, sd_bus_error *error, bool enabled) { error, NULL, NULL); - if (r < 0) - return r; - + if (r < 0) + return r; return 0; } @@ -337,6 +482,56 @@ static int property_get_ntp_sync( return sd_bus_message_append(reply, "b", ntp_synced()); } +static int property_get_can_ntp( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + assert(c); + assert(bus); + assert(property); + assert(reply); + assert(error); + + r = context_update_ntp_status(c, bus, reply); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "b", context_ntp_service_exists(c) > 0); +} + +static int property_get_ntp( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + assert(c); + assert(bus); + assert(property); + assert(reply); + assert(error); + + r = context_update_ntp_status(c, bus, reply); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "b", context_ntp_service_is_active(c) > 0); +} + static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; const char *z; @@ -500,19 +695,23 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error } static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int relative, interactive; + sd_bus *bus = sd_bus_message_get_bus(m); + int relative, interactive, r; Context *c = userdata; int64_t utc; struct timespec ts; usec_t start; struct tm* tm; - int r; assert(m); assert(c); - if (c->use_ntp) - return sd_bus_error_setf(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled"); + r = context_update_ntp_status(c, bus, m); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to update context: %m"); + + if (context_ntp_service_is_active(c) > 0) + return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled"); /* this only gets used if dbus does not provide a timestamp */ start = now(CLOCK_MONOTONIC); @@ -522,7 +721,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro return r; if (!relative && utc <= 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time"); + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time"); if (relative && utc == 0) return sd_bus_reply_method_return(m, NULL); @@ -535,7 +734,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro if ((utc > 0 && x < n) || (utc < 0 && x > n)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow"); + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow"); timespec_store(&ts, x); } else @@ -586,19 +785,25 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro } static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) { - int enabled, interactive; + sd_bus *bus = sd_bus_message_get_bus(m); Context *c = userdata; - int r; + UnitStatusInfo *u; + int enable, interactive, q, r; assert(m); + assert(bus); assert(c); - r = sd_bus_message_read(m, "bb", &enabled, &interactive); + r = sd_bus_message_read(m, "bb", &enable, &interactive); if (r < 0) return r; - if ((bool)enabled == c->use_ntp) - return sd_bus_reply_method_return(m, NULL); + r = context_update_ntp_status(c, bus, m); + if (r < 0) + return r; + + if (context_ntp_service_exists(c) <= 0) + return sd_bus_error_set(error, BUS_ERROR_NO_NTP_SUPPORT, "NTP not supported"); r = bus_verify_polkit_async( m, @@ -614,18 +819,49 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error if (r == 0) return 1; - r = context_enable_ntp(sd_bus_message_get_bus(m), error, enabled); + if (!enable) + LIST_FOREACH(units, u, c->units) { + if (!streq(u->load_state, "loaded")) + continue; + + q = unit_enable_or_disable(u, bus, error, enable); + if (q < 0) + r = q; + + q = unit_start_or_stop(u, bus, error, enable); + if (q < 0) + r = q; + } + + else if (context_ntp_service_is_enabled(c) <= 0) + LIST_FOREACH(units, u, c->units) { + if (!streq(u->load_state, "loaded")) + continue; + + r = unit_enable_or_disable(u, bus, error, enable); + if (r < 0) + continue; + + r = unit_start_or_stop(u, bus, error, enable); + break; + } + + else if (context_ntp_service_is_active(c) <= 0) + LIST_FOREACH(units, u, c->units) { + if (!streq(u->load_state, "loaded") || + !streq(u->unit_file_state, "enabled")) + continue; + + r = unit_start_or_stop(u, bus, error, enable); + break; + } + if (r < 0) return r; - r = context_start_ntp(sd_bus_message_get_bus(m), error, enabled); - if (r < 0) - return r; + log_info("Set NTP to %sd", enable_disable(enable)); - c->use_ntp = enabled; - log_info("Set NTP to %sd", enable_disable(enabled)); - - (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); + (void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); return sd_bus_reply_method_return(m, NULL); } @@ -634,8 +870,8 @@ static const sd_bus_vtable timedate_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("CanNTP", "b", bus_property_get_bool, offsetof(Context, can_ntp), 0), - SD_BUS_PROPERTY("NTP", "b", bus_property_get_bool, offsetof(Context, use_ntp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CanNTP", "b", property_get_can_ntp, 0, 0), + SD_BUS_PROPERTY("NTP", "b", property_get_ntp, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0), SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0), SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0), @@ -713,11 +949,9 @@ int main(int argc, char *argv[]) { goto finish; } - r = context_read_ntp(&context, bus); - if (r < 0) { - log_error_errno(r, "Failed to determine whether NTP is enabled: %m"); + r = context_parse_ntp_services(&context); + if (r < 0) goto finish; - } r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL); if (r < 0) {