From f90eb086270f0aea8efcbff5a5e4c338d178cfd4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 1 Mar 2024 11:21:56 +0900 Subject: [PATCH] network/varlink: introduce io.systemd.Network.SetPersistentStorage method And make the networkd use state directory. Currently, the state directory and the method are not used, but will be used later. --- src/network/networkd-manager-varlink.c | 53 ++++++++++++++++++++- src/network/networkd-manager.c | 24 ++++++++++ src/network/networkd-manager.h | 1 + src/network/org.freedesktop.network1.policy | 11 +++++ src/shared/varlink-io.systemd.Network.c | 5 ++ units/systemd-networkd.service.in | 2 +- 6 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c index 0c54e86aea..a85751491e 100644 --- a/src/network/networkd-manager-varlink.c +++ b/src/network/networkd-manager-varlink.c @@ -2,8 +2,11 @@ #include +#include "bus-polkit.h" +#include "fs-util.h" #include "lldp-rx-internal.h" #include "networkd-manager-varlink.h" +#include "stat-util.h" #include "varlink.h" #include "varlink-io.systemd.Network.h" @@ -164,6 +167,53 @@ static int vl_method_get_lldp_neighbors(Varlink *vlink, JsonVariant *parameters, JSON_BUILD_PAIR_CONDITION(!json_variant_is_blank_array(array), "Neighbors", JSON_BUILD_VARIANT(array)))); } +static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + static const JsonDispatch dispatch_table[] = { + { "Ready", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, 0, 0 }, + {} + }; + + Manager *manager = ASSERT_PTR(userdata); + bool ready; + int r; + + assert(vlink); + + r = varlink_dispatch(vlink, parameters, dispatch_table, &ready); + if (r != 0) + return r; + + if (ready) { + r = path_is_read_only_fs("/var/lib/systemd/network/"); + if (r < 0) + return log_warning_errno(r, "Failed to check if /var/lib/systemd/network/ is writable: %m"); + if (r > 0) + return log_warning_errno(SYNTHETIC_ERRNO(EROFS), "The directory /var/lib/systemd/network/ is read-only."); + } + + r = varlink_verify_polkit_async( + vlink, + manager->bus, + "org.freedesktop.network1.set-persistent-storage", + /* details= */ NULL, + &manager->polkit_registry); + if (r <= 0) + return r; + + manager->persistent_storage_is_ready = ready; + + if (ready) { + r = touch("/run/systemd/netif/persistent-storage-ready"); + if (r < 0) + log_debug_errno(r, "Failed to create /run/systemd/netif/persistent-storage-ready, ignoring: %m"); + } else { + if (unlink("/run/systemd/netif/persistent-storage-ready") < 0 && errno != ENOENT) + log_debug_errno(errno, "Failed to remove /run/systemd/netif/persistent-storage-ready, ignoring: %m"); + } + + return varlink_reply(vlink, NULL); +} + int manager_connect_varlink(Manager *m) { _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL; int r; @@ -187,7 +237,8 @@ int manager_connect_varlink(Manager *m) { s, "io.systemd.Network.GetStates", vl_method_get_states, "io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id, - "io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors); + "io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors, + "io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index c0d368ab11..b955eb9447 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -557,6 +557,29 @@ int manager_setup(Manager *m) { return 0; } +static bool persistent_storage_is_ready(void) { + int r; + + if (access("/run/systemd/netif/persistent-storage-ready", F_OK) < 0) { + if (errno != ENOENT) + return log_debug_errno(errno, "Failed to check if /run/systemd/netif/persistent-storage-ready exists, assuming not, ignoring: %m"); + return false; + } + + r = path_is_read_only_fs("/var/lib/systemd/network/"); + if (r == 0) + return true; + if (r < 0) + log_debug_errno(r, "Failed to check if /var/lib/systemd/network/ is writable: %m"); + else + log_debug("The directory /var/lib/systemd/network/ is read-only."); + + if (unlink("/run/systemd/netif/persistent-storage-ready") < 0 && errno != ENOENT) + log_debug_errno(errno, "Failed to remove /run/systemd/netif/persistent-storage-ready, ignoring: %m"); + + return false; +} + int manager_new(Manager **ret, bool test_mode) { _cleanup_(manager_freep) Manager *m = NULL; @@ -568,6 +591,7 @@ int manager_new(Manager **ret, bool test_mode) { .keep_configuration = _KEEP_CONFIGURATION_INVALID, .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO, .test_mode = test_mode, + .persistent_storage_is_ready = persistent_storage_is_ready(), .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL, .online_state = _LINK_ONLINE_STATE_INVALID, .manage_foreign_routes = true, diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 8088e20b38..320b859bfd 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -41,6 +41,7 @@ struct Manager { bool manage_foreign_routes; bool manage_foreign_rules; bool manage_foreign_nexthops; + bool persistent_storage_is_ready; Set *dirty_links; Set *new_wlan_ifindices; diff --git a/src/network/org.freedesktop.network1.policy b/src/network/org.freedesktop.network1.policy index 1e2d8d7cb4..e2525508a4 100644 --- a/src/network/org.freedesktop.network1.policy +++ b/src/network/org.freedesktop.network1.policy @@ -183,4 +183,15 @@ unix-user:systemd-network + + Specify whether persistent storage for systemd-networkd is available. + Authentication is required to specify whether persistent storage for systemd-networkd is available. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + diff --git a/src/shared/varlink-io.systemd.Network.c b/src/shared/varlink-io.systemd.Network.c index 986f2cfc69..c3be38b99a 100644 --- a/src/shared/varlink-io.systemd.Network.c +++ b/src/shared/varlink-io.systemd.Network.c @@ -40,11 +40,16 @@ static VARLINK_DEFINE_METHOD( VARLINK_DEFINE_INPUT(InterfaceName, VARLINK_STRING, VARLINK_NULLABLE), VARLINK_DEFINE_OUTPUT_BY_TYPE(Neighbors, LLDPNeighborsByInterface, VARLINK_ARRAY)); +static VARLINK_DEFINE_METHOD( + SetPersistentStorage, + VARLINK_DEFINE_INPUT(Ready, VARLINK_BOOL, 0)); + VARLINK_DEFINE_INTERFACE( io_systemd_Network, "io.systemd.Network", &vl_method_GetStates, &vl_method_GetNamespaceId, &vl_method_GetLLDPNeighbors, + &vl_method_SetPersistentStorage, &vl_type_LLDPNeighbor, &vl_type_LLDPNeighborsByInterface); diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in index 32b6e9fa2f..3dcaa55aac 100644 --- a/units/systemd-networkd.service.in +++ b/units/systemd-networkd.service.in @@ -35,7 +35,7 @@ ProtectControlGroups=yes ProtectHome=yes ProtectKernelLogs=yes ProtectKernelModules=yes -ProtectSystem=strict +ProtectSystem=full Restart=on-failure RestartKillSignal=SIGUSR2 RestartSec=0