From a77a95665fba06861125a4a62ffed8ccd75f37f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Apr 2026 09:35:33 +0200 Subject: [PATCH 1/5] sd-json: make sure SD_JSON_BUILD_STRING_UNDERSCORIFY() can deal with NULL strings SD_JSON_BUILD_STRING() and everything else can deal with it, make sure SD_JSON_BUILD_STRING_UNDERSCORIFY() can too. --- src/libsystemd/sd-json/sd-json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 1fd006c7d9..2c46a23632 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -3595,7 +3595,7 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { if (current->n_suppress == 0) { _cleanup_free_ char *c = NULL; - if (command == _JSON_BUILD_STRING_UNDERSCORIFY) { + if (command == _JSON_BUILD_STRING_UNDERSCORIFY && p) { c = strdup(p); if (!c) { r = -ENOMEM; From ab6feb11ed814c06723b55f5d57831f1fcb40ba8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Apr 2026 14:05:56 +0200 Subject: [PATCH 2/5] sd-json: add JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY() helper it's the combination of JSON_BUILD_PAIR_STRING_NON_EMPTY and JSON_BUILD_PAIR_STRING_UNDERSCORIFY --- src/libsystemd/sd-json/json-util.h | 2 ++ src/libsystemd/sd-json/sd-json.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 4ed0b708f8..cea2d368b4 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -170,6 +170,7 @@ enum { _JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL, _JSON_BUILD_PAIR_FINITE_USEC, _JSON_BUILD_PAIR_STRING_NON_EMPTY, + _JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY, _JSON_BUILD_PAIR_STRV_NON_EMPTY, _JSON_BUILD_PAIR_STRV_ENV_PAIR_NON_EMPTY, _JSON_BUILD_PAIR_VARIANT_NON_NULL, @@ -219,6 +220,7 @@ enum { #define JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL(name, u, eq) _JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL, (const char*) { name }, (uint64_t) { u }, (uint64_t) { eq } #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_STRING_NON_EMPTY_UNDERSCORIFY(name, s) _JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY, (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_STRV_ENV_PAIR_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_ENV_PAIR_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 }, (sd_json_variant*) { v } diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 2c46a23632..4c39b5660a 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -4573,7 +4573,8 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { break; } - case _JSON_BUILD_PAIR_STRING_NON_EMPTY: { + case _JSON_BUILD_PAIR_STRING_NON_EMPTY: + case _JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY: { const char *n, *s; if (current->expect != EXPECT_OBJECT_KEY) { @@ -4589,7 +4590,16 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { if (r < 0) goto finish; - r = sd_json_variant_new_string(&add_more, s); + if (command == _JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY) { + _cleanup_free_ char *c = strdup(s); + if (!c) { + r = -ENOMEM; + goto finish; + } + + r = sd_json_variant_new_string(&add_more, json_underscorify(c)); + } else + r = sd_json_variant_new_string(&add_more, s); if (r < 0) goto finish; } From f5575d9eb519968f48a15e8e9c5a4d8ea1d154fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Apr 2026 15:15:05 +0200 Subject: [PATCH 3/5] mountfsd: generate properly underscored designator json strings Let's make sure we generate data that will actually pass the IDL checks, and use underscores for designator names. (This is a bugfix) --- src/mountfsd/mountwork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index a5d34d4479..42860db134 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -748,7 +748,7 @@ static int vl_method_mount_image( r = sd_json_variant_append_arraybo( &aj, - SD_JSON_BUILD_PAIR_STRING("designator", partition_designator_to_string(d)), + JSON_BUILD_PAIR_ENUM("designator", partition_designator_to_string(d)), SD_JSON_BUILD_PAIR_BOOLEAN("writable", pp->rw), SD_JSON_BUILD_PAIR_BOOLEAN("growFileSystem", pp->growfs), SD_JSON_BUILD_PAIR_CONDITION(pp->partno > 0, "partitionNumber", SD_JSON_BUILD_INTEGER(pp->partno)), From 40ab0df557437f8463cdbfd5710da0c45e40d326 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Apr 2026 15:16:47 +0200 Subject: [PATCH 4/5] networkd: gnerate proper underscored enums in varlink interface AFAICS none of the states actually user dashes/underscores, but let's prepare for the future and be fully correct here. --- src/network/networkd-manager-varlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c index 71ec695339..d12847b089 100644 --- a/src/network/networkd-manager-varlink.c +++ b/src/network/networkd-manager-varlink.c @@ -54,11 +54,11 @@ static int vl_method_get_states(sd_varlink *link, sd_json_variant *parameters, s return sd_varlink_replybo( link, - SD_JSON_BUILD_PAIR_STRING("AddressState", link_address_state_to_string(m->address_state)), - SD_JSON_BUILD_PAIR_STRING("IPv4AddressState", link_address_state_to_string(m->ipv4_address_state)), - SD_JSON_BUILD_PAIR_STRING("IPv6AddressState", link_address_state_to_string(m->ipv6_address_state)), + JSON_BUILD_PAIR_ENUM("AddressState", link_address_state_to_string(m->address_state)), + JSON_BUILD_PAIR_ENUM("IPv4AddressState", link_address_state_to_string(m->ipv4_address_state)), + JSON_BUILD_PAIR_ENUM("IPv6AddressState", link_address_state_to_string(m->ipv6_address_state)), SD_JSON_BUILD_PAIR_STRING("CarrierState", link_carrier_state_to_string(m->carrier_state)), - SD_JSON_BUILD_PAIR_CONDITION(m->online_state >= 0, "OnlineState", SD_JSON_BUILD_STRING(link_online_state_to_string(m->online_state))), + SD_JSON_BUILD_PAIR_CONDITION(m->online_state >= 0, "OnlineState", JSON_BUILD_STRING_UNDERSCORIFY(link_online_state_to_string(m->online_state))), SD_JSON_BUILD_PAIR_STRING("OperationalState", link_operstate_to_string(m->operational_state))); } From 112f5317d1ce3cef8c2b35ed1201593db6f1cb65 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Apr 2026 15:18:04 +0200 Subject: [PATCH 5/5] resolved: let's generate enum fields properly too AFAICS none of the enums here uses dashes, hence this should not actually have any effect except for being more correct. --- src/network/networkd-json.c | 8 ++++---- src/resolve/resolved-dns-scope.c | 3 ++- src/resolve/resolved-manager.c | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index 04ad5cfaed..d5bed7718a 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -1544,10 +1544,10 @@ int link_build_json(Link *link, sd_json_variant **ret) { SD_JSON_BUILD_PAIR_STRING("AdministrativeState", link_state_to_string(link->state)), SD_JSON_BUILD_PAIR_STRING("OperationalState", link_operstate_to_string(link->operstate)), SD_JSON_BUILD_PAIR_STRING("CarrierState", link_carrier_state_to_string(link->carrier_state)), - SD_JSON_BUILD_PAIR_STRING("AddressState", link_address_state_to_string(link->address_state)), - SD_JSON_BUILD_PAIR_STRING("IPv4AddressState", link_address_state_to_string(link->ipv4_address_state)), - SD_JSON_BUILD_PAIR_STRING("IPv6AddressState", link_address_state_to_string(link->ipv6_address_state)), - SD_JSON_BUILD_PAIR_STRING("OnlineState", link_online_state_to_string(link->online_state))); + JSON_BUILD_PAIR_ENUM("AddressState", link_address_state_to_string(link->address_state)), + JSON_BUILD_PAIR_ENUM("IPv4AddressState", link_address_state_to_string(link->ipv4_address_state)), + JSON_BUILD_PAIR_ENUM("IPv6AddressState", link_address_state_to_string(link->ipv6_address_state)), + JSON_BUILD_PAIR_ENUM("OnlineState", link_online_state_to_string(link->online_state))); if (r < 0) return r; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 2e360a8513..89b13b0f1d 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -16,6 +16,7 @@ #include "errno-util.h" #include "fd-util.h" #include "hostname-util.h" +#include "json-util.h" #include "log.h" #include "random-util.h" #include "resolved-dns-browse-services.h" @@ -1814,7 +1815,7 @@ int dns_scope_to_json(DnsScope *scope, bool with_cache, sd_json_variant **ret) { return sd_json_buildo( ret, - SD_JSON_BUILD_PAIR_STRING("protocol", dns_protocol_to_string(scope->protocol)), + JSON_BUILD_PAIR_ENUM("protocol", dns_protocol_to_string(scope->protocol)), SD_JSON_BUILD_PAIR_CONDITION(scope->family != AF_UNSPEC, "family", SD_JSON_BUILD_INTEGER(scope->family)), SD_JSON_BUILD_PAIR_CONDITION(!!scope->link, "ifindex", SD_JSON_BUILD_INTEGER(dns_scope_ifindex(scope))), SD_JSON_BUILD_PAIR_CONDITION(!!scope->link, "ifname", SD_JSON_BUILD_STRING(dns_scope_ifname(scope))), diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index f16364fe6a..0a52e922c4 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -2156,9 +2156,9 @@ static int dns_configuration_json_append( JSON_BUILD_PAIR_CONDITION_BOOLEAN(dnssec_mode >= 0, "dnssecSupported", dnssec_supported), JSON_BUILD_PAIR_STRING_NON_EMPTY("dnssec", dnssec_mode_to_string(dnssec_mode)), JSON_BUILD_PAIR_STRING_NON_EMPTY("dnsOverTLS", dns_over_tls_mode_to_string(dns_over_tls_mode)), - JSON_BUILD_PAIR_STRING_NON_EMPTY("llmnr", resolve_support_to_string(llmnr_support)), - JSON_BUILD_PAIR_STRING_NON_EMPTY("mDNS", resolve_support_to_string(mdns_support)), - JSON_BUILD_PAIR_STRING_NON_EMPTY("resolvConfMode", resolv_conf_mode_to_string(resolv_conf_mode)), + JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY("llmnr", resolve_support_to_string(llmnr_support)), + JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY("mDNS", resolve_support_to_string(mdns_support)), + JSON_BUILD_PAIR_STRING_NON_EMPTY_UNDERSCORIFY("resolvConfMode", resolv_conf_mode_to_string(resolv_conf_mode)), JSON_BUILD_PAIR_VARIANT_NON_NULL("scopes", scopes_json)); }