mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-26 10:03:40 +03:00
Merge pull request #21360 from yuwata/network-json
network: json: add more information
This commit is contained in:
commit
66a8eddd6d
@ -114,6 +114,13 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
|
||||
return family == AF_INET6 ? 16 : 4;
|
||||
}
|
||||
|
||||
#define FAMILY_ADDRESS_SIZE_SAFE(f) \
|
||||
({ \
|
||||
int _f = (f); \
|
||||
_f == AF_INET ? sizeof(struct in_addr) : \
|
||||
_f == AF_INET6 ? sizeof(struct in6_addr) : 0; \
|
||||
})
|
||||
|
||||
/* Workaround for clang, explicitly specify the maximum-size element here.
|
||||
* See also oss-fuzz#11344. */
|
||||
#define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} })
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define ADDRESSES_PER_LINK_MAX 2048U
|
||||
#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
|
||||
|
||||
static int address_flags_to_string_alloc(uint32_t flags, int family, char **ret) {
|
||||
int address_flags_to_string_alloc(uint32_t flags, int family, char **ret) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
static const struct {
|
||||
uint32_t flag;
|
||||
|
@ -61,6 +61,8 @@ const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) _warn_unu
|
||||
#define FORMAT_LIFETIME(lifetime) \
|
||||
format_lifetime((char[FORMAT_TIMESPAN_MAX+STRLEN("for ")]){}, FORMAT_TIMESPAN_MAX+STRLEN("for "), lifetime)
|
||||
|
||||
int address_flags_to_string_alloc(uint32_t flags, int family, char **ret);
|
||||
|
||||
int address_new(Address **ret);
|
||||
Address* address_free(Address *address);
|
||||
int address_get(Link *link, const Address *in, Address **ret);
|
||||
|
@ -1,26 +1,480 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/nexthop.h>
|
||||
|
||||
#include "ip-protocol-list.h"
|
||||
#include "netif-util.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-json.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-neighbor.h"
|
||||
#include "networkd-nexthop.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-route-util.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "sort-util.h"
|
||||
#include "user-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
static int network_build_json(Network *network, JsonVariant **ret) {
|
||||
assert(network);
|
||||
static int address_build_json(Address *address, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ char *scope = NULL, *flags = NULL, *state = NULL;
|
||||
int r;
|
||||
|
||||
assert(address);
|
||||
assert(ret);
|
||||
|
||||
r = route_scope_to_string_alloc(address->scope, &scope);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = address_flags_to_string_alloc(address->flags, address->family, &flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_config_state_to_string_alloc(address->state, &state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_INTEGER("Family", address->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR("Address", &address->in_addr, address->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Peer", &address->in_addr_peer, address->family),
|
||||
JSON_BUILD_PAIR_IN4_ADDR_NON_NULL("Broadcast", &address->broadcast),
|
||||
JSON_BUILD_PAIR_UNSIGNED("PrefixLength", address->prefixlen),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Scope", address->scope),
|
||||
JSON_BUILD_PAIR_STRING("ScopeString", scope),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Flags", address->flags),
|
||||
JSON_BUILD_PAIR_STRING("FlagsString", flags),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Label", address->label),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUsec", address->lifetime_preferred_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUsec", address->lifetime_valid_usec),
|
||||
JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(address->source)),
|
||||
JSON_BUILD_PAIR_STRING("ConfigState", state),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &address->provider, address->family)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int addresses_build_json(Set *addresses, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
Address *address;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (set_isempty(addresses)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, set_size(addresses));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
SET_FOREACH(address, addresses) {
|
||||
r = address_build_json(address, elements + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("Addresses", JSON_BUILD_VARIANT_ARRAY(elements, n))));
|
||||
|
||||
finalize:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int neighbor_build_json(Neighbor *n, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ char *state = NULL;
|
||||
int r;
|
||||
|
||||
assert(n);
|
||||
assert(ret);
|
||||
|
||||
r = network_config_state_to_string_alloc(n->state, &state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_INTEGER("Family", n->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR("Destination", &n->in_addr, n->family),
|
||||
JSON_BUILD_PAIR_HW_ADDR("LinkLayerAddress", &n->ll_addr),
|
||||
JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
|
||||
JSON_BUILD_PAIR_STRING("ConfigState", state)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neighbors_build_json(Set *neighbors, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
Neighbor *neighbor;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (set_isempty(neighbors)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, set_size(neighbors));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
SET_FOREACH(neighbor, neighbors) {
|
||||
r = neighbor_build_json(neighbor, elements + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("Neighbors", JSON_BUILD_VARIANT_ARRAY(elements, n))));
|
||||
|
||||
finalize:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int nexthop_group_build_json(NextHop *nexthop, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
struct nexthop_grp *g;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(nexthop);
|
||||
assert(ret);
|
||||
|
||||
if (hashmap_isempty(nexthop->group)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, hashmap_size(nexthop->group));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(g, nexthop->group) {
|
||||
r = json_build(elements + n, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_UNSIGNED("ID", g->id),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Weight", g->weight+1)));
|
||||
if (r < 0)
|
||||
goto failure;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_variant_new_array(ret, elements, n);
|
||||
|
||||
failure:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int nexthop_build_json(NextHop *n, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *group = NULL;
|
||||
_cleanup_free_ char *flags = NULL, *protocol = NULL, *state = NULL;
|
||||
int r;
|
||||
|
||||
assert(n);
|
||||
assert(ret);
|
||||
|
||||
r = route_flags_to_string_alloc(n->flags, &flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = route_protocol_to_string_alloc(n->protocol, &protocol);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_config_state_to_string_alloc(n->state, &state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = nexthop_group_build_json(n, &group);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_UNSIGNED("ID", n->id),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw, n->family),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags),
|
||||
JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol),
|
||||
JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
|
||||
JSON_BUILD_PAIR_BOOLEAN("Blackhole", n->blackhole),
|
||||
JSON_BUILD_PAIR_VARIANT_NON_NULL("Group", group),
|
||||
JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)),
|
||||
JSON_BUILD_PAIR_STRING("ConfigState", state)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nexthops_build_json(Set *nexthops, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
NextHop *nexthop;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (set_isempty(nexthops)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, set_size(nexthops));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
SET_FOREACH(nexthop, nexthops) {
|
||||
r = nexthop_build_json(nexthop, elements + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("NextHops", JSON_BUILD_VARIANT_ARRAY(elements, n))));
|
||||
|
||||
finalize:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int route_build_json(Route *route, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ char *scope = NULL, *protocol = NULL, *table = NULL, *flags = NULL, *state = NULL;
|
||||
Manager *manager;
|
||||
int r;
|
||||
|
||||
assert(route);
|
||||
assert(ret);
|
||||
|
||||
manager = route->link ? route->link->manager : route->manager;
|
||||
|
||||
assert(manager);
|
||||
|
||||
r = route_scope_to_string_alloc(route->scope, &scope);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = route_protocol_to_string_alloc(route->protocol, &protocol);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_get_route_table_to_string(manager, route->table, &table);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = route_flags_to_string_alloc(route->flags, &flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_config_state_to_string_alloc(route->state, &state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_INTEGER("Family", route->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family),
|
||||
JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->gw, route->gw_family),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Source", &route->src, route->family),
|
||||
JSON_BUILD_PAIR_CONDITION(in_addr_is_set(route->family, &route->src),
|
||||
"SourcePrefixLength", JSON_BUILD_UNSIGNED(route->src_prefixlen)),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("PreferredSource", &route->prefsrc, route->family),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Scope", route->scope),
|
||||
JSON_BUILD_PAIR_STRING("ScopeString", scope),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Protocol", route->protocol),
|
||||
JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Type", route->type),
|
||||
JSON_BUILD_PAIR_STRING("TypeString", route_type_to_string(route->type)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Priority", route->priority),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Table", route->table),
|
||||
JSON_BUILD_PAIR_STRING("TableString", table),
|
||||
JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("MTU", route->mtu),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Preference", route->pref),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Flags", route->flags),
|
||||
JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("LifetimeUSec", route->lifetime_usec),
|
||||
JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(route->source)),
|
||||
JSON_BUILD_PAIR_STRING("ConfigState", state),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &route->provider, route->family)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int routes_build_json(Set *routes, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
Route *route;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (set_isempty(routes)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, set_size(routes));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
SET_FOREACH(route, routes) {
|
||||
r = route_build_json(route, elements + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("Routes", JSON_BUILD_VARIANT_ARRAY(elements, n))));
|
||||
|
||||
finalize:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int routing_policy_rule_build_json(RoutingPolicyRule *rule, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ char *table = NULL, *protocol = NULL, *state = NULL;
|
||||
int r;
|
||||
|
||||
assert(rule);
|
||||
assert(rule->manager);
|
||||
assert(ret);
|
||||
|
||||
r = manager_get_route_table_to_string(rule->manager, rule->table, &table);
|
||||
if (r < 0 && r != -EINVAL)
|
||||
return r;
|
||||
|
||||
r = route_protocol_to_string_alloc(rule->protocol, &protocol);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_config_state_to_string_alloc(rule->state, &state);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR_INTEGER("Family", rule->family),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("FromPrefix", &rule->from, rule->family),
|
||||
JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->from),
|
||||
"FromPrefixLength", JSON_BUILD_UNSIGNED(rule->from_prefixlen)),
|
||||
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ToPrefix", &rule->to, rule->family),
|
||||
JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->to),
|
||||
"ToPrefixLength", JSON_BUILD_UNSIGNED(rule->to_prefixlen)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Protocol", rule->protocol),
|
||||
JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
|
||||
JSON_BUILD_PAIR_UNSIGNED("TOS", rule->tos),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Type", rule->type),
|
||||
JSON_BUILD_PAIR_STRING("TypeString", fr_act_type_full_to_string(rule->type)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("IPProtocol", rule->ipproto),
|
||||
JSON_BUILD_PAIR_STRING("IPProtocolString", ip_protocol_to_name(rule->ipproto)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Priority", rule->priority),
|
||||
JSON_BUILD_PAIR_UNSIGNED("FirewallMark", rule->fwmark),
|
||||
JSON_BUILD_PAIR_UNSIGNED("FirewallMask", rule->fwmask),
|
||||
JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("Table", rule->table),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("TableString", table),
|
||||
JSON_BUILD_PAIR_BOOLEAN("Invert", rule->invert_rule),
|
||||
JSON_BUILD_PAIR_CONDITION(rule->suppress_prefixlen >= 0,
|
||||
"SuppressPrefixLength", JSON_BUILD_UNSIGNED(rule->suppress_prefixlen)),
|
||||
JSON_BUILD_PAIR_CONDITION(rule->suppress_ifgroup >= 0,
|
||||
"SuppressInterfaceGroup", JSON_BUILD_UNSIGNED(rule->suppress_ifgroup)),
|
||||
JSON_BUILD_PAIR_CONDITION(rule->sport.start != 0 || rule->sport.end != 0, "SourcePort",
|
||||
JSON_BUILD_ARRAY(JSON_BUILD_UNSIGNED(rule->sport.start), JSON_BUILD_UNSIGNED(rule->sport.end))),
|
||||
JSON_BUILD_PAIR_CONDITION(rule->dport.start != 0 || rule->dport.end != 0, "DestinationPort",
|
||||
JSON_BUILD_ARRAY(JSON_BUILD_UNSIGNED(rule->dport.start), JSON_BUILD_UNSIGNED(rule->dport.end))),
|
||||
JSON_BUILD_PAIR_CONDITION(rule->uid_range.start != UID_INVALID && rule->uid_range.end != UID_INVALID, "User",
|
||||
JSON_BUILD_ARRAY(JSON_BUILD_UNSIGNED(rule->uid_range.start), JSON_BUILD_UNSIGNED(rule->uid_range.end))),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("IncomingInterface", rule->iif),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("OutgoingInterface", rule->oif),
|
||||
JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(rule->source)),
|
||||
JSON_BUILD_PAIR_STRING("ConfigState", state)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int routing_policy_rules_build_json(Set *rules, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
RoutingPolicyRule *rule;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (set_isempty(rules)) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
elements = new(JsonVariant*, set_size(rules));
|
||||
if (!elements)
|
||||
return -ENOMEM;
|
||||
|
||||
SET_FOREACH(rule, rules) {
|
||||
r = routing_policy_rule_build_json(rule, elements + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("RoutingPolicyRules", JSON_BUILD_VARIANT_ARRAY(elements, n))));
|
||||
|
||||
finalize:
|
||||
json_variant_unref_many(elements, n);
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int network_build_json(Network *network, JsonVariant **ret) {
|
||||
assert(ret);
|
||||
|
||||
if (!network) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return json_build(ret, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("NetworkFile", JSON_BUILD_STRING(network->filename))));
|
||||
JSON_BUILD_PAIR_STRING("NetworkFile", 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);
|
||||
|
||||
if (!device) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) sd_device_get_property_value(device, "ID_NET_LINK_FILE", &link);
|
||||
(void) sd_device_get_property_value(device, "ID_PATH", &path);
|
||||
|
||||
@ -31,15 +485,15 @@ static int device_build_json(sd_device *device, JsonVariant **ret) {
|
||||
(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))));
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("LinkFile", link),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Path", path),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Vendor", vendor),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Model", model)));
|
||||
}
|
||||
|
||||
int link_build_json(Link *link, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ char *type = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
|
||||
_cleanup_free_ char *type = NULL, *flags = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@ -49,45 +503,106 @@ int link_build_json(Link *link, JsonVariant **ret) {
|
||||
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))),
|
||||
JSON_BUILD_PAIR("OnlineState", JSON_BUILD_STRING(link_online_state_to_string(link->online_state)))));
|
||||
r = link_flags_to_string_alloc(link->flags, &flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
|
||||
r = json_build(&v, JSON_BUILD_OBJECT(
|
||||
/* basic information */
|
||||
JSON_BUILD_PAIR_INTEGER("Index", link->ifindex),
|
||||
JSON_BUILD_PAIR_STRING("Name", link->ifname),
|
||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("AlternativeNames", link->alternative_names),
|
||||
JSON_BUILD_PAIR_CONDITION(link->master_ifindex > 0,
|
||||
"MasterInterfaceIndex", JSON_BUILD_INTEGER(link->master_ifindex)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Kind", link->kind),
|
||||
JSON_BUILD_PAIR_STRING("Type", type),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("Driver", link->driver),
|
||||
JSON_BUILD_PAIR_UNSIGNED("Flags", link->flags),
|
||||
JSON_BUILD_PAIR_STRING("FlagsString", flags),
|
||||
JSON_BUILD_PAIR_UNSIGNED("KernelOperationalState", link->kernel_operstate),
|
||||
JSON_BUILD_PAIR_STRING("KernelOperationalStateString", kernel_operstate_to_string(link->kernel_operstate)),
|
||||
JSON_BUILD_PAIR_UNSIGNED("MTU", link->mtu),
|
||||
JSON_BUILD_PAIR_UNSIGNED("MinimumMTU", link->min_mtu),
|
||||
JSON_BUILD_PAIR_UNSIGNED("MaximumMTU", link->max_mtu),
|
||||
JSON_BUILD_PAIR_HW_ADDR_NON_NULL("HardwareAddress", &link->hw_addr),
|
||||
JSON_BUILD_PAIR_HW_ADDR_NON_NULL("PermanentHardwareAddress", &link->permanent_hw_addr),
|
||||
JSON_BUILD_PAIR_HW_ADDR_NON_NULL("BroadcastAddress", &link->bcast_addr),
|
||||
JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("IPv6LinkLocalAddress", &link->ipv6ll_address),
|
||||
/* wlan information */
|
||||
JSON_BUILD_PAIR_CONDITION(link->wlan_iftype > 0, "WirelessLanInterfaceType",
|
||||
JSON_BUILD_UNSIGNED(link->wlan_iftype)),
|
||||
JSON_BUILD_PAIR_CONDITION(link->wlan_iftype > 0, "WirelessLanInterfaceTypeString",
|
||||
JSON_BUILD_STRING(nl80211_iftype_to_string(link->wlan_iftype))),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("SSID", link->ssid),
|
||||
JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL("BSSID", &link->bssid),
|
||||
/* link state */
|
||||
JSON_BUILD_PAIR_STRING("SetupState", link_state_to_string(link->state)),
|
||||
JSON_BUILD_PAIR_STRING("OperationalState", link_operstate_to_string(link->operstate)),
|
||||
JSON_BUILD_PAIR_STRING("CarrierState", link_carrier_state_to_string(link->carrier_state)),
|
||||
JSON_BUILD_PAIR_STRING("AddressState", link_address_state_to_string(link->address_state)),
|
||||
JSON_BUILD_PAIR_STRING("IPv4AddressState", link_address_state_to_string(link->ipv4_address_state)),
|
||||
JSON_BUILD_PAIR_STRING("IPv6AddressState", link_address_state_to_string(link->ipv6_address_state)),
|
||||
JSON_BUILD_PAIR_STRING("OnlineState", link_online_state_to_string(link->online_state))));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_build_json(link->network, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = network_build_json(link->network, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, 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;
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = device_build_json(link->sd_device, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = device_build_json(link->sd_device, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = addresses_build_json(link->addresses, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = neighbors_build_json(link->neighbors, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = nexthops_build_json(link->nexthops, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = routes_build_json(link->routes, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
@ -105,7 +620,7 @@ static int link_json_compare(JsonVariant * const *a, JsonVariant * const *b) {
|
||||
return CMP(index_a, index_b);
|
||||
}
|
||||
|
||||
int manager_build_json(Manager *manager, JsonVariant **ret) {
|
||||
static int links_build_json(Manager *manager, JsonVariant **ret) {
|
||||
JsonVariant **elements;
|
||||
Link *link;
|
||||
size_t n = 0;
|
||||
@ -134,3 +649,46 @@ finalize:
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
int manager_build_json(Manager *manager, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
assert(ret);
|
||||
|
||||
r = links_build_json(manager, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = nexthops_build_json(manager->nexthops, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = routes_build_json(manager->routes, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
w = json_variant_unref(w);
|
||||
|
||||
r = routing_policy_rules_build_json(manager->rules, &w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_merge(&v, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2670,3 +2670,53 @@ static const char* const link_state_table[_LINK_STATE_MAX] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
|
||||
|
||||
int link_flags_to_string_alloc(uint32_t flags, char **ret) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
static const struct {
|
||||
uint32_t flag;
|
||||
const char *name;
|
||||
} map[] = {
|
||||
{ IFF_UP, "up" }, /* interface is up. */
|
||||
{ IFF_BROADCAST, "broadcast" }, /* broadcast address valid.*/
|
||||
{ IFF_DEBUG, "debug" }, /* turn on debugging. */
|
||||
{ IFF_LOOPBACK, "loopback" }, /* interface is a loopback net. */
|
||||
{ IFF_POINTOPOINT, "point-to-point" }, /* interface has p-p link. */
|
||||
{ IFF_NOTRAILERS, "no-trailers" }, /* avoid use of trailers. */
|
||||
{ IFF_RUNNING, "running" }, /* interface RFC2863 OPER_UP. */
|
||||
{ IFF_NOARP, "no-arp" }, /* no ARP protocol. */
|
||||
{ IFF_PROMISC, "promiscuous" }, /* receive all packets. */
|
||||
{ IFF_ALLMULTI, "all-multicast" }, /* receive all multicast packets. */
|
||||
{ IFF_MASTER, "master" }, /* master of a load balancer. */
|
||||
{ IFF_SLAVE, "slave" }, /* slave of a load balancer. */
|
||||
{ IFF_MULTICAST, "multicast" }, /* supports multicast.*/
|
||||
{ IFF_PORTSEL, "portsel" }, /* can set media type. */
|
||||
{ IFF_AUTOMEDIA, "auto-media" }, /* auto media select active. */
|
||||
{ IFF_DYNAMIC, "dynamic" }, /* dialup device with changing addresses. */
|
||||
{ IFF_LOWER_UP, "lower-up" }, /* driver signals L1 up. */
|
||||
{ IFF_DORMANT, "dormant" }, /* driver signals dormant. */
|
||||
{ IFF_ECHO, "echo" }, /* echo sent packets. */
|
||||
};
|
||||
|
||||
assert(ret);
|
||||
|
||||
for (size_t i = 0; i < ELEMENTSOF(map); i++)
|
||||
if (flags & map[i].flag &&
|
||||
!strextend_with_separator(&str, ",", map[i].name))
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const kernel_operstate_table[] = {
|
||||
[IF_OPER_UNKNOWN] = "unknown",
|
||||
[IF_OPER_NOTPRESENT] = "not-present",
|
||||
[IF_OPER_DOWN] = "down",
|
||||
[IF_OPER_LOWERLAYERDOWN] = "lower-layer-down",
|
||||
[IF_OPER_TESTING] = "testing",
|
||||
[IF_OPER_DORMANT] = "dormant",
|
||||
[IF_OPER_UP] = "up",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(kernel_operstate, int);
|
||||
|
@ -227,3 +227,6 @@ int link_reconfigure_after_sleep(Link *link);
|
||||
|
||||
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
|
||||
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
int link_flags_to_string_alloc(uint32_t flags, char **ret);
|
||||
const char *kernel_operstate_to_string(int t) _const_;
|
||||
|
@ -29,8 +29,18 @@ static const char *const fr_act_type_table[__FR_ACT_MAX] = {
|
||||
[FR_ACT_PROHIBIT] = "prohibit",
|
||||
};
|
||||
|
||||
static const char *const fr_act_type_full_table[__FR_ACT_MAX] = {
|
||||
[FR_ACT_TO_TBL] = "table",
|
||||
[FR_ACT_GOTO] = "goto",
|
||||
[FR_ACT_NOP] = "nop",
|
||||
[FR_ACT_BLACKHOLE] = "blackhole",
|
||||
[FR_ACT_UNREACHABLE] = "unreachable",
|
||||
[FR_ACT_PROHIBIT] = "prohibit",
|
||||
};
|
||||
|
||||
assert_cc(__FR_ACT_MAX <= UINT8_MAX);
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(fr_act_type, int);
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(fr_act_type_full, int);
|
||||
|
||||
RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
|
||||
if (!rule)
|
||||
|
@ -54,6 +54,8 @@ typedef struct RoutingPolicyRule {
|
||||
int32_t suppress_ifgroup;
|
||||
} RoutingPolicyRule;
|
||||
|
||||
const char *fr_act_type_full_to_string(int t) _const_;
|
||||
|
||||
RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule);
|
||||
|
||||
void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state);
|
||||
|
@ -3242,7 +3242,7 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *add = NULL, *add_more = NULL;
|
||||
size_t n_subtract = 0; /* how much to subtract from current->n_suppress, i.e. how many elements would
|
||||
* have been added to the current variant */
|
||||
JsonStack *current;
|
||||
@ -3707,6 +3707,34 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_HW_ADDR: {
|
||||
const struct hw_addr_data *hw_addr;
|
||||
|
||||
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
assert_se(hw_addr = va_arg(ap, struct hw_addr_data*));
|
||||
|
||||
if (current->n_suppress == 0) {
|
||||
r = json_variant_new_array_bytes(&add, hw_addr->bytes, hw_addr->length);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 1;
|
||||
|
||||
if (current->expect == EXPECT_TOPLEVEL)
|
||||
current->expect = EXPECT_END;
|
||||
else if (current->expect == EXPECT_OBJECT_VALUE)
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
else
|
||||
assert(current->expect == EXPECT_ARRAY_ELEMENT);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_OBJECT_BEGIN:
|
||||
|
||||
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
|
||||
@ -3806,16 +3834,298 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
|
||||
current->expect = EXPECT_OBJECT_VALUE;
|
||||
break;
|
||||
}}
|
||||
}
|
||||
|
||||
/* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */
|
||||
case _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO: {
|
||||
const char *n;
|
||||
uint64_t u;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
u = va_arg(ap, uint64_t);
|
||||
|
||||
if (u != 0 && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_unsigned(&add_more, u);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_FINITE_USEC: {
|
||||
const char *n;
|
||||
usec_t u;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
u = va_arg(ap, usec_t);
|
||||
|
||||
if (u != USEC_INFINITY && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_unsigned(&add_more, u);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_STRING_NON_EMPTY: {
|
||||
const char *n, *s;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
s = va_arg(ap, const char *);
|
||||
|
||||
if (!isempty(s) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_string(&add_more, s);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_STRV_NON_EMPTY: {
|
||||
const char *n;
|
||||
char **l;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
l = va_arg(ap, char **);
|
||||
|
||||
if (!strv_isempty(l) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_strv(&add_more, l);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_VARIANT_NON_NULL: {
|
||||
JsonVariant *v;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
v = va_arg(ap, JsonVariant *);
|
||||
|
||||
if (v && !json_variant_is_null(v) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
add_more = json_variant_ref(v);
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: {
|
||||
const struct in_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in_addr *);
|
||||
|
||||
if (in4_addr_is_set(a) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL: {
|
||||
const struct in6_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct in6_addr *);
|
||||
|
||||
if (in6_addr_is_set(a) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: {
|
||||
const union in_addr_union *a;
|
||||
const char *n;
|
||||
int f;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const union in_addr_union *);
|
||||
f = va_arg(ap, int);
|
||||
|
||||
if (in_addr_is_set(f, a) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE(f));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL: {
|
||||
const struct ether_addr *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct ether_addr *);
|
||||
|
||||
if (!ether_addr_is_null(a) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_bytes(&add_more, a->ether_addr_octet, sizeof(struct ether_addr));
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
case _JSON_BUILD_PAIR_HW_ADDR_NON_NULL: {
|
||||
const struct hw_addr_data *a;
|
||||
const char *n;
|
||||
|
||||
if (current->expect != EXPECT_OBJECT_KEY) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n = va_arg(ap, const char *);
|
||||
a = va_arg(ap, const struct hw_addr_data *);
|
||||
|
||||
if (!hw_addr_is_null(a) && current->n_suppress == 0) {
|
||||
r = json_variant_new_string(&add, n);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = json_variant_new_array_bytes(&add_more, a->bytes, a->length);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
n_subtract = 2; /* we generated two item */
|
||||
|
||||
current->expect = EXPECT_OBJECT_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If variants were generated, add them to our current variant, but only if we are not supposed to suppress additions */
|
||||
if (add && current->n_suppress == 0) {
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 1)) {
|
||||
if (!GREEDY_REALLOC(current->elements, current->n_elements + 1 + !!add_more)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
current->elements[current->n_elements++] = TAKE_PTR(add);
|
||||
if (add_more)
|
||||
current->elements[current->n_elements++] = TAKE_PTR(add_more);
|
||||
}
|
||||
|
||||
/* If we are supposed to suppress items, let's subtract how many items where generated from that
|
||||
|
@ -9,9 +9,13 @@
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "ether-addr-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "string-util.h"
|
||||
#include "log.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
||||
/*
|
||||
In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has
|
||||
@ -236,6 +240,18 @@ enum {
|
||||
_JSON_BUILD_HEX,
|
||||
_JSON_BUILD_ID128,
|
||||
_JSON_BUILD_BYTE_ARRAY,
|
||||
_JSON_BUILD_HW_ADDR,
|
||||
_JSON_BUILD_PAIR_UNSIGNED_NON_ZERO,
|
||||
_JSON_BUILD_PAIR_FINITE_USEC,
|
||||
_JSON_BUILD_PAIR_STRING_NON_EMPTY,
|
||||
_JSON_BUILD_PAIR_STRV_NON_EMPTY,
|
||||
_JSON_BUILD_PAIR_VARIANT_NON_NULL,
|
||||
_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY,
|
||||
_JSON_BUILD_PAIR_IN4_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN6_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_IN_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL,
|
||||
_JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
|
||||
_JSON_BUILD_MAX,
|
||||
};
|
||||
|
||||
@ -260,6 +276,46 @@ enum {
|
||||
#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, (const sd_id128_t*) { &(id) }
|
||||
#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, (const void*) { v }, (size_t) { n }
|
||||
#define JSON_BUILD_CONST_STRING(s) _JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s)
|
||||
#define JSON_BUILD_IN4_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr))
|
||||
#define JSON_BUILD_IN6_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr))
|
||||
#define JSON_BUILD_IN_ADDR(v, f) JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
|
||||
#define JSON_BUILD_ETHER_ADDR(v) JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr))
|
||||
#define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v }
|
||||
|
||||
#define JSON_BUILD_PAIR_STRING(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING(s))
|
||||
#define JSON_BUILD_PAIR_INTEGER(name, i) JSON_BUILD_PAIR(name, JSON_BUILD_INTEGER(i))
|
||||
#define JSON_BUILD_PAIR_UNSIGNED(name, u) JSON_BUILD_PAIR(name, JSON_BUILD_UNSIGNED(u))
|
||||
#define JSON_BUILD_PAIR_REAL(name, d) JSON_BUILD_PAIR(name, JSON_BUILD_REAL(d))
|
||||
#define JSON_BUILD_PAIR_BOOLEAN(name, b) JSON_BUILD_PAIR(name, JSON_BUILD_BOOLEAN(b))
|
||||
#define JSON_BUILD_PAIR_ARRAY(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_ARRAY(__VA_ARGS__))
|
||||
#define JSON_BUILD_PAIR_EMPTY_ARRAY(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_ARRAY)
|
||||
#define JSON_BUILD_PAIR_OBJECT(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_OBJECT(__VA_ARGS__))
|
||||
#define JSON_BUILD_PAIR_EMPTY_OBJECT(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_OBJECT)
|
||||
#define JSON_BUILD_PAIR_NULL(name) JSON_BUILD_PAIR(name, JSON_BUILD_NULL)
|
||||
#define JSON_BUILD_PAIR_VARIANT(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT(v))
|
||||
#define JSON_BUILD_PAIR_VARIANT_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT_ARRAY(v, n))
|
||||
#define JSON_BUILD_PAIR_LITERAL(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_LITERAL(l))
|
||||
#define JSON_BUILD_PAIR_STRV(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_STRV(l))
|
||||
#define JSON_BUILD_PAIR_BASE64(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_BASE64(p, n))
|
||||
#define JSON_BUILD_PAIR_HEX(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_HEX(p, n))
|
||||
#define JSON_BUILD_PAIR_ID128(name, id) JSON_BUILD_PAIR(name, JSON_BUILD_ID128(id))
|
||||
#define JSON_BUILD_PAIR_BYTE_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_BYTE_ARRAY(v, n))
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_IN_ADDR(name, v, f) JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f))
|
||||
#define JSON_BUILD_PAIR_ETHER_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v))
|
||||
#define JSON_BUILD_PAIR_HW_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v))
|
||||
|
||||
#define JSON_BUILD_PAIR_UNSIGNED_NON_ZERO(name, u) _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, (const char*) { name }, (uint64_t) { u }
|
||||
#define JSON_BUILD_PAIR_FINITE_USEC(name, u) _JSON_BUILD_PAIR_FINITE_USEC, (const char*) { name }, (usec_t) { u }
|
||||
#define JSON_BUILD_PAIR_STRING_NON_EMPTY(name, s) _JSON_BUILD_PAIR_STRING_NON_EMPTY, (const char*) { name }, (const char*) { s }
|
||||
#define JSON_BUILD_PAIR_STRV_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_NON_EMPTY, (const char*) { name }, (char**) { l }
|
||||
#define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (JsonVariant*) { v }
|
||||
#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, v, f) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (const union in_addr_union*) { v }, (int) { f }
|
||||
#define JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, (const char*) { name }, (const struct ether_addr*) { v }
|
||||
#define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v }
|
||||
|
||||
int json_build(JsonVariant **ret, ...);
|
||||
int json_buildv(JsonVariant **ret, va_list ap);
|
||||
|
@ -2091,6 +2091,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
for i in range(1,254):
|
||||
self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
def test_address_ipv4acd(self):
|
||||
check_output('ip netns add ns99')
|
||||
check_output('ip link add veth99 type veth peer veth-peer')
|
||||
@ -2288,6 +2291,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, 'iif test1')
|
||||
self.assertRegex(output, 'lookup 10')
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
def test_routing_policy_rule_issue_11280(self):
|
||||
copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
|
||||
'routing-policy-rule-dummy98.network', '12-dummy.netdev')
|
||||
@ -2513,6 +2519,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
|
||||
self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
copy_unit_to_networkd_unit_path('25-address-static.network')
|
||||
check_output(*networkctl_cmd, 'reload', env=env)
|
||||
time.sleep(1)
|
||||
@ -2746,6 +2755,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
|
||||
self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
def test_neighbor_reconfigure(self):
|
||||
copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
|
||||
start_networkd()
|
||||
@ -2782,6 +2794,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
def test_link_local_addressing(self):
|
||||
copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
|
||||
'25-link-local-addressing-no.network', '12-dummy.netdev')
|
||||
@ -3124,6 +3139,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertIn('nexthop via 192.168.20.1 dev dummy98 weight 1', output)
|
||||
self.assertIn('nexthop via 192.168.5.1 dev veth99 weight 3', output)
|
||||
|
||||
# TODO: check json string
|
||||
check_output(*networkctl_cmd, '--json=short', 'status', env=env)
|
||||
|
||||
copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
|
||||
'12-dummy.netdev', '25-nexthop-dummy.network')
|
||||
start_networkd()
|
||||
|
Loading…
x
Reference in New Issue
Block a user