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 /src/network/networkd-json.c | |
parent | 1a3caa49d757ed0b90f86d0f1c3eee55a1588e61 (diff) | |
download | systemd-54a16efe18289126467c802651dffb9a1c4bf703.tar.gz |
network: introduce Describe() method for manager and links
Diffstat (limited to 'src/network/networkd-json.c')
-rw-r--r-- | src/network/networkd-json.c | 135 |
1 files changed, 135 insertions, 0 deletions
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; +} |