]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: add basic Varlink interface
authorLennart Poettering <lennart@poettering.net>
Mon, 20 Nov 2023 11:07:13 +0000 (12:07 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Dec 2023 02:54:43 +0000 (11:54 +0900)
Let's get networkd onto Varlink. This only adds the most basic of
operations.

I'd love to see networkd do Varlink for all its basic operations so that
networkctl can use that, and work correctly before D-Bus is up. Right
now, many of networkctls calls simply don't work before D-Bus, and I'd
like to see that improved.

src/network/meson.build
src/network/networkd-manager-varlink.c [new file with mode: 0644]
src/network/networkd-manager-varlink.h [new file with mode: 0644]
src/network/networkd-manager.c
src/network/networkd-manager.h
src/shared/meson.build
src/shared/varlink-io.systemd.Network.c [new file with mode: 0644]
src/shared/varlink-io.systemd.Network.h [new file with mode: 0644]
src/test/test-varlink-idl.c

index 3d692abf443da67c8e68f345060c62a00f6406c1..5f06948752beb292f70a7f7bb2eddb695dc98b6d 100644 (file)
@@ -56,8 +56,9 @@ sources = files(
         'networkd-link.c',
         'networkd-lldp-rx.c',
         'networkd-lldp-tx.c',
-        'networkd-manager-bus.c',
         'networkd-manager.c',
+        'networkd-manager-bus.c',
+        'networkd-manager-varlink.c',
         'networkd-ndisc.c',
         'networkd-neighbor.c',
         'networkd-netlabel.c',
diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c
new file mode 100644 (file)
index 0000000..d9750d9
--- /dev/null
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <unistd.h>
+
+#include "networkd-manager-varlink.h"
+#include "varlink.h"
+#include "varlink-io.systemd.Network.h"
+
+static int vl_method_get_states(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Manager *m = ASSERT_PTR(userdata);
+
+        assert(link);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        return varlink_replyb(link,
+                              JSON_BUILD_OBJECT(
+                                              JSON_BUILD_PAIR_STRING("AddressState", link_address_state_to_string(m->address_state)),
+                                              JSON_BUILD_PAIR_STRING("IPv4AddressState", link_address_state_to_string(m->ipv4_address_state)),
+                                              JSON_BUILD_PAIR_STRING("IPv6AddressState", link_address_state_to_string(m->ipv6_address_state)),
+                                              JSON_BUILD_PAIR_STRING("CarrierState", link_carrier_state_to_string(m->carrier_state)),
+                                              JSON_BUILD_PAIR_CONDITION(m->online_state >= 0, "OnlineState", JSON_BUILD_STRING(link_online_state_to_string(m->online_state))),
+                                              JSON_BUILD_PAIR_STRING("OperationalState", link_operstate_to_string(m->operational_state))));
+}
+
+static int vl_method_get_namespace_id(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        uint64_t id;
+
+        assert(link);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        struct stat st;
+        if (stat("/proc/self/ns/net", &st) < 0) {
+                log_warning_errno(errno, "Failed to stat network namespace, ignoring: %m");
+                id = 0;
+        } else
+                id = st.st_ino;
+
+        return varlink_replyb(link,
+                              JSON_BUILD_OBJECT(
+                                              JSON_BUILD_PAIR_UNSIGNED("NamespaceId", id)));
+}
+
+int manager_connect_varlink(Manager *m) {
+        _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+        int r;
+
+        assert(m);
+
+        if (m->varlink_server)
+                return 0;
+
+        r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate varlink server object: %m");
+
+        varlink_server_set_userdata(s, m);
+
+        r = varlink_server_add_interface(s, &vl_interface_io_systemd_Network);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add Network interface to varlink server: %m");
+
+        r = varlink_server_bind_method_many(
+                        s,
+                        "io.systemd.Network.GetStates", vl_method_get_states,
+                        "io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register varlink methods: %m");
+
+        r = varlink_server_listen_address(s, "/run/systemd/netif/io.systemd.Network", 0666);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind to varlink socket: %m");
+
+        r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
+
+        m->varlink_server = TAKE_PTR(s);
+        return 0;
+}
+
+void manager_varlink_done(Manager *m) {
+        assert(m);
+
+        m->varlink_server = varlink_server_unref(m->varlink_server);
+        (void) unlink("/run/systemd/netif/io.systemd.Network");
+}
diff --git a/src/network/networkd-manager-varlink.h b/src/network/networkd-manager-varlink.h
new file mode 100644 (file)
index 0000000..46078a8
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "networkd-manager.h"
+
+int manager_connect_varlink(Manager *m);
+void manager_varlink_done(Manager *m);
index 51f8b0cc749a5cd87803979c7ef875d011a66521..3319cbe0861f814297cbcfa2c5921746732cc426 100644 (file)
@@ -36,8 +36,9 @@
 #include "networkd-dhcp-server-bus.h"
 #include "networkd-dhcp6.h"
 #include "networkd-link-bus.h"
-#include "networkd-manager-bus.h"
 #include "networkd-manager.h"
+#include "networkd-manager-bus.h"
+#include "networkd-manager-varlink.h"
 #include "networkd-neighbor.h"
 #include "networkd-network-bus.h"
 #include "networkd-nexthop.h"
@@ -529,6 +530,10 @@ int manager_setup(Manager *m) {
         if (m->test_mode)
                 return 0;
 
+        r = manager_connect_varlink(m);
+        if (r < 0)
+                return r;
+
         r = manager_connect_bus(m);
         if (r < 0)
                 return r;
@@ -640,6 +645,8 @@ Manager* manager_free(Manager *m) {
 
         sd_device_monitor_unref(m->device_monitor);
 
+        manager_varlink_done(m);
+
         bus_verify_polkit_async_registry_free(m->polkit_registry);
         sd_bus_flush_close_unref(m->bus);
 
index a9827d8a4b4fffea9b61280829b5abc6e40691b6..fc6d1903fab0e26317b1f707dc87fc55ab5fa7bf 100644 (file)
@@ -17,6 +17,7 @@
 #include "ordered-set.h"
 #include "set.h"
 #include "time-util.h"
+#include "varlink.h"
 
 struct Manager {
         sd_netlink *rtnl;
@@ -25,6 +26,7 @@ struct Manager {
         sd_event *event;
         sd_resolve *resolve;
         sd_bus *bus;
+        VarlinkServer *varlink_server;
         sd_device_monitor *device_monitor;
         Hashmap *polkit_registry;
         int ethtool_fd;
index bcd02d4cfb4e953c113496a44bd7080685be5ff5..b2cee6fa2c869ac6d9f949e79fe09b5887e7fdd0 100644 (file)
@@ -176,9 +176,10 @@ shared_sources = files(
         'varlink-io.systemd.Credentials.c',
         'varlink-io.systemd.Journal.c',
         'varlink-io.systemd.ManagedOOM.c',
+        'varlink-io.systemd.Network.c',
         'varlink-io.systemd.PCRExtend.c',
-        'varlink-io.systemd.Resolve.Monitor.c',
         'varlink-io.systemd.Resolve.c',
+        'varlink-io.systemd.Resolve.Monitor.c',
         'varlink-io.systemd.UserDatabase.c',
         'varlink-io.systemd.oom.c',
         'varlink-io.systemd.service.c',
diff --git a/src/shared/varlink-io.systemd.Network.c b/src/shared/varlink-io.systemd.Network.c
new file mode 100644 (file)
index 0000000..ec25e26
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "varlink-io.systemd.Network.h"
+
+static VARLINK_DEFINE_METHOD(GetStates,
+                             VARLINK_DEFINE_OUTPUT(AddressState, VARLINK_STRING, 0),
+                             VARLINK_DEFINE_OUTPUT(IPv4AddressState, VARLINK_STRING, 0),
+                             VARLINK_DEFINE_OUTPUT(IPv6AddressState, VARLINK_STRING, 0),
+                             VARLINK_DEFINE_OUTPUT(CarrierState, VARLINK_STRING, 0),
+                             VARLINK_DEFINE_OUTPUT(OnlineState, VARLINK_STRING, 0),
+                             VARLINK_DEFINE_OUTPUT(OperationalState, VARLINK_STRING, 0));
+
+static VARLINK_DEFINE_METHOD(GetNamespaceId,
+                             VARLINK_DEFINE_OUTPUT(NamespaceId, VARLINK_INT, 0));
+
+VARLINK_DEFINE_INTERFACE(
+                io_systemd_Network,
+                "io.systemd.Network",
+                &vl_method_GetStates,
+                &vl_method_GetNamespaceId);
diff --git a/src/shared/varlink-io.systemd.Network.h b/src/shared/varlink-io.systemd.Network.h
new file mode 100644 (file)
index 0000000..12d532a
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "varlink-idl.h"
+
+extern const VarlinkInterface vl_interface_io_systemd_Network;
index 6aa1fa6b1df679f81b6160996db682a5a2570d58..1770cb3c03859775223e1a949576d53cba02f131 100644 (file)
@@ -11,6 +11,7 @@
 #include "varlink-io.systemd.Credentials.h"
 #include "varlink-io.systemd.Journal.h"
 #include "varlink-io.systemd.ManagedOOM.h"
+#include "varlink-io.systemd.Network.h"
 #include "varlink-io.systemd.PCRExtend.h"
 #include "varlink-io.systemd.Resolve.Monitor.h"
 #include "varlink-io.systemd.Resolve.h"
@@ -134,6 +135,8 @@ TEST(parse_format) {
         print_separator();
         test_parse_format_one(&vl_interface_io_systemd_ManagedOOM);
         print_separator();
+        test_parse_format_one(&vl_interface_io_systemd_Network);
+        print_separator();
         test_parse_format_one(&vl_interface_io_systemd_oom);
         print_separator();
         test_parse_format_one(&vl_interface_io_systemd);