diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-10-23 22:20:48 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-10-24 14:18:09 +0900 |
commit | 7f06b3e1b96004f5950f9cc97e2c98181f787e35 (patch) | |
tree | 894f2e6360cb232dac0a29f358ef5373a1f7c7d5 | |
parent | 6f3ad94590e3d6092f008b8b1443e12af84534e8 (diff) | |
download | systemd-7f06b3e1b96004f5950f9cc97e2c98181f787e35.tar.gz systemd-7f06b3e1b96004f5950f9cc97e2c98181f787e35.tar.bz2 systemd-7f06b3e1b96004f5950f9cc97e2c98181f787e35.zip |
network: add Reload() dbus method
-rw-r--r-- | src/network/fuzz-network-parser.c | 2 | ||||
-rw-r--r-- | src/network/networkd-manager-bus.c | 31 | ||||
-rw-r--r-- | src/network/networkd-manager.c | 2 | ||||
-rw-r--r-- | src/network/networkd-network.c | 76 | ||||
-rw-r--r-- | src/network/networkd-network.h | 6 | ||||
-rw-r--r-- | src/network/org.freedesktop.network1.policy | 11 |
6 files changed, 108 insertions, 20 deletions
diff --git a/src/network/fuzz-network-parser.c b/src/network/fuzz-network-parser.c index b05626751e..732b5b21f4 100644 --- a/src/network/fuzz-network-parser.c +++ b/src/network/fuzz-network-parser.c @@ -23,6 +23,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fflush(f); assert_se(manager_new(&manager) >= 0); - (void) network_load_one(manager, network_config); + (void) network_load_one(manager, &manager->networks, network_config); return 0; } diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c index 7484fcfa12..6bc2c22f07 100644 --- a/src/network/networkd-manager-bus.c +++ b/src/network/networkd-manager-bus.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include <net/if.h> +#include <sys/capability.h> #include "alloc-util.h" #include "bus-common-errors.h" @@ -11,6 +12,7 @@ #include "networkd-manager.h" #include "path-util.h" #include "strv.h" +#include "user-util.h" static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; @@ -187,6 +189,34 @@ static int bus_method_renew_link(sd_bus_message *message, void *userdata, sd_bus return call_link_method(userdata, message, bus_link_method_renew, error); } +static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + Iterator i; + Link *link; + int r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.reload", + NULL, true, UID_INVALID, + &manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + r = network_reload(manager); + if (r < 0) + return r; + + HASHMAP_FOREACH(link, manager->links, i) { + r = link_reconfigure(link); + if (r < 0) + return r; + } + + return sd_bus_reply_method_return(message, NULL); +} + const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), @@ -209,6 +239,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("RevertLinkNTP", "i", NULL, bus_method_revert_link_ntp, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RevertLinkDNS", "i", NULL, bus_method_revert_link_dns, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RenewLink", "i", NULL, bus_method_renew_link, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reload", NULL, NULL, bus_method_reload, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index c70194f1f8..36481bcde6 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1860,7 +1860,7 @@ int manager_load_config(Manager *m) { if (r < 0) return r; - r = network_load(m); + r = network_load(m, &m->networks); if (r < 0) return r; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 24d6556c76..85d6150312 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -314,7 +314,7 @@ int network_verify(Network *network) { return 0; } -int network_load_one(Manager *manager, const char *filename) { +int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) { _cleanup_free_ char *fname = NULL, *name = NULL; _cleanup_(network_unrefp) Network *network = NULL; _cleanup_fclose_ FILE *file = NULL; @@ -488,36 +488,42 @@ int network_load_one(Manager *manager, const char *filename) { log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m", network->filename); - r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops); + struct stat stats; + if (stat(filename, &stats) < 0) + return -errno; + network->timestamp = timespec_load(&stats.st_mtim); + + if (network_verify(network) < 0) + /* Ignore .network files that do not match the conditions. */ + return 0; + + r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops); if (r < 0) return r; - r = ordered_hashmap_put(manager->networks, network->name, network); + r = ordered_hashmap_put(*networks, network->name, network); if (r < 0) return r; - if (network_verify(network) < 0) - return 0; - network = NULL; return 0; } -int network_load(Manager *manager) { +int network_load(Manager *manager, OrderedHashmap **networks) { _cleanup_strv_free_ char **files = NULL; char **f; int r; assert(manager); - ordered_hashmap_clear_with_destructor(manager->networks, network_unref); + ordered_hashmap_clear_with_destructor(*networks, network_unref); r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS); if (r < 0) return log_error_errno(r, "Failed to enumerate network files: %m"); STRV_FOREACH(f, files) { - r = network_load_one(manager, *f); + r = network_load_one(manager, networks, *f); if (r < 0) log_error_errno(r, "Failed to load %s, ignoring: %m", *f); } @@ -525,6 +531,48 @@ int network_load(Manager *manager) { return 0; } +int network_reload(Manager *manager) { + OrderedHashmap *new_networks = NULL; + Network *n, *old; + Iterator i; + int r; + + assert(manager); + + r = network_load(manager, &new_networks); + if (r < 0) + goto failure; + + ORDERED_HASHMAP_FOREACH(n, new_networks, i) { + r = network_get_by_name(manager, n->name, &old); + if (r < 0) + continue; /* The .network file is new. */ + + if (n->timestamp != old->timestamp) + continue; /* The .network file is modified. */ + + if (!streq(n->filename, old->filename)) + continue; + + r = ordered_hashmap_replace(new_networks, old->name, old); + if (r < 0) + goto failure; + + network_ref(old); + network_unref(n); + } + + ordered_hashmap_free_with_destructor(manager->networks, network_unref); + manager->networks = new_networks; + + return 0; + +failure: + ordered_hashmap_free_with_destructor(new_networks, network_unref); + + return r; +} + static Network *network_free(Network *network) { IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; RoutingPolicyRule *rule; @@ -615,13 +663,9 @@ static Network *network_free(Network *network) { hashmap_free(network->prefixes_by_section); hashmap_free(network->rules_by_section); - if (network->manager) { - if (network->manager->networks && network->name) - ordered_hashmap_remove(network->manager->networks, network->name); - - if (network->manager->duids_requesting_uuid) - set_remove(network->manager->duids_requesting_uuid, &network->duid); - } + if (network->manager && + network->manager->duids_requesting_uuid) + set_remove(network->manager->duids_requesting_uuid, &network->duid); free(network->name); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index d169481cd8..1ae560e994 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -54,6 +54,7 @@ struct Network { char *filename; char *name; + usec_t timestamp; unsigned n_ref; @@ -283,8 +284,9 @@ Network *network_ref(Network *network); Network *network_unref(Network *network); DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_unref); -int network_load(Manager *manager); -int network_load_one(Manager *manager, const char *filename); +int network_load(Manager *manager, OrderedHashmap **networks); +int network_reload(Manager *manager); +int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename); int network_verify(Network *network); int network_get_by_name(Manager *manager, const char *name, Network **ret); diff --git a/src/network/org.freedesktop.network1.policy b/src/network/org.freedesktop.network1.policy index 4a33f5a8aa..79b418b3e9 100644 --- a/src/network/org.freedesktop.network1.policy +++ b/src/network/org.freedesktop.network1.policy @@ -150,4 +150,15 @@ <annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate> </action> + <action id="org.freedesktop.network1.reload"> + <description gettext-domain="systemd">Reload network settings</description> + <message gettext-domain="systemd">Authentication is required to reload network settings.</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-network</annotate> + </action> + </policyconfig> |