Merge pull request #22614 from zonque/timesync/runtime
timesyncd: add runtime servers
This commit is contained in:
@@ -50,6 +50,8 @@ if conf.get('ENABLE_TIMESYNCD') == 1
|
||||
install_dir : dbussystemservicedir)
|
||||
install_data('80-systemd-timesync.list',
|
||||
install_dir : ntpservicelistdir)
|
||||
install_data('org.freedesktop.timesync1.policy',
|
||||
install_dir : polkitpolicydir)
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
send_interface="org.freedesktop.DBus.Properties"
|
||||
send_member="GetAll"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.timesync1"
|
||||
send_interface="org.freedesktop.timesync1.Manager"
|
||||
send_member="SetRuntimeNTPServers"/>
|
||||
|
||||
<allow receive_sender="org.freedesktop.timesync1"/>
|
||||
</policy>
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
|
||||
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<policyconfig>
|
||||
|
||||
<vendor>The systemd Project</vendor>
|
||||
<vendor_url>https://systemd.io</vendor_url>
|
||||
|
||||
<action id="org.freedesktop.timesync1.set-runtime-servers">
|
||||
<description gettext-domain="systemd">Set runtime NTP servers</description>
|
||||
<message gettext-domain="systemd">Authentication is required to set runtime NTP servers.</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin_keep</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-timesync</annotate>
|
||||
</action>
|
||||
|
||||
</policyconfig>
|
||||
@@ -1,18 +1,24 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/capability.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-get-properties.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-log-control-api.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-protocol.h"
|
||||
#include "bus-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "timesyncd-bus.h"
|
||||
#include "user-util.h"
|
||||
|
||||
static int property_get_servers(
|
||||
sd_bus *bus,
|
||||
@@ -43,6 +49,54 @@ static int property_get_servers(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int method_set_runtime_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_strv_free_ char **msg_names = NULL;
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(message);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &msg_names);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(name, msg_names) {
|
||||
r = dns_name_is_valid_or_address(*name);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", *name);
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NTP server name or address, refusing: %s", *name);
|
||||
}
|
||||
|
||||
r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
|
||||
"org.freedesktop.timesync1.set-runtime-servers",
|
||||
NULL, true, UID_INVALID,
|
||||
&m->polkit_registry, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
/* Polkit will call us back */
|
||||
return 1;
|
||||
|
||||
manager_flush_runtime_servers(m);
|
||||
|
||||
STRV_FOREACH(name, msg_names) {
|
||||
r = server_name_new(m, NULL, SERVER_RUNTIME, *name);
|
||||
if (r < 0) {
|
||||
manager_flush_runtime_servers(m);
|
||||
|
||||
return log_error_errno(r, "Failed to add runtime server '%s': %m", *name);
|
||||
}
|
||||
}
|
||||
|
||||
m->exhausted_servers = true;
|
||||
manager_set_server_name(m, NULL);
|
||||
(void) manager_connect(m);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int property_get_current_server_name(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -162,6 +216,7 @@ static const sd_bus_vtable manager_vtable[] = {
|
||||
|
||||
SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers, offsetof(Manager, link_servers), 0),
|
||||
SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers, offsetof(Manager, system_servers), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RuntimeNTPServers", "as", property_get_servers, offsetof(Manager, runtime_servers), 0),
|
||||
SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers, offsetof(Manager, fallback_servers), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name, offsetof(Manager, current_server_name), 0),
|
||||
SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address, offsetof(Manager, current_server_address), 0),
|
||||
@@ -172,6 +227,13 @@ static const sd_bus_vtable manager_vtable[] = {
|
||||
SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Frequency", "x", NULL, offsetof(Manager, drift_freq), 0),
|
||||
|
||||
SD_BUS_METHOD_WITH_NAMES("SetRuntimeNTPServers",
|
||||
"as",
|
||||
SD_BUS_PARAM(runtime_servers),
|
||||
NULL,,
|
||||
method_set_runtime_servers,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "dns-domain.h"
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
@@ -825,22 +826,25 @@ int manager_connect(Manager *m) {
|
||||
bool restart = true;
|
||||
|
||||
/* Our current server name list is exhausted,
|
||||
* let's find the next one to iterate. First
|
||||
* we try the system list, then the link list.
|
||||
* After having processed the link list we
|
||||
* jump back to the system list. However, if
|
||||
* both lists are empty, we change to the
|
||||
* fallback list. */
|
||||
* let's find the next one to iterate. First we try the runtime list, then the system list,
|
||||
* then the link list. After having processed the link list we jump back to the system list
|
||||
* if no runtime server list.
|
||||
* However, if all lists are empty, we change to the fallback list. */
|
||||
if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) {
|
||||
f = m->system_servers;
|
||||
f = m->runtime_servers;
|
||||
if (!f)
|
||||
f = m->system_servers;
|
||||
if (!f)
|
||||
f = m->link_servers;
|
||||
} else {
|
||||
f = m->link_servers;
|
||||
if (!f)
|
||||
f = m->system_servers;
|
||||
else
|
||||
if (f)
|
||||
restart = false;
|
||||
else {
|
||||
f = m->runtime_servers;
|
||||
if (!f)
|
||||
f = m->system_servers;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f)
|
||||
@@ -852,7 +856,7 @@ int manager_connect(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (restart && !m->exhausted_servers && m->poll_interval_usec) {
|
||||
if (restart && !m->exhausted_servers && m->poll_interval_usec > 0) {
|
||||
log_debug("Waiting after exhausting servers.");
|
||||
r = sd_event_add_time_relative(m->event, &m->event_retry, CLOCK_BOOTTIME, m->poll_interval_usec, 0, manager_retry_connect, m);
|
||||
if (r < 0)
|
||||
@@ -925,6 +929,16 @@ void manager_flush_server_names(Manager *m, ServerType t) {
|
||||
if (t == SERVER_FALLBACK)
|
||||
while (m->fallback_servers)
|
||||
server_name_free(m->fallback_servers);
|
||||
|
||||
if (t == SERVER_RUNTIME)
|
||||
manager_flush_runtime_servers(m);
|
||||
}
|
||||
|
||||
void manager_flush_runtime_servers(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
while (m->runtime_servers)
|
||||
server_name_free(m->runtime_servers);
|
||||
}
|
||||
|
||||
Manager* manager_free(Manager *m) {
|
||||
@@ -934,6 +948,7 @@ Manager* manager_free(Manager *m) {
|
||||
manager_disconnect(m);
|
||||
manager_flush_server_names(m, SERVER_SYSTEM);
|
||||
manager_flush_server_names(m, SERVER_LINK);
|
||||
manager_flush_server_names(m, SERVER_RUNTIME);
|
||||
manager_flush_server_names(m, SERVER_FALLBACK);
|
||||
|
||||
sd_event_source_unref(m->event_retry);
|
||||
@@ -948,6 +963,8 @@ Manager* manager_free(Manager *m) {
|
||||
|
||||
sd_bus_flush_close_unref(m->bus);
|
||||
|
||||
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
@@ -1013,7 +1030,9 @@ clear:
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool manager_is_connected(Manager *m) {
|
||||
bool manager_is_connected(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Return true when the manager is sending a request, resolving a server name, or
|
||||
* in a poll interval. */
|
||||
return m->server_socket >= 0 || m->resolve_query || m->event_timer;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "sd-network.h"
|
||||
#include "sd-resolve.h"
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "list.h"
|
||||
#include "ratelimit.h"
|
||||
#include "time-util.h"
|
||||
@@ -41,6 +42,7 @@ struct Manager {
|
||||
|
||||
LIST_HEAD(ServerName, system_servers);
|
||||
LIST_HEAD(ServerName, link_servers);
|
||||
LIST_HEAD(ServerName, runtime_servers);
|
||||
LIST_HEAD(ServerName, fallback_servers);
|
||||
|
||||
bool have_fallbacks:1;
|
||||
@@ -63,6 +65,9 @@ struct Manager {
|
||||
sd_event_source *event_timeout;
|
||||
bool talking;
|
||||
|
||||
/* PolicyKit */
|
||||
Hashmap *polkit_registry;
|
||||
|
||||
/* last sent packet */
|
||||
struct timespec trans_time_mon;
|
||||
struct timespec trans_time;
|
||||
@@ -121,8 +126,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
void manager_set_server_name(Manager *m, ServerName *n);
|
||||
void manager_set_server_address(Manager *m, ServerAddress *a);
|
||||
void manager_flush_server_names(Manager *m, ServerType t);
|
||||
void manager_flush_runtime_servers(Manager *m);
|
||||
|
||||
int manager_connect(Manager *m);
|
||||
void manager_disconnect(Manager *m);
|
||||
bool manager_is_connected(Manager *m);
|
||||
|
||||
int manager_setup_save_time_event(Manager *m);
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "string-table.h"
|
||||
#include "timesyncd-server.h"
|
||||
|
||||
static const char * const server_type_table[_SERVER_TYPE_MAX] = {
|
||||
[SERVER_SYSTEM] = "system",
|
||||
[SERVER_FALLBACK] = "fallback",
|
||||
[SERVER_LINK] = "link",
|
||||
[SERVER_RUNTIME] = "runtime",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(server_type, ServerType);
|
||||
|
||||
int server_address_new(
|
||||
ServerName *n,
|
||||
ServerAddress **ret,
|
||||
@@ -56,7 +66,7 @@ int server_name_new(
|
||||
ServerType type,
|
||||
const char *string) {
|
||||
|
||||
ServerName *n, *tail;
|
||||
ServerName *n;
|
||||
|
||||
assert(m);
|
||||
assert(string);
|
||||
@@ -76,24 +86,29 @@ int server_name_new(
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (type == SERVER_SYSTEM) {
|
||||
LIST_FIND_TAIL(names, m->system_servers, tail);
|
||||
LIST_INSERT_AFTER(names, m->system_servers, tail, n);
|
||||
} else if (type == SERVER_LINK) {
|
||||
LIST_FIND_TAIL(names, m->link_servers, tail);
|
||||
LIST_INSERT_AFTER(names, m->link_servers, tail, n);
|
||||
} else if (type == SERVER_FALLBACK) {
|
||||
LIST_FIND_TAIL(names, m->fallback_servers, tail);
|
||||
LIST_INSERT_AFTER(names, m->fallback_servers, tail, n);
|
||||
} else
|
||||
switch (type) {
|
||||
case SERVER_SYSTEM:
|
||||
LIST_APPEND(names, m->system_servers, n);
|
||||
break;
|
||||
case SERVER_LINK:
|
||||
LIST_APPEND(names, m->link_servers, n);
|
||||
break;
|
||||
case SERVER_FALLBACK:
|
||||
LIST_APPEND(names, m->fallback_servers, n);
|
||||
break;
|
||||
case SERVER_RUNTIME:
|
||||
LIST_APPEND(names, m->runtime_servers, n);
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (type != SERVER_FALLBACK &&
|
||||
m->current_server_name &&
|
||||
m->current_server_name->type == SERVER_FALLBACK)
|
||||
manager_set_server_name(m, NULL);
|
||||
|
||||
log_debug("Added new server %s.", string);
|
||||
log_debug("Added new %s server %s.", server_type_to_string(type), string);
|
||||
|
||||
if (ret)
|
||||
*ret = n;
|
||||
@@ -114,6 +129,8 @@ ServerName *server_name_free(ServerName *n) {
|
||||
LIST_REMOVE(names, n->manager->link_servers, n);
|
||||
else if (n->type == SERVER_FALLBACK)
|
||||
LIST_REMOVE(names, n->manager->fallback_servers, n);
|
||||
else if (n->type == SERVER_RUNTIME)
|
||||
LIST_REMOVE(names, n->manager->runtime_servers, n);
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ typedef enum ServerType {
|
||||
SERVER_SYSTEM,
|
||||
SERVER_FALLBACK,
|
||||
SERVER_LINK,
|
||||
SERVER_RUNTIME,
|
||||
_SERVER_TYPE_MAX,
|
||||
_SERVER_TYPE_INVALID = -EINVAL,
|
||||
} ServerType;
|
||||
|
||||
#include "timesyncd-manager.h"
|
||||
|
||||
Reference in New Issue
Block a user