]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce Describe() method for manager and links
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 12 May 2021 13:11:09 +0000 (22:11 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 14 May 2021 00:18:29 +0000 (09:18 +0900)
src/network/meson.build
src/network/networkd-json.c [new file with mode: 0644]
src/network/networkd-json.h [new file with mode: 0644]
src/network/networkd-link-bus.c
src/network/networkd-link-bus.h
src/network/networkd-manager-bus.c

index a8b9232e64d8318ede91da6d1332b9a951549a01..7b6a4b7c7abf83db538ab4c2e6fcd521981b6c36 100644 (file)
@@ -79,6 +79,8 @@ sources = files('''
         networkd-ipv4ll.h
         networkd-ipv6-proxy-ndp.c
         networkd-ipv6-proxy-ndp.h
+        networkd-json.c
+        networkd-json.h
         networkd-link-bus.c
         networkd-link-bus.h
         networkd-link.c
diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c
new file mode 100644 (file)
index 0000000..7a7fc24
--- /dev/null
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "network-util.h"
+#include "networkd-json.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "networkd-network.h"
+#include "sort-util.h"
+
+static int network_build_json(Network *network, JsonVariant **ret) {
+        assert(network);
+        assert(ret);
+
+        return json_build(ret, JSON_BUILD_OBJECT(
+                                        JSON_BUILD_PAIR("NetworkFile", JSON_BUILD_STRING(network->filename))));
+}
+
+static int device_build_json(sd_device *device, JsonVariant **ret) {
+        const char *link = NULL, *path = NULL, *vendor = NULL, *model = NULL;
+
+        assert(device);
+        assert(ret);
+
+        (void) sd_device_get_property_value(device, "ID_NET_LINK_FILE", &link);
+        (void) sd_device_get_property_value(device, "ID_PATH", &path);
+
+        if (sd_device_get_property_value(device, "ID_VENDOR_FROM_DATABASE", &vendor) < 0)
+                (void) sd_device_get_property_value(device, "ID_VENDOR", &vendor);
+
+        if (sd_device_get_property_value(device, "ID_MODEL_FROM_DATABASE", &model) < 0)
+                (void) sd_device_get_property_value(device, "ID_MODEL", &model);
+
+        return json_build(ret, JSON_BUILD_OBJECT(
+                                        JSON_BUILD_PAIR("LinkFile", JSON_BUILD_STRING(link)),
+                                        JSON_BUILD_PAIR("Path", JSON_BUILD_STRING(path)),
+                                        JSON_BUILD_PAIR("Vendor", JSON_BUILD_STRING(vendor)),
+                                        JSON_BUILD_PAIR("Model", JSON_BUILD_STRING(model))));
+}
+
+int link_build_json(Link *link, JsonVariant **ret) {
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_free_ char *type = NULL;
+        int r;
+
+        assert(link);
+        assert(ret);
+
+        r = link_get_type_string(link->sd_device, link->iftype, &type);
+        if (r == -ENOMEM)
+                return r;
+
+        r = json_build(&v, JSON_BUILD_OBJECT(
+                                        JSON_BUILD_PAIR("Index", JSON_BUILD_INTEGER(link->ifindex)),
+                                        JSON_BUILD_PAIR("Name", JSON_BUILD_STRING(link->ifname)),
+                                        JSON_BUILD_PAIR("AlternativeNames", JSON_BUILD_STRV(link->alternative_names)),
+                                        JSON_BUILD_PAIR("Type", JSON_BUILD_STRING(type)),
+                                        JSON_BUILD_PAIR("Driver", JSON_BUILD_STRING(link->driver)),
+                                        JSON_BUILD_PAIR("SetupState", JSON_BUILD_STRING(link_state_to_string(link->state))),
+                                        JSON_BUILD_PAIR("OperationalState", JSON_BUILD_STRING(link_operstate_to_string(link->operstate))),
+                                        JSON_BUILD_PAIR("CarrierState", JSON_BUILD_STRING(link_carrier_state_to_string(link->carrier_state))),
+                                        JSON_BUILD_PAIR("AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->address_state))),
+                                        JSON_BUILD_PAIR("IPv4AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv4_address_state))),
+                                        JSON_BUILD_PAIR("IPv6AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv6_address_state)))));
+        if (r < 0)
+                return r;
+
+        if (link->network) {
+                _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
+
+                r = network_build_json(link->network, &w);
+                if (r < 0)
+                        return r;
+
+                r = json_variant_merge(&v, w);
+                if (r < 0)
+                        return r;
+        }
+
+        if (link->sd_device) {
+                _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
+
+                r = device_build_json(link->sd_device, &w);
+                if (r < 0)
+                        return r;
+
+                r = json_variant_merge(&v, w);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(v);
+        return 0;
+}
+
+static int link_json_compare(JsonVariant * const *a, JsonVariant * const *b) {
+        intmax_t index_a, index_b;
+
+        assert(a && *a);
+        assert(b && *b);
+
+        index_a = json_variant_integer(json_variant_by_key(*a, "Index"));
+        index_b = json_variant_integer(json_variant_by_key(*b, "Index"));
+
+        return CMP(index_a, index_b);
+}
+
+int manager_build_json(Manager *manager, JsonVariant **ret) {
+        JsonVariant **elements;
+        Link *link;
+        size_t n = 0;
+        int r;
+
+        assert(manager);
+        assert(ret);
+
+        elements = new(JsonVariant*, hashmap_size(manager->links));
+        if (!elements)
+                return -ENOMEM;
+
+        HASHMAP_FOREACH(link, manager->links) {
+                r = link_build_json(link, elements + n);
+                if (r < 0)
+                        goto finalize;
+                n++;
+        }
+
+        typesafe_qsort(elements, n, link_json_compare);
+
+        r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("Interfaces", JSON_BUILD_VARIANT_ARRAY(elements, n))));
+
+finalize:
+        json_variant_unref_many(elements, n);
+        free(elements);
+        return r;
+}
diff --git a/src/network/networkd-json.h b/src/network/networkd-json.h
new file mode 100644 (file)
index 0000000..25018fa
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "json.h"
+
+typedef struct Link Link;
+typedef struct Manager Manager;
+
+int link_build_json(Link *link, JsonVariant **ret);
+int manager_build_json(Manager *manager, JsonVariant **ret);
index a999b05845c1422221d3bcdff0120a34b0077337..f2f47c52b086f3e86ae22ccd5cb68726cdc95137 100644 (file)
@@ -10,6 +10,7 @@
 #include "bus-message-util.h"
 #include "bus-polkit.h"
 #include "dns-domain.h"
+#include "networkd-json.h"
 #include "networkd-link-bus.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
@@ -678,6 +679,35 @@ int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_
         return sd_bus_reply_method_return(message, NULL);
 }
 
+int bus_link_method_describe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_free_ char *text = NULL;
+        Link *link = userdata;
+        int r;
+
+        assert(message);
+        assert(link);
+
+        r = link_build_json(link, &v);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to build JSON data: %m");
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to format JSON data: %m");
+
+        r = sd_bus_message_new_method_return(message, &reply);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "s", text);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(NULL, reply, NULL);
+}
+
 const sd_bus_vtable link_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
@@ -764,6 +794,11 @@ const sd_bus_vtable link_vtable[] = {
                                 SD_BUS_NO_RESULT,
                                 bus_link_method_reconfigure,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("Describe",
+                                SD_BUS_NO_ARGS,
+                                SD_BUS_RESULT("s", json),
+                                bus_link_method_describe,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_VTABLE_END
 };
index 45594dfac99911428496131f78673741a7f32af3..ddc3fcb39df7a46351bd9cf2b7e08a6984c7f8e2 100644 (file)
@@ -34,3 +34,4 @@ int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_e
 int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_link_method_force_renew(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_link_method_describe(sd_bus_message *message, void *userdata, sd_bus_error *error);
index 0acaeb2bed0cb2af251e92901b6312014d9b847e..f66d7d1612778a3a4ea5872b46484b66f8ca20f5 100644 (file)
@@ -8,6 +8,7 @@
 #include "bus-common-errors.h"
 #include "bus-message-util.h"
 #include "bus-polkit.h"
+#include "networkd-json.h"
 #include "networkd-link-bus.h"
 #include "networkd-link.h"
 #include "networkd-manager-bus.h"
@@ -229,6 +230,39 @@ static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_err
         return sd_bus_reply_method_return(message, NULL);
 }
 
+static int bus_method_describe_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return call_link_method(userdata, message, bus_link_method_describe, error);
+}
+
+static int bus_method_describe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_free_ char *text = NULL;
+        Manager *manager = userdata;
+        int r;
+
+        assert(message);
+        assert(manager);
+
+        r = manager_build_json(manager, &v);
+        if (r < 0)
+                return log_error_errno(r, "Failed to build JSON data: %m");
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_error_errno(r, "Failed to format JSON data: %m");
+
+        r = sd_bus_message_new_method_return(message, &reply);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(reply, "s", text);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send(NULL, reply, NULL);
+}
+
 const sd_bus_vtable manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
@@ -333,6 +367,16 @@ const sd_bus_vtable manager_vtable[] = {
                                 SD_BUS_NO_RESULT,
                                 bus_method_reload,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DescribeLink",
+                                SD_BUS_ARGS("i", ifindex),
+                                SD_BUS_RESULT("s", json),
+                                bus_method_describe_link,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("Describe",
+                                SD_BUS_NO_ARGS,
+                                SD_BUS_RESULT("s", json),
+                                bus_method_describe,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_VTABLE_END
 };