1
1
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:
Zbigniew Jędrzejewski-Szmek 2021-11-26 11:04:52 +01:00 committed by GitHub
commit 66a8eddd6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1064 additions and 48 deletions

View File

@ -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 = {} })

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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_;

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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()