From: gvenugo3 Date: Fri, 23 Jan 2026 02:38:30 +0000 (-0700) Subject: networkd-json: add human-readable address strings for IP addresses X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf27c70d70f5912078f68b66869d16198aaa36a5;p=thirdparty%2Fsystemd.git networkd-json: add human-readable address strings for IP addresses Add JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, and JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING macros (plus _NON_NULL variants) that emit both the binary address array and a human-readable string representation. For example, an address field now emits both: "Address": [192, 168, 1, 1] "AddressString": "192.168.1.1" This improves usability of the JSON/Varlink output for debugging and tooling that consumes networkd state. Updated networkd-json.c to use these new macros for addresses, neighbors, nexthops, routes, routing policy rules, DNS servers, NTP servers, SIP servers, domains, DHCPv6 prefixes, and link-local addresses. Also updated the Varlink interface definitions to include the new string fields. --- diff --git a/src/libsystemd-network/sd-dhcp-server-lease.c b/src/libsystemd-network/sd-dhcp-server-lease.c index b8807391bdc..171d809faab 100644 --- a/src/libsystemd-network/sd-dhcp-server-lease.c +++ b/src/libsystemd-network/sd-dhcp-server-lease.c @@ -244,7 +244,7 @@ static int dhcp_server_lease_append_json(sd_dhcp_server_lease *lease, sd_json_va return sd_json_buildo( ret, SD_JSON_BUILD_PAIR_BYTE_ARRAY("ClientId", lease->client_id.raw, lease->client_id.size), - JSON_BUILD_PAIR_IN4_ADDR_NON_NULL("Address", &(struct in_addr) { .s_addr = lease->address }), + JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL("Address", &(struct in_addr) { .s_addr = lease->address }), JSON_BUILD_PAIR_STRING_NON_EMPTY("Hostname", lease->hostname), SD_JSON_BUILD_PAIR_UNSIGNED("HardwareAddressType", lease->htype), SD_JSON_BUILD_PAIR_UNSIGNED("HardwareAddressLength", lease->hlen), diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 12c11a316a7..334a2506dc8 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -190,6 +190,12 @@ enum { _JSON_BUILD_PAIR_TRISTATE_NON_NULL, _JSON_BUILD_PAIR_PIDREF_NON_NULL, _JSON_BUILD_PAIR_DEVNUM, + _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, + _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, + _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, + _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, + _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, + _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, _SD_JSON_BUILD_REALLYMAX, }; @@ -237,6 +243,12 @@ enum { #define JSON_BUILD_PAIR_OCTESCAPE_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_HEX_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n } #define JSON_BUILD_PAIR_TRISTATE_NON_NULL(name, i) _JSON_BUILD_PAIR_TRISTATE_NON_NULL, (const char*) { name }, (int) { i } #define JSON_BUILD_PAIR_PIDREF_NON_NULL(name, p) _JSON_BUILD_PAIR_PIDREF_NON_NULL, (const char*) { name }, (const PidRef*) { p } +#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } +#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, (const char*) { name }, (const struct in6_addr*) { v } +#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, (const char*) { name }, (const struct in_addr*) { v } +#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } +#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v } +#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in_addr*) { v } #define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov)) #define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov)) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index c18807444de..f263ab67400 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -4741,7 +4741,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { if (r < 0) goto finish; - r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE(f)); + r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)); if (r < 0) goto finish; } @@ -4896,6 +4896,207 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { break; } + case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL: + case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: { + 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 *); + f = va_arg(ap, int); + a = va_arg(ap, const union in_addr_union *); + + if (current->n_suppress == 0) { + bool have_address = a && in_addr_is_set(f, a); + + if (have_address || command != _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL) { + _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; + + /* For non-NON_NULL variant, always convert address to string (even if all zeros). + * For NON_NULL variant, we only get here when have_address is true. */ + if (a) { + r = in_addr_to_string(f, a, &addr_str); + if (r < 0) + goto finish; + } + + string_key_name = strjoin(n, "String"); + if (!string_key_name) { + r = -ENOMEM; + goto finish; + } + + r = sd_json_variant_new_string(&add, n); + if (r < 0) + goto finish; + + r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_key, string_key_name); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_value, addr_str); + if (r < 0) + goto finish; + + if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(string_key); + current->elements[current->n_elements++] = TAKE_PTR(string_value); + } + } + + n_subtract = 4; /* we generated two pairs (binary and string) */ + + current->expect = EXPECT_OBJECT_KEY; + break; + } + + case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL: + case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING: { + 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 (current->n_suppress == 0) { + bool have_address = a && in6_addr_is_set(a); + + if (have_address || command != _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL) { + _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; + + /* For non-NON_NULL variant, always convert address to string (even if all zeros). + * For NON_NULL variant, we only get here when have_address is true. */ + if (a) { + r = in6_addr_to_string(a, &addr_str); + if (r < 0) + goto finish; + } + + string_key_name = strjoin(n, "String"); + if (!string_key_name) { + r = -ENOMEM; + goto finish; + } + + r = sd_json_variant_new_string(&add, n); + if (r < 0) + goto finish; + + r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr)); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_key, string_key_name); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_value, addr_str); + if (r < 0) + goto finish; + + if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(string_key); + current->elements[current->n_elements++] = TAKE_PTR(string_value); + } + } + + n_subtract = 4; /* we generated two pairs (binary and string) */ + + current->expect = EXPECT_OBJECT_KEY; + break; + } + + case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL: + case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING: { + 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 (current->n_suppress == 0) { + bool have_address = a && !in4_addr_is_null(a); + + if (have_address || command != _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL) { + _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; + + /* For non-NON_NULL variant, always convert address to string (even if all zeros). + * For NON_NULL variant, we only get here when have_address is true. */ + if (a) { + union in_addr_union addr_union = { .in = *a }; + r = in_addr_to_string(AF_INET, &addr_union, &addr_str); + if (r < 0) + goto finish; + } + + string_key_name = strjoin(n, "String"); + if (!string_key_name) { + r = -ENOMEM; + goto finish; + } + + r = sd_json_variant_new_string(&add, n); + if (r < 0) + goto finish; + + r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr)); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_key, string_key_name); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_value, addr_str); + if (r < 0) + goto finish; + + if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(string_key); + current->elements[current->n_elements++] = TAKE_PTR(string_value); + } + } + + n_subtract = 4; /* we generated two pairs (binary and string) */ + + current->expect = EXPECT_OBJECT_KEY; + break; + } + case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: { sd_json_build_callback_t cb; void *userdata; diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index cd09ed29c97..584f07249d4 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -10,6 +10,7 @@ #include "dhcp-server-lease-internal.h" #include "dhcp6-lease-internal.h" #include "extract-word.h" +#include "in-addr-util.h" #include "ip-protocol-list.h" #include "json-util.h" #include "netif-util.h" @@ -42,11 +43,11 @@ static int address_append_json(Address *address, bool serializing, sd_json_varia r = sd_json_buildo( &v, SD_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_IN_ADDR_WITH_STRING("Address", address->family, &address->in_addr), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("Peer", address->family, &address->in_addr_peer), SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", address->prefixlen), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(address->source)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &address->provider, address->family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", address->family, &address->provider)); if (r < 0) return r; @@ -67,7 +68,7 @@ static int address_append_json(Address *address, bool serializing, sd_json_varia r = sd_json_variant_merge_objectbo( &v, - JSON_BUILD_PAIR_IN4_ADDR_NON_NULL("Broadcast", &address->broadcast), + JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL("Broadcast", &address->broadcast), SD_JSON_BUILD_PAIR_UNSIGNED("Scope", address->scope), SD_JSON_BUILD_PAIR_STRING("ScopeString", scope), SD_JSON_BUILD_PAIR_UNSIGNED("Flags", address->flags), @@ -125,7 +126,7 @@ static int neighbor_append_json(Neighbor *n, sd_json_variant **array) { return sd_json_variant_append_arraybo( array, SD_JSON_BUILD_PAIR_INTEGER("Family", n->dst_addr.family), - JSON_BUILD_PAIR_IN_ADDR("Destination", &n->dst_addr.address, n->dst_addr.family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING("Destination", n->dst_addr.family, &n->dst_addr.address), JSON_BUILD_PAIR_HW_ADDR("LinkLayerAddress", &n->ll_addr), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)), SD_JSON_BUILD_PAIR_STRING("ConfigState", state)); @@ -180,7 +181,7 @@ static int nexthop_append_json(NextHop *n, bool serializing, sd_json_variant **a SD_JSON_BUILD_PAIR_UNSIGNED("ID", n->id), SD_JSON_BUILD_PAIR_INTEGER("Family", n->family), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(n->source)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &n->provider, n->family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", n->family, &n->provider)); if (r < 0) return r; @@ -206,7 +207,7 @@ static int nexthop_append_json(NextHop *n, bool serializing, sd_json_variant **a r = sd_json_variant_merge_objectbo( &v, - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &n->gw.address, n->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("Gateway", n->family, &n->gw.address), SD_JSON_BUILD_PAIR_UNSIGNED("Flags", n->flags), SD_JSON_BUILD_PAIR_STRING("FlagsString", strempty(flags)), SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", n->protocol), @@ -260,13 +261,12 @@ static int route_append_json(Route *route, bool serializing, sd_json_variant **a r = sd_json_buildo( &v, SD_JSON_BUILD_PAIR_INTEGER("Family", route->family), - JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING("Destination", route->family, &route->dst), SD_JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->nexthop.gw, route->nexthop.family), - SD_JSON_BUILD_PAIR_CONDITION(route->src_prefixlen > 0, - "Source", JSON_BUILD_IN_ADDR(&route->src, route->family)), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("Gateway", route->nexthop.family, &route->nexthop.gw), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("Source", route->family, route->src_prefixlen > 0 ? &route->src : NULL), JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("SourcePrefixLength", route->src_prefixlen), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("PreferredSource", &route->prefsrc, route->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("PreferredSource", route->family, &route->prefsrc), SD_JSON_BUILD_PAIR_UNSIGNED("TOS", route->tos), SD_JSON_BUILD_PAIR_UNSIGNED("Scope", route->scope), SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", route->protocol), @@ -276,7 +276,7 @@ static int route_append_json(Route *route, bool serializing, sd_json_variant **a SD_JSON_BUILD_PAIR_UNSIGNED("Flags", route->flags), JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("NextHopID", route->nexthop_id), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(route->source)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", &route->provider, route->family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", route->family, &route->provider)); if (r < 0) return r; @@ -383,10 +383,10 @@ static int routing_policy_rule_append_json(RoutingPolicyRule *rule, sd_json_vari return sd_json_variant_append_arraybo( array, SD_JSON_BUILD_PAIR_INTEGER("Family", rule->family), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("FromPrefix", &rule->from.address, rule->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("FromPrefix", rule->family, &rule->from.address), SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->from.address), "FromPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->from.prefixlen)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ToPrefix", &rule->to.address, rule->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ToPrefix", rule->family, &rule->to.address), SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->to.address), "ToPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->to.prefixlen)), SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", rule->protocol), @@ -510,12 +510,12 @@ static int dns_append_json_one(Link *link, const struct in_addr_full *a, Network return sd_json_variant_append_arraybo( array, SD_JSON_BUILD_PAIR_INTEGER("Family", a->family), - JSON_BUILD_PAIR_IN_ADDR("Address", &a->address, a->family), + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING("Address", a->family, &a->address), JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("Port", a->port), SD_JSON_BUILD_PAIR_CONDITION(a->ifindex != 0, "InterfaceIndex", SD_JSON_BUILD_INTEGER(a->ifindex)), JSON_BUILD_PAIR_STRING_NON_EMPTY("ServerName", a->server_name), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, a->family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", a->family, p)); } static int dns_append_json(Link *link, sd_json_variant **v) { @@ -709,16 +709,24 @@ static int dnr_append_json(Link *link, sd_json_variant **v) { } static int server_append_json_one_addr(int family, const union in_addr_union *a, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) { + _cleanup_free_ char *address_str = NULL; + int r; + assert(IN_SET(family, AF_INET, AF_INET6)); assert(a); assert(array); + r = in_addr_to_string(family, a, &address_str); + if (r < 0) + return r; + return sd_json_variant_append_arraybo( array, SD_JSON_BUILD_PAIR_INTEGER("Family", family), JSON_BUILD_PAIR_IN_ADDR("Address", a, family), + SD_JSON_BUILD_PAIR_STRING("AddressString", address_str), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p)); } static int server_append_json_one_fqdn(int family, const char *fqdn, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) { @@ -730,7 +738,7 @@ static int server_append_json_one_fqdn(int family, const char *fqdn, NetworkConf array, SD_JSON_BUILD_PAIR_STRING("Server", fqdn), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p)); } static int server_append_json_one_string(const char *str, NetworkConfigSource s, sd_json_variant **array) { @@ -829,7 +837,7 @@ static int domain_append_json(int family, const char *domain, NetworkConfigSourc array, SD_JSON_BUILD_PAIR_STRING("Domain", domain), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family)); + JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p)); } static int sip_append_json(Link *link, sd_json_variant **v) { @@ -1103,10 +1111,10 @@ static int pref64_append_json(Link *link, sd_json_variant **v) { SET_FOREACH(i, link->ndisc_pref64) { r = sd_json_variant_append_arraybo( &array, - JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("Prefix", &i->prefix), + JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING("Prefix", &i->prefix), SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", i->prefix_len), JSON_BUILD_PAIR_FINITE_USEC("LifetimeUSec", i->lifetime_usec), - JSON_BUILD_PAIR_IN6_ADDR_NON_NULL("ConfigProvider", &i->router)); + JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL("ConfigProvider", &i->router)); if (r < 0) return r; } @@ -1222,6 +1230,7 @@ static int dhcp6_client_pd_append_json(Link *link, sd_json_variant **v) { usec_t lifetime_preferred_usec, lifetime_valid_usec; struct in6_addr prefix; uint8_t prefix_len; + _cleanup_free_ char *prefix_str = NULL; r = sd_dhcp6_lease_get_pd_prefix(link->dhcp6_lease, &prefix, &prefix_len); if (r < 0) @@ -1232,9 +1241,16 @@ static int dhcp6_client_pd_append_json(Link *link, sd_json_variant **v) { if (r < 0) return r; + if (in6_addr_is_set(&prefix)) { + r = in6_addr_to_string(&prefix, &prefix_str); + if (r < 0) + return r; + } + r = sd_json_variant_append_arraybo( &array, JSON_BUILD_PAIR_IN6_ADDR("Prefix", &prefix), + JSON_BUILD_PAIR_STRING_NON_EMPTY("PrefixString", prefix_str), SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", prefix_len), JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUSec", lifetime_preferred_usec), JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUSec", lifetime_valid_usec)); @@ -1343,6 +1359,7 @@ static int dhcp_client_pd_append_json(Link *link, sd_json_variant **v) { struct in6_addr sixrd_prefix; const struct in_addr *br_addresses; size_t n_br_addresses = 0; + _cleanup_free_ char *prefix_str = NULL; int r; assert(link); @@ -1356,6 +1373,12 @@ static int dhcp_client_pd_append_json(Link *link, sd_json_variant **v) { if (r < 0) return r; + if (in6_addr_is_set(&sixrd_prefix)) { + r = in6_addr_to_string(&sixrd_prefix, &prefix_str); + if (r < 0) + return r; + } + FOREACH_ARRAY(br_address, br_addresses, n_br_addresses) { r = sd_json_variant_append_arrayb(&addresses, JSON_BUILD_IN4_ADDR(br_address)); if (r < 0) @@ -1365,6 +1388,7 @@ static int dhcp_client_pd_append_json(Link *link, sd_json_variant **v) { r = sd_json_buildo( &array, JSON_BUILD_PAIR_IN6_ADDR("Prefix", &sixrd_prefix), + JSON_BUILD_PAIR_STRING_NON_EMPTY("PrefixString", prefix_str), SD_JSON_BUILD_PAIR_UNSIGNED("PrefixLength", sixrd_prefixlen), SD_JSON_BUILD_PAIR_UNSIGNED("IPv4MaskLength", ipv4masklen), JSON_BUILD_PAIR_VARIANT_NON_NULL("BorderRouters", addresses)); @@ -1502,7 +1526,7 @@ int link_build_json(Link *link, sd_json_variant **ret) { 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), + JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL("IPv6LinkLocalAddress", &link->ipv6ll_address), /* wlan information */ SD_JSON_BUILD_PAIR_CONDITION(link->wlan_iftype > 0, "WirelessLanInterfaceType", SD_JSON_BUILD_UNSIGNED(link->wlan_iftype)), diff --git a/src/shared/varlink-io.systemd.Network.c b/src/shared/varlink-io.systemd.Network.c index f4623ad5763..1fdb6a7b659 100644 --- a/src/shared/varlink-io.systemd.Network.c +++ b/src/shared/varlink-io.systemd.Network.c @@ -2,6 +2,13 @@ #include "varlink-io.systemd.Network.h" +/* Helper macro to define address fields with both binary and string representation */ +#define SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \ + SD_VARLINK_FIELD_COMMENT(comment), \ + SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \ + SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \ + SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags)) + static SD_VARLINK_DEFINE_ENUM_TYPE( LinkState, SD_VARLINK_DEFINE_ENUM_VALUE(pending), @@ -35,12 +42,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( RoutingPolicyRule, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("Source address prefix to match"), - SD_VARLINK_DEFINE_FIELD(FromPrefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"), SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Destination address prefix to match"), - SD_VARLINK_DEFINE_FIELD(ToPrefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of destination prefix in bits"), SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"), @@ -92,18 +97,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Route, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("Destination network address"), - SD_VARLINK_DEFINE_FIELD(Destination, SD_VARLINK_INT, SD_VARLINK_ARRAY), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0), SD_VARLINK_FIELD_COMMENT("Destination network prefix length"), SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("Gateway address for this route"), - SD_VARLINK_DEFINE_FIELD(Gateway, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Source address prefix for route selection"), - SD_VARLINK_DEFINE_FIELD(Source, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Source prefix length"), SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Preferred source address for outgoing packets"), - SD_VARLINK_DEFINE_FIELD(PreferredSource, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field"), SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"), @@ -138,8 +139,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this route"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration state of this route"), SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Interface index for serialization"), @@ -162,8 +162,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("Gateway address for this next hop"), - SD_VARLINK_DEFINE_FIELD(Gateway, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"), SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable flags string"), @@ -178,8 +177,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this next hop"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration state of this next hop"), SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); @@ -210,8 +208,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( DNS, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("DNS server IP address"), - SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0), SD_VARLINK_FIELD_COMMENT("DNS server port number"), SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"), @@ -220,34 +217,29 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( NTP, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("NTP server IP address"), - SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("NTP server"), SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( SIP, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("SIP server IP address"), - SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("SIP server domain name"), SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( Domain, @@ -255,8 +247,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0), SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( DNSSECNegativeTrustAnchor, @@ -282,12 +273,13 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Pref64, SD_VARLINK_FIELD_COMMENT("IPv6 prefix for NAT64/DNS64"), SD_VARLINK_DEFINE_FIELD(Prefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Human-readable IPv6 prefix"), + SD_VARLINK_DEFINE_FIELD(PrefixString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of the prefix in bits"), SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"), SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Address of router that provided this prefix"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( NDisc, @@ -298,18 +290,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Address, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("IP address"), - SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY), - SD_VARLINK_FIELD_COMMENT("Peer address for point-to-point interfaces"), - SD_VARLINK_DEFINE_FIELD(Peer, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Network prefix length"), SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Configuration source for this address"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_FIELD_COMMENT("Address of the configuration provider (DHCP server, router, etc.)"), - SD_VARLINK_DEFINE_FIELD(ConfigProvider, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Broadcast address for IPv4 networks"), - SD_VARLINK_DEFINE_FIELD(Broadcast, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"), SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable scope string"), @@ -335,8 +323,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Neighbor, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_FIELD_COMMENT("IP address of the neighbor"), - SD_VARLINK_DEFINE_FIELD(Destination, SD_VARLINK_INT, SD_VARLINK_ARRAY), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0), SD_VARLINK_FIELD_COMMENT("Link layer (MAC) address of the neighbor"), SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY), SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"), @@ -366,12 +353,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( DHCPv6ClientPD, SD_VARLINK_FIELD_COMMENT("Delegated IPv6 prefix"), SD_VARLINK_DEFINE_FIELD(Prefix, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("Human-readable delegated IPv6 prefix"), + SD_VARLINK_DEFINE_FIELD(PrefixString, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of the delegated prefix in bits"), SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Preferred lifetime of the prefix in microseconds"), - SD_VARLINK_DEFINE_FIELD(PreferredLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_FIELD(PreferredLifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Valid lifetime of the prefix in microseconds"), - SD_VARLINK_DEFINE_FIELD(ValidLifetimeUsec, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_FIELD(ValidLifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( DHCPv6ClientVendorOption, @@ -397,8 +386,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( DHCPServerLease, SD_VARLINK_FIELD_COMMENT("DHCP client identifier"), SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("Address assigned to the client"), - SD_VARLINK_DEFINE_FIELD(Address, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Hostname provided by the DHCP client"), SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"), @@ -459,8 +447,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Broadcast address for Ethernet interfaces"), SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_FIELD_COMMENT("IPv6 link-local address"), - SD_VARLINK_DEFINE_FIELD(IPv6LinkLocalAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"), SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"),