network/varlink: introduce io.systemd.Network.SetPersistentStorage method
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 1 Mar 2024 02:21:56 +0000 (11:21 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Mar 2024 16:57:11 +0000 (01:57 +0900)
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
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/org.freedesktop.network1.policy
src/shared/varlink-io.systemd.Network.c
units/systemd-networkd.service.in

index 0c54e86aea85d530ce6152980c976455c4f3ad51..a85751491e584f21d0f4e516ed62a97ee2490bb2 100644 (file)
@@ -2,8 +2,11 @@
 
 #include <unistd.h>
 
+#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");
 
index c0d368ab1154b16cf0726ad47904a98b8ba877c6..b955eb94475175ae9cdde708e686cedf711c79b9 100644 (file)
@@ -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,
index 8088e20b380b4b36abaaad8c722047e1f6a51c5c..320b859bfd839526a53e5aeed0f165f7a02c79ab 100644 (file)
@@ -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;
index 1e2d8d7cb42865d021d64928f1f1e9c3d1c2abc5..e2525508a4537871643c1056ad0006ccdbc0f2e7 100644 (file)
                 <annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
         </action>
 
+        <action id="org.freedesktop.network1.set-persistent-storage">
+                <description gettext-domain="systemd">Specify whether persistent storage for systemd-networkd is available.</description>
+                <message gettext-domain="systemd">Authentication is required to specify whether persistent storage for systemd-networkd is available.</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>
index 986f2cfc695b2b83a6f11d506e3ed8dcb056c439..c3be38b99a03be9223d1e44d598b592e77795172 100644 (file)
@@ -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);
index 32b6e9fa2ffed33562b84cf031503b63d25d99e1..3dcaa55aac32c7509ea26dd4f1e194864314f045 100644 (file)
@@ -35,7 +35,7 @@ ProtectControlGroups=yes
 ProtectHome=yes
 ProtectKernelLogs=yes
 ProtectKernelModules=yes
-ProtectSystem=strict
+ProtectSystem=full
 Restart=on-failure
 RestartKillSignal=SIGUSR2
 RestartSec=0