diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-12 22:11:09 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-14 09:18:29 +0900 |
commit | 54a16efe18289126467c802651dffb9a1c4bf703 (patch) | |
tree | 628fe8dd6ae9cd963ff811388c105f6cc105dddd | |
parent | 1a3caa49d757ed0b90f86d0f1c3eee55a1588e61 (diff) | |
download | systemd-54a16efe18289126467c802651dffb9a1c4bf703.tar.gz |
network: introduce Describe() method for manager and links
-rw-r--r-- | src/network/meson.build | 2 | ||||
-rw-r--r-- | src/network/networkd-json.c | 135 | ||||
-rw-r--r-- | src/network/networkd-json.h | 10 | ||||
-rw-r--r-- | src/network/networkd-link-bus.c | 35 | ||||
-rw-r--r-- | src/network/networkd-link-bus.h | 1 | ||||
-rw-r--r-- | src/network/networkd-manager-bus.c | 44 |
6 files changed, 227 insertions, 0 deletions
diff --git a/src/network/meson.build b/src/network/meson.build index a8b9232e64..7b6a4b7c7a 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -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 index 0000000000..7a7fc24ea6 --- /dev/null +++ b/src/network/networkd-json.c @@ -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 index 0000000000..25018fa097 --- /dev/null +++ b/src/network/networkd-json.h @@ -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); diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index a999b05845..f2f47c52b0 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -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 }; diff --git a/src/network/networkd-link-bus.h b/src/network/networkd-link-bus.h index 45594dfac9..ddc3fcb39d 100644 --- a/src/network/networkd-link-bus.h +++ b/src/network/networkd-link-bus.h @@ -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); diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c index 0acaeb2bed..f66d7d1612 100644 --- a/src/network/networkd-manager-bus.c +++ b/src/network/networkd-manager-bus.c @@ -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 }; |