diff --git a/extra-repos/systemd/systemd-stage0/APKBUILD b/extra-repos/systemd/systemd-stage0/APKBUILD index ddfb7738a..0858843af 100644 --- a/extra-repos/systemd/systemd-stage0/APKBUILD +++ b/extra-repos/systemd/systemd-stage0/APKBUILD @@ -2,10 +2,10 @@ # Co-Maintainer: Oliver Smith maintainer="Clayton Craft " pkgname=systemd-stage0 -pkgver=261.2 +pkgver=262_rc1 _pkgver="${pkgver/_/-}" # pkgrel must match systemd! -pkgrel=1 +pkgrel=0 pkgdesc="Minimal systemd bootstrap package" url="https://github.com/systemd/systemd" # armhf: pmb#2618 @@ -101,7 +101,6 @@ build() { -Ddefault-locale=en_US.UTF-8 \ \ -Didn=false \ - -Dsysvinit-path="" \ \ -Dbacklight=false \ -Dbinfmt=false \ @@ -163,5 +162,5 @@ package() { } sha512sums=" -876f043970cb65b39ae15fba39f23bf94c7c3d80569503d6e8ea2c8013c30ee40ce43cb55cbcb1cf14d5c3021aafc09c0f67473bbf742d8964bf9fa30693b971 systemd-261.2.tar.gz +5bd4ed38246de1ea17b46fcc6f921f94a53047cec4dc53b005afd4ca75cd50d631b92c6662204871ad2c0808694244ec15d90732b1251d15bf5f9d74b6a2a7f0 systemd-262_rc1.tar.gz " diff --git a/extra-repos/systemd/systemd/0001-json-util-generalize-json_dispatch_address_family.patch b/extra-repos/systemd/systemd/0001-json-util-generalize-json_dispatch_address_family.patch deleted file mode 100644 index 00e3bb9e4..000000000 --- a/extra-repos/systemd/systemd/0001-json-util-generalize-json_dispatch_address_family.patch +++ /dev/null @@ -1,249 +0,0 @@ -From c5f08a2e5cf1f246c908ddaaefbccdcfbdbaa754 Mon Sep 17 00:00:00 2001 -From: Nick Rosbrook -Date: Fri, 19 Jun 2026 15:00:59 -0400 -Subject: [PATCH] json-util: generalize json_dispatch_address_family - -There are several places where address family is dispatched from JSON, -so take json_dispatch_address_family from networkd and put it in -json-util.c. - -Update the all instances in the tree to use this new function, adding -SD_JSON_RELAX to the dispatch flags if AF_UNSPEC should be allowed -in that case. ---- - src/libsystemd/sd-json/json-util.c | 24 ++++++++++++++++++++++++ - src/libsystemd/sd-json/json-util.h | 1 + - src/network/networkd-serialize.c | 22 ---------------------- - src/nss-resolve/nss-resolve.c | 23 +++-------------------- - src/resolve/resolvectl.c | 2 +- - src/resolve/resolved-varlink.c | 15 +++------------ - src/shared/dns-configuration.c | 14 +++++++------- - 7 files changed, 39 insertions(+), 62 deletions(-) - -diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c -index c6727ac760..485b4a03c8 100644 ---- a/src/libsystemd/sd-json/json-util.c -+++ b/src/libsystemd/sd-json/json-util.c -@@ -918,3 +918,27 @@ int json_variant_compare(sd_json_variant *a, sd_json_variant *b) { - - return CMP(sd_json_variant_type(a), sd_json_variant_type(b)); - } -+ -+int json_dispatch_address_family(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ int *family = ASSERT_PTR(userdata), r; -+ -+ assert(variant); -+ -+ if (sd_json_variant_is_negative(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), -+ "JSON field '%s' for an address family cannot be negative.", strna(name)); -+ -+ int k = AF_UNSPEC; -+ if (!sd_json_variant_is_null(variant)) { -+ r = sd_json_dispatch_int(name, variant, flags, &k); -+ if (r < 0) -+ return r; -+ } -+ -+ if (!IN_SET(k, AF_INET, AF_INET6) && !(FLAGS_SET(flags, SD_JSON_RELAX) && k == AF_UNSPEC)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), -+ "JSON field '%s' out of range for an address family.", strna(name)); -+ -+ *family = k; -+ return 0; -+} -diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h -index ecb4e2d633..de7790a6d3 100644 ---- a/src/libsystemd/sd-json/json-util.h -+++ b/src/libsystemd/sd-json/json-util.h -@@ -133,6 +133,7 @@ int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_ - int json_dispatch_strv_environment(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_access_mode(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_job_id(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); -+int json_dispatch_address_family(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - - static inline int json_variant_unbase64_iovec(sd_json_variant *v, struct iovec *ret) { - return sd_json_variant_unbase64(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL); -diff --git a/src/network/networkd-serialize.c b/src/network/networkd-serialize.c -index 394f03ced6..224fcc93a0 100644 ---- a/src/network/networkd-serialize.c -+++ b/src/network/networkd-serialize.c -@@ -102,28 +102,6 @@ int manager_set_serialization_fd(Manager *manager, int fd, const char *name) { - - static JSON_DISPATCH_ENUM_DEFINE(json_dispatch_network_config_source, NetworkConfigSource, network_config_source_from_string); - --static int json_dispatch_address_family(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -- int r, *i = ASSERT_PTR(userdata); -- int64_t i64; -- -- assert_return(variant, -EINVAL); -- -- if (FLAGS_SET(flags, SD_JSON_RELAX) && sd_json_variant_is_null(variant)) { -- *i = AF_UNSPEC; -- return 0; -- } -- -- r = sd_json_dispatch_int64(name, variant, flags, &i64); -- if (r < 0) -- return r; -- -- if (!IN_SET(i64, AF_INET, AF_INET6) && !(FLAGS_SET(flags, SD_JSON_RELAX) && i64 == AF_UNSPEC)) -- return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds for an address family.", strna(name)); -- -- *i = (int) i64; -- return 0; --} -- - typedef struct AddressParam { - int family; - struct iovec address; -diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c -index 86eaf4e3b3..9f4225be3f 100644 ---- a/src/nss-resolve/nss-resolve.c -+++ b/src/nss-resolve/nss-resolve.c -@@ -78,23 +78,6 @@ static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) { - return in6_addr_is_link_local(&in6) ? ifindex : 0; - } - --static int json_dispatch_family(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -- int *family = ASSERT_PTR(userdata); -- int64_t t; -- -- assert(variant); -- -- if (!sd_json_variant_is_integer(variant)) -- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name)); -- -- t = sd_json_variant_integer(variant); -- if (t < 0 || t > INT_MAX) -- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid family.", strna(name)); -- -- *family = (int) t; -- return 0; --} -- - typedef struct ResolveHostnameReply { - sd_json_variant *addresses; - char *name; -@@ -159,9 +142,9 @@ static int json_dispatch_address(const char *name, sd_json_variant *variant, sd_ - } - - static const sd_json_dispatch_field address_parameters_dispatch_table[] = { -- { "ifindex", SD_JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(AddressParameters, ifindex), 0 }, -- { "family", SD_JSON_VARIANT_INTEGER, json_dispatch_family, offsetof(AddressParameters, family), SD_JSON_MANDATORY }, -- { "address", SD_JSON_VARIANT_ARRAY, json_dispatch_address, 0, SD_JSON_MANDATORY }, -+ { "ifindex", SD_JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(AddressParameters, ifindex), 0 }, -+ { "family", SD_JSON_VARIANT_INTEGER, json_dispatch_address_family, offsetof(AddressParameters, family), SD_JSON_MANDATORY }, -+ { "address", SD_JSON_VARIANT_ARRAY, json_dispatch_address, 0, SD_JSON_MANDATORY }, - {} - }; - -diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c -index 67be81195a..b3895df6cf 100644 ---- a/src/resolve/resolvectl.c -+++ b/src/resolve/resolvectl.c -@@ -2386,7 +2386,7 @@ static int dump_cache_scope(sd_json_variant *scope) { - - static const sd_json_dispatch_field dispatch_table[] = { - { "protocol", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(struct scope_info, protocol), SD_JSON_MANDATORY }, -- { "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(struct scope_info, family), 0 }, -+ { "family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(struct scope_info, family), SD_JSON_RELAX }, - { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(struct scope_info, ifindex), SD_JSON_RELAX }, - { "ifname", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(struct scope_info, ifname), 0 }, - { "cache", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_variant_noref, offsetof(struct scope_info, cache), SD_JSON_MANDATORY }, -diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c -index 2ac4ee9555..db26ccb11a 100644 ---- a/src/resolve/resolved-varlink.c -+++ b/src/resolve/resolved-varlink.c -@@ -346,7 +346,7 @@ static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *paramet - static const sd_json_dispatch_field dispatch_table[] = { - { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX }, - { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParameters, name), SD_JSON_MANDATORY }, -- { "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), 0 }, -+ { "family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(LookupParameters, family), SD_JSON_RELAX }, - { "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 }, - {} - }; -@@ -377,9 +377,6 @@ static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *paramet - if (r == 0) - return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("name")); - -- if (!IN_SET(p.family, AF_UNSPEC, AF_INET, AF_INET6)) -- return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family")); -- - if (validate_and_mangle_query_flags(m, &p.flags, p.name, SD_RESOLVED_NO_SEARCH) < 0) - return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags")); - -@@ -475,7 +472,7 @@ finish: - static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { - static const sd_json_dispatch_field dispatch_table[] = { - { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParameters, ifindex), SD_JSON_RELAX }, -- { "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParameters, family), SD_JSON_MANDATORY }, -+ { "family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(LookupParameters, family), SD_JSON_MANDATORY }, - { "address", SD_JSON_VARIANT_ARRAY, json_dispatch_byte_array_iovec, offsetof(LookupParameters, address), SD_JSON_MANDATORY }, - { "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParameters, flags), 0 }, - {} -@@ -501,9 +498,6 @@ static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *paramete - if (r != 0) - return r; - -- if (!IN_SET(p.family, AF_INET, AF_INET6)) -- return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family")); -- - if (FAMILY_ADDRESS_SIZE(p.family) != p.address.iov_len) - return sd_varlink_error(link, "io.systemd.Resolve.BadAddressSize", NULL); - -@@ -961,7 +955,7 @@ static int vl_method_resolve_service(sd_varlink* link, sd_json_variant* paramete - { "type", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParametersResolveService, type), 0 }, - { "domain", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParametersResolveService, domain), SD_JSON_MANDATORY }, - { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(LookupParametersResolveService, ifindex), SD_JSON_RELAX }, -- { "family", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParametersResolveService, family), 0 }, -+ { "family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(LookupParametersResolveService, family), SD_JSON_RELAX }, - { "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParametersResolveService, flags), 0 }, - {} - }; -@@ -987,9 +981,6 @@ static int vl_method_resolve_service(sd_varlink* link, sd_json_variant* paramete - if (r != 0) - return r; - -- if (!IN_SET(p.family, AF_INET, AF_INET6, AF_UNSPEC)) -- return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family")); -- - if (isempty(p.name)) - p.name = NULL; - else if (!dns_service_name_is_valid(p.name)) -diff --git a/src/shared/dns-configuration.c b/src/shared/dns-configuration.c -index 1194e87258..01b59bbd89 100644 ---- a/src/shared/dns-configuration.c -+++ b/src/shared/dns-configuration.c -@@ -36,7 +36,7 @@ static int dispatch_dns_server(const char *name, sd_json_variant *variant, sd_js - static const sd_json_dispatch_field dns_server_dispatch_table[] = { - { "address", SD_JSON_VARIANT_ARRAY, json_dispatch_byte_array_iovec, offsetof(DNSServer, addr), SD_JSON_MANDATORY }, - { "addressString", _SD_JSON_VARIANT_TYPE_INVALID, NULL, 0, 0 }, -- { "family", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(DNSServer, family), SD_JSON_MANDATORY }, -+ { "family", SD_JSON_VARIANT_INTEGER, json_dispatch_address_family, offsetof(DNSServer, family), SD_JSON_MANDATORY }, - { "port", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint16, offsetof(DNSServer, port), 0 }, - { "ifindex", SD_JSON_VARIANT_UNSIGNED, json_dispatch_ifindex, offsetof(DNSServer, ifindex), SD_JSON_RELAX }, - { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSServer, server_name), 0 }, -@@ -177,12 +177,12 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( - - static int dispatch_dns_scope(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { - static const sd_json_dispatch_field dns_scope_dispatch_table[] = { -- { "protocol", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, protocol), SD_JSON_MANDATORY }, -- { "family", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint, offsetof(DNSScope, family), 0 }, -- { "ifname", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, ifname), 0 }, -- { "ifindex", SD_JSON_VARIANT_UNSIGNED, json_dispatch_ifindex, offsetof(DNSScope, ifindex), SD_JSON_RELAX }, -- { "dnssec", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, dnssec_mode_str), 0 }, -- { "dnsOverTLS", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, dns_over_tls_mode_str), 0 }, -+ { "protocol", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, protocol), SD_JSON_MANDATORY }, -+ { "family", SD_JSON_VARIANT_INTEGER, json_dispatch_address_family, offsetof(DNSScope, family), SD_JSON_RELAX }, -+ { "ifname", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, ifname), 0 }, -+ { "ifindex", SD_JSON_VARIANT_UNSIGNED, json_dispatch_ifindex, offsetof(DNSScope, ifindex), SD_JSON_RELAX }, -+ { "dnssec", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, dnssec_mode_str), 0 }, -+ { "dnsOverTLS", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(DNSScope, dns_over_tls_mode_str), 0 }, - {}, - }; - DNSScope **ret = ASSERT_PTR(userdata); --- -2.55.0 - diff --git a/extra-repos/systemd/systemd/0001-json-util-introduce-json_dispatch_in_addr_data.patch b/extra-repos/systemd/systemd/0001-json-util-introduce-json_dispatch_in_addr_data.patch deleted file mode 100644 index 7cf48e726..000000000 --- a/extra-repos/systemd/systemd/0001-json-util-introduce-json_dispatch_in_addr_data.patch +++ /dev/null @@ -1,305 +0,0 @@ -From 3f73f1ef75d5c8da66eda2cff270676e70becf9b Mon Sep 17 00:00:00 2001 -From: Nick Rosbrook -Date: Tue, 23 Jun 2026 12:02:19 -0400 -Subject: [PATCH] json-util: introduce json_dispatch_in_addr_data - -Generalize json_dispatch_address from nss-resolve, and add support for -strings to be compatible with the existing json_dispatch_{in,in6}_addr -helpers. This will be used in a later commit. ---- - src/libsystemd/sd-json/json-util.c | 55 ++++++++ - src/libsystemd/sd-json/json-util.h | 1 + - src/libsystemd/sd-json/test-json.c | 194 +++++++++++++++++++++++++++++ - 3 files changed, 250 insertions(+) - -diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c -index 485b4a03c8..193ee714d0 100644 ---- a/src/libsystemd/sd-json/json-util.c -+++ b/src/libsystemd/sd-json/json-util.c -@@ -248,6 +248,61 @@ int json_dispatch_in6_addr(const char *name, sd_json_variant *variant, sd_json_d - return 0; - } - -+int json_dispatch_in_addr_data(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ struct in_addr_data *ret = ASSERT_PTR(userdata), data = { .family = AF_UNSPEC, .address = IN_ADDR_NULL }; -+ int r; -+ -+ assert(variant); -+ -+ if (sd_json_variant_is_null(variant)) { -+ *ret = data; -+ return 0; -+ } -+ -+ /* We support both a more human readable string based encoding and an array based encoding */ -+ if (sd_json_variant_is_string(variant)) { -+ r = in_addr_from_string_auto(sd_json_variant_string(variant), &data.family, &data.address); -+ if (r < 0) -+ return json_log(variant, flags, r, -+ "JSON field '%s' is not a valid IPv4 or IPv6 address string: %s", strna(name), sd_json_variant_string(variant)); -+ *ret = data; -+ return 0; -+ } -+ -+ if (!sd_json_variant_is_array(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name)); -+ -+ switch (sd_json_variant_elements(variant)) { -+ case sizeof(struct in_addr): -+ data.family = AF_INET; -+ break; -+ case sizeof(struct in6_addr): -+ data.family = AF_INET6; -+ break; -+ default: -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name)); -+ } -+ -+ size_t k = 0; -+ sd_json_variant *i; -+ JSON_VARIANT_ARRAY_FOREACH(i, variant) { -+ if (!sd_json_variant_is_integer(i)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name)); -+ -+ int64_t b = sd_json_variant_integer(i); -+ if (b < 0 || b > 0xff) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), -+ "Element %zu of JSON field '%s' is out of range 0%s255.", -+ k, strna(name), glyph(GLYPH_ELLIPSIS)); -+ -+ data.address.bytes[k++] = (uint8_t) b; -+ } -+ assert(k == FAMILY_ADDRESS_SIZE_SAFE(data.family)); -+ -+ *ret = data; -+ return 0; -+} -+ - int json_dispatch_const_path(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { - const char **p = ASSERT_PTR(userdata), *path; - -diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h -index de7790a6d3..2032566fdd 100644 ---- a/src/libsystemd/sd-json/json-util.h -+++ b/src/libsystemd/sd-json/json-util.h -@@ -119,6 +119,7 @@ int json_dispatch_const_user_group_name(const char *name, sd_json_variant *varia - int json_dispatch_const_unit_name(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_in_addr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_in6_addr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); -+int json_dispatch_in_addr_data(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_path(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_const_path(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); - int json_dispatch_strv_path(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); -diff --git a/src/libsystemd/sd-json/test-json.c b/src/libsystemd/sd-json/test-json.c -index bb94dfea4b..6992d095c6 100644 ---- a/src/libsystemd/sd-json/test-json.c -+++ b/src/libsystemd/sd-json/test-json.c -@@ -13,6 +13,7 @@ - #include "fd-util.h" - #include "format-util.h" - #include "fileio.h" -+#include "in-addr-util.h" - #include "io-util.h" - #include "iovec-util.h" - #include "json-internal.h" -@@ -1998,4 +1999,197 @@ TEST(json_dispatch_in6_addr) { - ASSERT_EQ(data.addr.s6_addr[i], 0); - } - -+TEST(json_dispatch_in_addr_data) { -+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL; -+ -+ /* 192.168.1.1 = { 192, 168, 1, 1 } */ -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", JSON_BUILD_IN4_ADDR(&(const struct in_addr) { .s_addr = htobe32(0xC0A80101U) })), -+ SD_JSON_BUILD_PAIR("null_addr", SD_JSON_BUILD_NULL)))); -+ -+ struct { -+ struct in_addr_data addr; -+ struct in_addr_data null_addr; -+ } data = {}; -+ -+ ASSERT_OK(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, offsetof(typeof(data), addr) }, -+ { "null_addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, offsetof(typeof(data), null_addr) }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &data)); -+ -+ ASSERT_EQ(be32toh(data.addr.address.in.s_addr), 0xC0A80101U); -+ ASSERT_EQ(data.null_addr.address.in.s_addr, 0U); -+ ASSERT_EQ(data.addr.family, AF_INET); -+ ASSERT_EQ(data.null_addr.family, AF_UNSPEC); -+ -+ struct in_addr_data dummy = {}; -+ -+ /* Too few bytes (3 instead of 4) */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(192), SD_JSON_BUILD_UNSIGNED(168), SD_JSON_BUILD_UNSIGNED(1)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* Too many bytes (5 instead of 4) */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(192), SD_JSON_BUILD_UNSIGNED(168), SD_JSON_BUILD_UNSIGNED(1), SD_JSON_BUILD_UNSIGNED(1), SD_JSON_BUILD_UNSIGNED(0)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* Not an array or string */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_BOOLEAN(true))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* A string */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", JSON_BUILD_CONST_STRING("192.168.1.1"))))); -+ zero(data); -+ ASSERT_OK(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &data)); -+ ASSERT_EQ(be32toh(data.addr.address.in.s_addr), 0xC0A80101U); -+ ASSERT_EQ(data.addr.family, AF_INET); -+ -+ /* Byte value out of range (> 255) */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_UNSIGNED(256), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(1)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* Negative element */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_INTEGER(-1), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(1)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* ::1 */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", JSON_BUILD_IN6_ADDR(&(const struct in6_addr) { .s6_addr = { [15] = 1 } })), -+ SD_JSON_BUILD_PAIR("null_addr", SD_JSON_BUILD_NULL)))); -+ -+ zero(data); -+ ASSERT_OK(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, offsetof(typeof(data), addr) }, -+ { "null_addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, offsetof(typeof(data), null_addr) }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &data)); -+ -+ ASSERT_EQ(data.addr.address.in6.s6_addr[15], 1); -+ for (size_t i = 0; i < 15; i++) -+ ASSERT_EQ(data.addr.address.in6.s6_addr[i], 0); -+ for (size_t i = 0; i < 16; i++) -+ ASSERT_EQ(data.null_addr.address.in6.s6_addr[i], 0); -+ ASSERT_EQ(data.addr.family, AF_INET6); -+ ASSERT_EQ(data.null_addr.family, AF_UNSPEC); -+ -+ /* Too few bytes (15 instead of 16) */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY( -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(1)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* Too many bytes (17 instead of 16) */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_ARRAY( -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), -+ SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(0), SD_JSON_BUILD_UNSIGNED(1), -+ SD_JSON_BUILD_UNSIGNED(0)))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* Not an array */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", SD_JSON_BUILD_BOOLEAN(true))))); -+ ASSERT_ERROR(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &dummy), EINVAL); -+ -+ /* A string */ -+ j = sd_json_variant_unref(j); -+ ASSERT_OK(sd_json_build(&j, SD_JSON_BUILD_OBJECT( -+ SD_JSON_BUILD_PAIR("addr", JSON_BUILD_CONST_STRING("::1"))))); -+ -+ zero(data); -+ ASSERT_OK(sd_json_dispatch(j, -+ (const sd_json_dispatch_field[]) { -+ { "addr", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, 0 }, -+ {}, -+ }, -+ /* flags= */ 0, -+ &data)); -+ -+ ASSERT_EQ(data.addr.address.in6.s6_addr[15], 1); -+ for (size_t i = 0; i < 15; i++) -+ ASSERT_EQ(data.addr.address.in6.s6_addr[i], 0); -+ ASSERT_EQ(data.addr.family, AF_INET6); -+} -+ - DEFINE_TEST_MAIN(LOG_DEBUG); --- -2.55.0 - diff --git a/extra-repos/systemd/systemd/0001-resolvectl-use-varlink-instead-of-dbus-for-ResolveHo.patch b/extra-repos/systemd/systemd/0001-resolvectl-use-varlink-instead-of-dbus-for-ResolveHo.patch deleted file mode 100644 index 6f72cbd33..000000000 --- a/extra-repos/systemd/systemd/0001-resolvectl-use-varlink-instead-of-dbus-for-ResolveHo.patch +++ /dev/null @@ -1,440 +0,0 @@ -From 35d611622a0c4277e1a3e0b8866a800c0fc6fcf8 Mon Sep 17 00:00:00 2001 -From: Nick Rosbrook -Date: Fri, 19 Jun 2026 15:01:00 -0400 -Subject: [PATCH] resolvectl: use varlink instead of dbus for ResolveHostname - ---- - src/resolve/resolvectl.c | 202 +++++++++++++++++++----------- - src/shared/meson.build | 1 + - src/shared/resolve-varlink-util.c | 107 ++++++++++++++++ - src/shared/resolve-varlink-util.h | 34 +++++ - 4 files changed, 274 insertions(+), 70 deletions(-) - create mode 100644 src/shared/resolve-varlink-util.c - create mode 100644 src/shared/resolve-varlink-util.h - -diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c -index b3895df6cf..4baa2f3868 100644 ---- a/src/resolve/resolvectl.c -+++ b/src/resolve/resolvectl.c -@@ -48,6 +48,7 @@ - #include "resolvectl.h" - #include "resolved-def.h" - #include "resolved-util.h" -+#include "resolve-varlink-util.h" - #include "set.h" - #include "socket-netlink.h" - #include "string-table.h" -@@ -278,20 +279,97 @@ static void print_ifindex_comment(int printed_so_far, int ifindex) { - ansi_grey(), ifname, ansi_normal()); - } - --static int resolve_host_error(const char *name, int r, const sd_bus_error *error) { -- if (sd_bus_error_has_name(error, BUS_ERROR_DNS_NXDOMAIN)) -- return log_error_errno(r, "%s: %s", name, bus_error_message(error, r)); -+static int varlink_log_resolve_error(const char *name, const char *error_id, sd_json_variant *reply) { -+ int r; -+ -+ assert(name); -+ assert(!isempty(error_id)); -+ -+ int ret = sd_varlink_error_to_errno(error_id, reply); -+ static const struct { -+ const char *error_id; -+ const char *msg; -+ } error_message_table[] = { -+ { "io.systemd.Resolve.NoNameServers", "No appropriate name servers or networks for name found" }, -+ { "io.systemd.Resolve.QueryTimedOut", "Query timed out" }, -+ { "io.systemd.Resolve.MaxAttemptsReached", "All attempts to contact name servers or networks failed" }, -+ { "io.systemd.Resolve.InvalidReply", "Received invalid reply" }, -+ { "io.systemd.Resolve.QueryAborted", "Query aborted" }, -+ { "io.systemd.Resolve.QueryRefused", "DNS query type refused" }, -+ { "io.systemd.Resolve.NoTrustAnchor", "No suitable trust anchor known" }, -+ { "io.systemd.Resolve.ResourceRecordTypeUnsupported", "Server does not support requested resource record type" }, -+ { "io.systemd.Resolve.NetworkDown", "Network is down" }, -+ { "io.systemd.Resolve.NoSource", "All suitable resolution sources turned off" }, -+ { "io.systemd.Resolve.StubLoop", "Configured DNS server loops back to us" }, -+ { "io.systemd.Resolve.ZoneTransfersNotPermitted", "Zone transfers not permitted via this programming interface" }, -+ }; -+ FOREACH_ELEMENT(em, error_message_table) -+ if (streq(em->error_id, error_id)) -+ return log_error_errno(ret, "%s: resolve call failed: %s", name, em->msg); -+ -+ if (streq(error_id, "io.systemd.Resolve.NoSuchResourceRecord")) -+ return log_error_errno(ret, "%s: resolve call failed: '%s' does not have any RR of the requested type", name, name); - -- return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(error, r)); -+ if (streq(error_id, "io.systemd.Resolve.CNAMELoop")) -+ return log_error_errno(ret, "%s: resolve call failed: CNAME loop detected, or CNAME resolving disabled on '%s'", name, name); -+ -+ if (streq(error_id, "io.systemd.Resolve.ServiceNotProvided")) -+ return log_error_errno(ret, "%s: resolve call failed: '%s' does not provide the requested service", name, name); -+ -+ if (streq(error_id, "io.systemd.Resolve.InconsistentServiceRecords")) -+ return log_error_errno(ret, "%s: resolve call failed: '%s' does not provide a consistent set of service resource records", name, name); -+ -+ _cleanup_(resolve_error_done) ResolveError error = { -+ .rcode = _DNS_RCODE_INVALID, -+ .ede_rcode = _DNS_EDE_RCODE_INVALID, -+ }; -+ r = dispatch_resolve_error(/* name = */ NULL, reply, SD_JSON_LOG, &error); -+ if (r < 0) -+ log_debug_errno(r, "Failed to dispatch error JSON, ignoring: %m"); -+ -+ _cleanup_free_ char *msg_extended = NULL; -+ if (error.ede_rcode >= 0) { -+ msg_extended = strjoin(" (", -+ FORMAT_DNS_EDE_RCODE(error.ede_rcode), -+ !isempty(error.ede_msg) ? ": " : "", -+ strempty(error.ede_msg), -+ ")"); -+ if (!msg_extended) -+ return log_oom(); -+ } -+ -+ if (streq(error_id, "io.systemd.Resolve.DNSSECValidationFailed")) -+ return log_error_errno(ret, "%s: resolve call failed: DNSSEC validation failed: %s%s", name, error.result, strempty(msg_extended)); -+ -+ if (error.rcode != _DNS_RCODE_INVALID) { -+ if (error.rcode == DNS_RCODE_NXDOMAIN) -+ return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "%s: resolve call failed: Name '%s' not found%s%s", -+ name, error.query_string ?: name, error.ede_rcode >= 0 ? ":" : "", strempty(msg_extended)); -+ -+ return log_error_errno(ret, "%s: resolve call failed: Could not resolve '%s', server or network returned error: %s%s", -+ name, error.query_string ?: name, FORMAT_DNS_RCODE(error.rcode), strempty(msg_extended)); -+ } -+ -+ return log_error_errno(ret, "%s: resolve call failed: %s", name, error_id); - } - --static int resolve_host(sd_bus *bus, const char *name) { -- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -- const char *canonical = NULL; -- unsigned c = 0; -- uint64_t flags; -- usec_t ts; -+static int varlink_connect_with_query_timeout(sd_varlink **vl) { -+ int r; -+ -+ assert(vl); -+ -+ r = sd_varlink_connect_address(vl, "/run/systemd/resolve/io.systemd.Resolve"); -+ if (r < 0) -+ return log_error_errno(r, "Failed to connect to service /run/systemd/resolve/io.systemd.Resolve: %m"); -+ -+ r = sd_varlink_set_relative_timeout(*vl, SD_RESOLVED_QUERY_TIMEOUT_USEC); -+ if (r < 0) -+ return log_error_errno(r, "Failed to set query timeout: %m"); -+ -+ return 0; -+} -+ -+static int resolve_host(const char *name) { - int r; - - assert(name); -@@ -301,85 +379,69 @@ static int resolve_host(sd_bus *bus, const char *name) { - - log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); - -- r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname"); -- if (r < 0) -- return bus_log_create_error(r); -- -- r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags); -+ _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL; -+ r = varlink_connect_with_query_timeout(&vl); - if (r < 0) -- return bus_log_create_error(r); -+ return r; - -- ts = now(CLOCK_MONOTONIC); -+ usec_t ts = now(CLOCK_MONOTONIC); - -- r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); -+ const char *error_id = NULL; -+ sd_json_variant *v = NULL; -+ r = sd_varlink_callbo( -+ vl, -+ "io.systemd.Resolve.ResolveHostname", -+ &v, -+ &error_id, -+ SD_JSON_BUILD_PAIR_STRING("name", name), -+ JSON_BUILD_PAIR_CONDITION_UNSIGNED(arg_ifindex > 0, "ifindex", arg_ifindex), -+ JSON_BUILD_PAIR_CONDITION_UNSIGNED(arg_family != AF_UNSPEC, "family", arg_family), -+ JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("flags", arg_flags)); - if (r < 0) -- return resolve_host_error(name, r, &error); -+ return log_error_errno(r, "Failed to issue varlink call: %m"); - - ts = now(CLOCK_MONOTONIC) - ts; - -- r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); -+ if (!isempty(error_id)) -+ return varlink_log_resolve_error(name, error_id, v); -+ -+ _cleanup_(resolve_hostname_reply_done) ResolveHostnameReply reply = {}; -+ r = dispatch_resolve_hostname_reply(/* name = */ NULL, v, SD_JSON_LOG, &reply); - if (r < 0) -- return bus_log_parse_error(r); -+ return r; - -- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { -+ bool first = true; -+ FOREACH_ARRAY(address, reply.addresses, reply.n_addresses) { - _cleanup_free_ char *pretty = NULL; -- int ifindex, family, k; -- union in_addr_union a; -- -- assert_cc(sizeof(int) == sizeof(int32_t)); -- -- r = sd_bus_message_read(reply, "i", &ifindex); -- if (r < 0) -- return bus_log_parse_error(r); -- -- sd_bus_error_free(&error); -- r = bus_message_read_in_addr_auto(reply, &error, &family, &a); -- if (r < 0 && !sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)) -- return log_error_errno(r, "%s: systemd-resolved returned invalid result: %s", name, bus_error_message(&error, r)); -- -- r = sd_bus_message_exit_container(reply); -- if (r < 0) -- return bus_log_parse_error(r); -- -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)) { -- log_debug_errno(r, "%s: systemd-resolved returned invalid result, ignoring: %s", name, bus_error_message(&error, r)); -- continue; -- } -- -- r = in_addr_ifindex_to_string(family, &a, ifindex, &pretty); -+ r = in_addr_ifindex_to_string(address->family, &address->in_addr.address, address->ifindex, &pretty); - if (r < 0) - return log_error_errno(r, "Failed to print address for %s: %m", name); - -- k = printf("%*s%s %s%s%s", -- (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", -- ansi_highlight(), pretty, ansi_normal()); -+ int k = printf("%*s%s %s%s%s", -+ (int) strlen(name), -+ first ? name : "", -+ first ? ":" : " ", -+ ansi_highlight(), -+ pretty, -+ ansi_normal()); - -- print_ifindex_comment(k, ifindex); -+ print_ifindex_comment(k, address->ifindex); - fputc('\n', stdout); - -- c++; -+ first = false; - } -- if (r < 0) -- return bus_log_parse_error(r); -- -- r = sd_bus_message_exit_container(reply); -- if (r < 0) -- return bus_log_parse_error(r); - -- r = sd_bus_message_read(reply, "st", &canonical, &flags); -- if (r < 0) -- return bus_log_parse_error(r); -- -- if (!streq(name, canonical)) -+ if (!streq(name, reply.name)) - printf("%*s%s (%s)\n", -- (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", -- canonical); -+ (int) strlen(name), -+ reply.n_addresses == 0 ? name : "", -+ reply.n_addresses == 0 ? ":" : " ", -+ reply.name); - -- if (c == 0) -- return log_error_errno(SYNTHETIC_ERRNO(ESRCH), -- "%s: no addresses found", name); -+ if (reply.n_addresses == 0) -+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "%s: no addresses found", name); - -- print_source(flags, ts); -+ print_source(reply.flags, ts); - - return 0; - } -@@ -827,7 +889,7 @@ static int verb_query(int argc, char *argv[], uintptr_t _data, void *userdata) { - if (r >= 0) - RET_GATHER(ret, resolve_address(bus, family, &a, ifindex)); - else -- RET_GATHER(ret, resolve_host(bus, *p)); -+ RET_GATHER(ret, resolve_host(*p)); - } - } - -diff --git a/src/shared/meson.build b/src/shared/meson.build -index 6fa4216305..7b2a8b5ee2 100644 ---- a/src/shared/meson.build -+++ b/src/shared/meson.build -@@ -185,6 +185,7 @@ shared_sources = files( - 'resize-fs.c', - 'resolve-hook-util.c', - 'resolve-util.c', -+ 'resolve-varlink-util.c', - 'rm-rf.c', - 'seccomp-util.c', - 'securebits-util.c', -diff --git a/src/shared/resolve-varlink-util.c b/src/shared/resolve-varlink-util.c -new file mode 100644 -index 0000000000..3459cfc9d6 ---- /dev/null -+++ b/src/shared/resolve-varlink-util.c -@@ -0,0 +1,107 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+ -+#include "sd-json.h" -+ -+#include "dns-packet.h" -+#include "json-util.h" -+#include "resolve-varlink-util.h" -+ -+void resolve_error_done(ResolveError *error) { -+ if (!error) -+ return; -+ -+ error->ede_msg = mfree(error->ede_msg); -+ error->query_string = mfree(error->query_string); -+ error->result = mfree(error->result); -+} -+ -+int dispatch_resolve_error(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ static const sd_json_dispatch_field resolve_error_dispatch_table[] = { -+ { "rcode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(ResolveError, rcode), 0 }, -+ { "extendedDNSErrorCode", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(ResolveError, ede_rcode), 0 }, -+ { "extendedDNSErrorMessage", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(ResolveError, ede_msg), 0 }, -+ { "queryString", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(ResolveError, query_string), 0 }, -+ { "result", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(ResolveError, result), 0 }, -+ {}, -+ }; -+ ResolveError *ret = ASSERT_PTR(userdata); -+ int r; -+ -+ _cleanup_(resolve_error_done) ResolveError error = { -+ .rcode = _DNS_RCODE_INVALID, -+ .ede_rcode = _DNS_EDE_RCODE_INVALID, -+ }; -+ r = sd_json_dispatch(variant, resolve_error_dispatch_table, flags | SD_JSON_ALLOW_EXTENSIONS, &error); -+ if (r < 0) -+ return r; -+ -+ *ret = TAKE_STRUCT(error); -+ return 0; -+} -+ -+static int dispatch_resolved_address(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ static const sd_json_dispatch_field resolved_address_dispatch_table[] = { -+ { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(ResolvedAddress, ifindex), SD_JSON_RELAX }, -+ { "family", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_address_family, offsetof(ResolvedAddress, family), SD_JSON_MANDATORY }, -+ { "address", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_in_addr_data, offsetof(ResolvedAddress, in_addr), SD_JSON_MANDATORY }, -+ {}, -+ }; -+ ResolvedAddress *ret = ASSERT_PTR(userdata); -+ int r; -+ -+ ResolvedAddress address = {}; -+ r = sd_json_dispatch(variant, resolved_address_dispatch_table, flags & ~SD_JSON_MANDATORY, &address); -+ if (r < 0) -+ return r; -+ -+ if (address.family != address.in_addr.family) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "'%s' address and family are inconsistent.", strna(name)); -+ -+ *ret = TAKE_STRUCT(address); -+ return 0; -+} -+ -+static int dispatch_resolved_address_array(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ ResolveHostnameReply *reply = ASSERT_PTR(userdata); -+ int r; -+ -+ sd_json_variant *v; -+ JSON_VARIANT_ARRAY_FOREACH(v, variant) { -+ if (!GREEDY_REALLOC0(reply->addresses, reply->n_addresses + 1)) -+ return json_log_oom(variant, flags); -+ -+ r = dispatch_resolved_address(name, v, flags, &reply->addresses[reply->n_addresses++]); -+ if (r < 0) -+ return r; -+ } -+ -+ return 0; -+} -+ -+void resolve_hostname_reply_done(ResolveHostnameReply *reply) { -+ if (!reply) -+ return; -+ -+ reply->name = mfree(reply->name); -+ reply->addresses = mfree(reply->addresses); -+ reply->n_addresses = 0; -+} -+ -+int dispatch_resolve_hostname_reply(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { -+ static const sd_json_dispatch_field resolve_hostname_reply_dispatch_table[] = { -+ { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(ResolveHostnameReply, name), SD_JSON_MANDATORY }, -+ { "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(ResolveHostnameReply, flags), SD_JSON_MANDATORY }, -+ { "addresses", SD_JSON_VARIANT_ARRAY, dispatch_resolved_address_array, 0, SD_JSON_MANDATORY }, -+ {}, -+ }; -+ ResolveHostnameReply *ret = ASSERT_PTR(userdata); -+ int r; -+ -+ _cleanup_(resolve_hostname_reply_done) ResolveHostnameReply reply = {}; -+ r = sd_json_dispatch(variant, resolve_hostname_reply_dispatch_table, flags | SD_JSON_ALLOW_EXTENSIONS, &reply); -+ if (r < 0) -+ return r; -+ -+ *ret = TAKE_STRUCT(reply); -+ return 0; -+} -diff --git a/src/shared/resolve-varlink-util.h b/src/shared/resolve-varlink-util.h -new file mode 100644 -index 0000000000..4e94fbe8c6 ---- /dev/null -+++ b/src/shared/resolve-varlink-util.h -@@ -0,0 +1,34 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+#pragma once -+ -+#include "in-addr-util.h" -+#include "shared-forward.h" -+ -+typedef struct ResolveError { -+ int rcode; -+ int ede_rcode; -+ char *ede_msg; -+ char *query_string; -+ char *result; -+} ResolveError; -+ -+void resolve_error_done(ResolveError *error); -+ -+int dispatch_resolve_error(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); -+ -+typedef struct ResolvedAddress { -+ int ifindex; -+ int family; -+ struct in_addr_data in_addr; -+} ResolvedAddress; -+ -+typedef struct ResolveHostnameReply { -+ char *name; -+ uint64_t flags; -+ ResolvedAddress *addresses; -+ size_t n_addresses; -+} ResolveHostnameReply; -+ -+void resolve_hostname_reply_done(ResolveHostnameReply *reply); -+ -+int dispatch_resolve_hostname_reply(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); --- -2.55.0 - diff --git a/extra-repos/systemd/systemd/42275.patch b/extra-repos/systemd/systemd/42275.patch deleted file mode 100644 index 385e3514c..000000000 --- a/extra-repos/systemd/systemd/42275.patch +++ /dev/null @@ -1,267 +0,0 @@ -From 58fc96bb716cdd5ec17796914283720ef9f28240 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Sat, 23 May 2026 17:42:55 -0700 -Subject: [PATCH 1/3] pam_systemd: add inhibit= and inhibit-why= module - arguments to parse_argv - -This adds two new module arguments to parse_argv: - -1) inhibit= takes a colon-separated list of inhibitor lock types to acquire - -2) inhibit-why= takes an optional human-readable reason string. - -Both are currently parsed but are unused until a later commit. ---- - src/login/pam_systemd.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c -index 9bdd147db4d08..aeb917977bdbf 100644 ---- a/src/login/pam_systemd.c -+++ b/src/login/pam_systemd.c -@@ -117,6 +117,8 @@ static int parse_argv( - const char **type, - const char **desktop, - const char **area, -+ const char **inhibit_what, -+ const char **inhibit_why, - bool *debug, - uint64_t *default_capability_bounding_set, - uint64_t *default_capability_ambient_set) { -@@ -148,6 +150,12 @@ static int parse_argv( - sym_pam_syslog(pamh, LOG_WARNING, "Area name specified among PAM module parameters is not valid, ignoring: %s", p); - else if (area) - *area = p; -+ } else if ((p = startswith(argv[i], "inhibit="))) { -+ if (inhibit_what) -+ *inhibit_what = p; -+ } else if ((p = startswith(argv[i], "inhibit-why="))) { -+ if (inhibit_why) -+ *inhibit_why = p; - - } else if (streq(argv[i], "debug")) { - if (debug) -@@ -1755,7 +1763,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( - pam_log_setup(); - - uint64_t default_capability_bounding_set = CAP_MASK_UNSET, default_capability_ambient_set = CAP_MASK_UNSET; -- const char *class_pam = NULL, *type_pam = NULL, *desktop_pam = NULL, *area_pam = NULL; -+ const char *class_pam = NULL, *type_pam = NULL, *desktop_pam = NULL, *area_pam = NULL, *inhibit_what = NULL, *inhibit_why = NULL; - bool debug = false; - if (parse_argv(pamh, - argc, argv, -@@ -1763,6 +1771,8 @@ _public_ PAM_EXTERN int pam_sm_open_session( - &type_pam, - &desktop_pam, - &area_pam, -+ &inhibit_what, -+ &inhibit_why, - &debug, - &default_capability_bounding_set, - &default_capability_ambient_set) < 0) -@@ -1859,6 +1869,8 @@ _public_ PAM_EXTERN int pam_sm_close_session( - /* type= */ NULL, - /* desktop= */ NULL, - /* area= */ NULL, -+ /* inhibit_what= */ NULL, -+ /* inhibit_why= */ NULL, - &debug, - /* default_capability_bounding_set= */ NULL, - /* default_capability_ambient_set= */ NULL) < 0) - -From 179b7c2ab5491e7772c51acc33abd0a991be9851 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Sat, 23 May 2026 20:06:31 -0700 -Subject: [PATCH 2/3] pam_systemd: acquire inhibit lock when inhibit= is - specified - -This adds a new function, acquire_inhibit_lock, that takes a logind -inhibitor lock for the duration of the PAM session. The lock fd is -stored in PAM data with pam_cleanup_close. In pam_sm_close_session, the -lock is released explicitly by passing NULL to pam_set_data, which -triggers the registered cleanup function immediately rather than waiting -for pam_end. - -The inhibit type and reason string can also be configured via the -XDG_SESSION_INHIBIT and XDG_SESSION_INHIBIT_WHY environment variables, -which take precedence over the module arguments. - -Fixes: #20654 ---- - src/login/pam_systemd.c | 60 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 60 insertions(+) - -diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c -index aeb917977bdbf..06d19607b2f9c 100644 ---- a/src/login/pam_systemd.c -+++ b/src/login/pam_systemd.c -@@ -1747,6 +1747,57 @@ static int close_osc_context(pam_handle_t *pamh, bool debug) { - return PAM_SUCCESS; - } - -+static int acquire_inhibit_lock( -+ pam_handle_t *pamh, -+ const char *inhibit_what, -+ const char *inhibit_why, -+ bool debug) { -+ -+ _cleanup_(pam_bus_data_disconnectp) PamBusData *d = NULL; -+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; -+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; -+ const char *service = NULL; -+ int r; -+ -+ assert(pamh); -+ assert(inhibit_what); -+ -+ r = pam_acquire_bus_connection(pamh, "pam-systemd", debug, &bus, &d); -+ if (r != PAM_SUCCESS) -+ return r; -+ -+ (void) sym_pam_get_item(pamh, PAM_SERVICE, (const void **) &service); -+ -+ r = bus_call_method(bus, bus_login_mgr, "Inhibit", &error, &reply, "ssss", -+ inhibit_what, -+ service ?: "pam_systemd", -+ inhibit_why ?: "Active PAM session", -+ "block"); -+ if (r < 0) { -+ sym_pam_syslog(pamh, LOG_WARNING, "Failed to acquire inhibit lock: %s", bus_error_message(&error, r)); -+ return PAM_SESSION_ERR; -+ } -+ -+ int raw_fd; -+ r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &raw_fd); -+ if (r < 0) -+ return pam_bus_log_parse_error(pamh, r); -+ -+ _cleanup_close_ int fd = fcntl(raw_fd, F_DUPFD_CLOEXEC, 3); -+ if (fd < 0) -+ return pam_syslog_errno(pamh, LOG_ERR, errno, "Failed to dup inhibit lock fd: %m"); -+ -+ r = sym_pam_set_data(pamh, "systemd.inhibit-fd", FD_TO_PTR(fd), pam_cleanup_close); -+ if (r != PAM_SUCCESS) -+ return pam_syslog_pam_error(pamh, LOG_ERR, r, -+ "Failed to store inhibit lock fd: @PAMERR@"); -+ TAKE_FD(fd); -+ -+ pam_debug_syslog(pamh, debug, "Acquired inhibit lock for '%s'.", inhibit_what); -+ return PAM_SUCCESS; -+} -+ - _public_ PAM_EXTERN int pam_sm_open_session( - pam_handle_t *pamh, - int flags, -@@ -1803,6 +1854,8 @@ _public_ PAM_EXTERN int pam_sm_open_session( - c.desktop = getenv_harder(pamh, "XDG_SESSION_DESKTOP", desktop_pam); - c.area = getenv_harder(pamh, "XDG_AREA", area_pam); - c.incomplete = getenv_harder_bool(pamh, "XDG_SESSION_INCOMPLETE", false); -+ inhibit_what = getenv_harder(pamh, "XDG_SESSION_INHIBIT", inhibit_what); -+ inhibit_why = getenv_harder(pamh, "XDG_SESSION_INHIBIT_WHY", inhibit_why); - - const char *extra_device_access = getenv_harder(pamh, "XDG_SESSION_EXTRA_DEVICE_ACCESS", NULL); - if (extra_device_access) { -@@ -1828,6 +1881,11 @@ _public_ PAM_EXTERN int pam_sm_open_session( - if (r != PAM_SUCCESS) - return r; - -+ if (inhibit_what) -+ /* Failure to acquire the inhibit lock is not fatal, session setup should proceed -+ * regardless. */ -+ (void) acquire_inhibit_lock(pamh, inhibit_what, inhibit_why, debug); -+ - r = import_shell_credentials(pamh, debug); - if (r != PAM_SUCCESS) - return r; -@@ -1880,6 +1938,8 @@ _public_ PAM_EXTERN int pam_sm_close_session( - - (void) close_osc_context(pamh, debug); - -+ (void) sym_pam_set_data(pamh, "systemd.inhibit-fd", NULL, NULL); -+ - id = sym_pam_getenv(pamh, "XDG_SESSION_ID"); - if (id) { - _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL; - -From 87fa1c28a5f084b5837e58baf5d6a7482c02f382 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Sat, 23 May 2026 19:53:56 -0700 -Subject: [PATCH 3/3] pam_systemd: document inhibit= and inhibit-why= options - ---- - man/pam_systemd.xml | 47 +++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - -diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml -index 5482ced067745..bb464556954f0 100644 ---- a/man/pam_systemd.xml -+++ b/man/pam_systemd.xml -@@ -238,6 +238,33 @@ - - - -+ -+ inhibit= -+ -+ Takes a colon-separated list of inhibitor lock types to acquire for the duration of -+ the session. The XDG_SESSION_INHIBIT environment variable (see below) takes -+ precedence. Inhibitor locks prevent the system from performing certain actions, such as sleeping. -+ The supported lock types are the same as for the -+ systemd-inhibit1 -+ command, e.g. shutdown, sleep, idle. -+ If not set, no inhibitor lock is acquired. The lock is taken in block mode, the requested -+ actions are fully inhibited as long as the session is active. -+ -+ -+ -+ -+ -+ inhibit-why= -+ -+ Takes a short human-readable string describing the reason for the inhibitor lock -+ acquired via inhibit=. The XDG_SESSION_INHIBIT_WHY -+ environment variable (see below) takes precedence. Defaults to Active PAM session -+ if not set. Only has an effect if inhibit= or -+ XDG_SESSION_INHIBIT is set. -+ -+ -+ -+ - - default-capability-bounding-set= - default-capability-ambient-set= -@@ -414,6 +441,25 @@ - - - -+ -+ -+ $XDG_SESSION_INHIBIT -+ -+ The inhibitor lock types to acquire for the duration of the session, as a -+ colon-separated list. This may be used instead of inhibit= on the module -+ parameter line. -+ -+ -+ -+ -+ -+ $XDG_SESSION_INHIBIT_WHY -+ -+ The reason string for the inhibitor lock. This may be used instead of -+ inhibit-why= on the module parameter line. -+ -+ -+ - - - If not set, pam_systemd will initialize -@@ -528,6 +574,7 @@ session required pam_unix.so - logind.conf5 - loginctl1 - pam_systemd_home8 -+ systemd-inhibit1 - pam.conf5 - pam.d5 - pam8 diff --git a/extra-repos/systemd/systemd/43380.patch b/extra-repos/systemd/systemd/43380.patch deleted file mode 100644 index 8814f9dd0..000000000 --- a/extra-repos/systemd/systemd/43380.patch +++ /dev/null @@ -1,418 +0,0 @@ -From 98e7cc36f019e48a3f20db9787ccd38d899957f5 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Thu, 13 Aug 2026 13:51:30 -0700 -Subject: [PATCH 1/4] timesyncd: resolve NTP hostnames through resolved's - varlink interface - -With DNSSEC on, resolved can't validate anything until the clock is -right, and without an RTC the only thing that fixes the clock is talking -to the NTP servers we're trying to resolve. On glibc the timesyncd unit -sets SYSTEMD_NSS_RESOLVE_VALIDATE=0 and nss-resolve turns that into a -per-query flag, which breaks the chicken/egg. musl (and other systems -not using nss-resolve) have no NSS, so nothing reads it there and we're -stuck. - -So talk to resolved directly when it's there, and pass -SD_RESOLVED_NO_VALIDATE until we've synced the clock ourselves. -NTP-related lookups after that are validated normally, which is better -than what we get from nss. If resolved isn't around we just keep using -getaddrinfo(). - -The reply handler duplicates the tail of the getaddrinfo handler, since -the two differ in how they report failures. Varlink discards what the -callback returns, so it has to move on to the next host itself. - -This also drops SYSTEMD_NSS_RESOLVE_VALIDATE=0 from the unit because -nss-resolve talks to resolved over the same socket we do, so the -getaddrinfo() path is only ever taken when resolved is unreachable, and -then nothing validates anyway. ---- - src/timesync/timesyncd-manager.c | 136 +++++++++++++++++++++++++++-- - src/timesync/timesyncd-manager.h | 1 + - units/systemd-timesyncd.service.in | 4 - - 3 files changed, 132 insertions(+), 9 deletions(-) - -diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c -index b0f22516dfe3..7b2ed4f831a0 100644 ---- a/src/timesync/timesyncd-manager.c -+++ b/src/timesync/timesyncd-manager.c -@@ -10,8 +10,10 @@ - - #include "sd-bus.h" - #include "sd-daemon.h" -+#include "sd-json.h" - #include "sd-messages.h" - #include "sd-network.h" -+#include "sd-varlink.h" - - #include "alloc-util.h" - #include "clock-util.h" -@@ -23,6 +25,7 @@ - #include "format-util.h" - #include "fs-util.h" - #include "hashmap.h" -+#include "in-addr-util.h" - #include "list.h" - #include "log.h" - #include "logarithm.h" -@@ -30,6 +33,8 @@ - #include "random-util.h" - #include "ratelimit.h" - #include "resolve-private.h" -+#include "resolve-varlink-util.h" -+#include "resolved-def.h" - #include "socket-util.h" - #include "string-util.h" - #include "strv.h" -@@ -780,6 +785,119 @@ static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct ad - return manager_begin(m); - } - -+static int manager_resolve_varlink_reply( -+ sd_varlink *link, -+ sd_json_variant *parameters, -+ const char *error_id, -+ sd_varlink_reply_flags_t flags, -+ void *userdata) { -+ -+ Manager *m = ASSERT_PTR(userdata); -+ int r; -+ -+ assert(m->current_server_name); -+ -+ _unused_ _cleanup_(sd_varlink_unrefp) sd_varlink *link_free = TAKE_PTR(m->resolve_varlink); -+ -+ if (!isempty(error_id)) { -+ log_debug("Failed to resolve %s: %s", m->current_server_name->string, error_id); -+ -+ /* Try next one */ -+ return manager_connect(m); -+ } -+ -+ _cleanup_(resolve_hostname_reply_done) ResolveHostnameReply reply = {}; -+ r = dispatch_resolve_hostname_reply(/* name = */ NULL, parameters, SD_JSON_LOG, &reply); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to parse reply for %s, ignoring: %m", m->current_server_name->string); -+ -+ return manager_connect(m); -+ } -+ -+ FOREACH_ARRAY(entry, reply.addresses, reply.n_addresses) { -+ _cleanup_free_ char *pretty = NULL; -+ union sockaddr_union sa = {}; -+ ServerAddress *a; -+ -+ if (!IN_SET(entry->family, AF_INET, AF_INET6)) { -+ log_debug("Ignoring unsuitable address protocol for %s.", m->current_server_name->string); -+ continue; -+ } -+ -+ r = sockaddr_set_in_addr(&sa, entry->family, &entry->in_addr.address, 123); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to convert address for %s, trying next host: %m", m->current_server_name->string); -+ return manager_connect(m); -+ } -+ -+ /* Only link-local addresses need a scope, setting it on a global one pins us to one interface. */ -+ if (entry->family == AF_INET6 && in6_addr_is_link_local(&entry->in_addr.address.in6)) -+ sa.in6.sin6_scope_id = entry->ifindex; -+ -+ r = server_address_new(m->current_server_name, &a, &sa, sockaddr_len(&sa)); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to add server address, trying next host: %m"); -+ return manager_connect(m); -+ } -+ -+ (void) server_address_pretty(a, &pretty); -+ log_debug("Resolved address %s for %s.", strna(pretty), m->current_server_name->string); -+ } -+ -+ if (!m->current_server_name->addresses) { -+ log_error("Failed to find suitable address for host %s.", m->current_server_name->string); -+ -+ /* Try next host */ -+ return manager_connect(m); -+ } -+ -+ manager_set_server_address(m, m->current_server_name->addresses); -+ -+ return manager_begin(m); -+} -+ -+/* Resolve the current server name through resolved's Varlink interface. This returns 0 if resolved is -+ * unavailable */ -+static int manager_resolve_varlink(Manager *m) { -+ _cleanup_(sd_varlink_close_unrefp) sd_varlink *link = NULL; -+ int r; -+ -+ assert(m); -+ assert(m->current_server_name); -+ -+ r = sd_varlink_connect_address(&link, "/run/systemd/resolve/io.systemd.Resolve"); -+ if (r < 0) { -+ log_debug_errno(r, "Failed to connect to systemd-resolved, using getaddrinfo(): %m"); -+ return 0; -+ } -+ -+ (void) sd_varlink_set_description(link, "timesyncd-resolve"); -+ (void) sd_varlink_set_relative_timeout(link, SD_RESOLVED_QUERY_TIMEOUT_USEC); -+ -+ r = sd_varlink_attach_event(link, m->event, SD_EVENT_PRIORITY_NORMAL); -+ if (r < 0) -+ return log_error_errno(r, "Failed to attach Varlink connection to event loop: %m"); -+ -+ r = sd_varlink_bind_reply(link, manager_resolve_varlink_reply); -+ if (r < 0) -+ return log_error_errno(r, "Failed to bind Varlink reply callback: %m"); -+ -+ sd_varlink_set_userdata(link, m); -+ -+ /* Ask resolved to skip DNSSEC validation as long as our clock is not synchronized yet. */ -+ r = sd_varlink_invokebo( -+ link, -+ "io.systemd.Resolve.ResolveHostname", -+ SD_JSON_BUILD_PAIR_STRING("name", m->current_server_name->string), -+ SD_JSON_BUILD_PAIR_CONDITION(!socket_ipv6_is_enabled(), "family", SD_JSON_BUILD_INTEGER(AF_INET)), -+ SD_JSON_BUILD_PAIR_UNSIGNED("flags", m->synchronized ? 0 : SD_RESOLVED_NO_VALIDATE)); -+ if (r < 0) -+ return log_error_errno(r, "Failed to call ResolveHostname(): %m"); -+ -+ m->resolve_varlink = TAKE_PTR(link); -+ return 1; -+} -+ - static int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) { - Manager *m = ASSERT_PTR(userdata); - -@@ -868,15 +986,22 @@ int manager_connect(Manager *m) { - manager_set_server_name(m, f); - } - -- /* Tell the resolver to reread /etc/resolv.conf, in -- * case it changed. */ -- res_init(); -- - /* Flush out any previously resolved addresses */ - server_name_flush_addresses(m->current_server_name); - - log_debug("Resolving %s...", m->current_server_name->string); - -+ /* Prefer resolved's varlink interface. If that's unavailable, then fall through to getaddrinfo below. */ -+ r = manager_resolve_varlink(m); -+ if (r < 0) -+ return r; -+ if (r > 0) -+ return 1; -+ -+ /* Tell the resolver to reread /etc/resolv.conf, in -+ * case it changed. */ -+ res_init(); -+ - struct addrinfo hints = { - .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG, - .ai_socktype = SOCK_DGRAM, -@@ -901,6 +1026,7 @@ void manager_disconnect(Manager *m) { - assert(m); - - m->resolve_query = sd_resolve_query_unref(m->resolve_query); -+ m->resolve_varlink = sd_varlink_close_unref(m->resolve_varlink); - - m->event_timer = sd_event_source_unref(m->event_timer); - -@@ -1035,7 +1161,7 @@ static bool manager_is_connected(Manager *m) { - - /* Return true when the manager is sending a request, resolving a server name, or - * in a poll interval. */ -- return m->server_socket >= 0 || m->resolve_query || m->event_timer; -+ return m->server_socket >= 0 || m->resolve_query || m->resolve_varlink || m->event_timer; - } - - static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -diff --git a/src/timesync/timesyncd-manager.h b/src/timesync/timesyncd-manager.h -index 9966b64ac697..8c1e30f48fd5 100644 ---- a/src/timesync/timesyncd-manager.h -+++ b/src/timesync/timesyncd-manager.h -@@ -41,6 +41,7 @@ typedef struct Manager { - - /* peer */ - sd_resolve_query *resolve_query; -+ sd_varlink *resolve_varlink; - sd_event_source *event_receive; - ServerName *current_server_name; - ServerAddress *current_server_address; -diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in -index 560bcee92f4c..bc64e2414007 100644 ---- a/units/systemd-timesyncd.service.in -+++ b/units/systemd-timesyncd.service.in -@@ -22,10 +22,6 @@ Wants=time-set.target - AmbientCapabilities=CAP_SYS_TIME - BusName=org.freedesktop.timesync1 - CapabilityBoundingSet=CAP_SYS_TIME --# Turn off DNSSEC validation for hostname look-ups, since those need the --# correct time to work, but we likely won't acquire that without NTP. Let's --# break this chicken-and-egg cycle here. --Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0 - ExecStart={{LIBEXECDIR}}/systemd-timesyncd - LockPersonality=yes - MemoryDenyWriteExecute=yes - -From 6279910be7b26239ce7eb442b227a879cb66e24e Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Thu, 13 Aug 2026 14:01:59 -0700 -Subject: [PATCH 2/4] timesyncd: order after systemd-resolved - -Our first resolve happens way before sockets.target, and -systemd-resolved-varlink.socket has no ordering of its own, so there's -nothing making sure the socket is listening by then. Without this the -connect fails and we quietly fall back to getaddrinfo(), which is exactly -the case the varlink path is there for. - -Order after both the service and the socket since either one is enough -on its own but neither covers every install situation. For example -resolved binds the socket itself when nothing hands it one, and on -systems where only the socket is enabled the service isn't started at -boot at all. ---- - units/systemd-timesyncd.service.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in -index bc64e2414007..c1809710477b 100644 ---- a/units/systemd-timesyncd.service.in -+++ b/units/systemd-timesyncd.service.in -@@ -13,7 +13,7 @@ Documentation=man:systemd-timesyncd.service(8) - ConditionCapability=CAP_SYS_TIME - ConditionVirtualization=!container - DefaultDependencies=no --After=systemd-sysusers.service -+After=systemd-sysusers.service systemd-resolved.service systemd-resolved-varlink.socket - Before=time-set.target sysinit.target shutdown.target - Conflicts=shutdown.target - Wants=time-set.target - -From 8027ff6ecd12058d08e0bb6dce046b86828f7dd4 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Fri, 14 Aug 2026 15:19:56 -0700 -Subject: [PATCH 3/4] timesyncd: don't ask for AAAA when IPv6 is disabled - -ipv6_is_supported only tells us the kernel has IPv6, not that -it's usable. ipv6_is_enabled also checks the sysctl that turns -it off, so we stop resolving addresses we can't use. ---- - src/timesync/timesyncd-manager.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c -index 7b2ed4f831a0..4b3978bebc7f 100644 ---- a/src/timesync/timesyncd-manager.c -+++ b/src/timesync/timesyncd-manager.c -@@ -1005,7 +1005,7 @@ int manager_connect(Manager *m) { - struct addrinfo hints = { - .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG, - .ai_socktype = SOCK_DGRAM, -- .ai_family = socket_ipv6_is_supported() ? AF_UNSPEC : AF_INET, -+ .ai_family = socket_ipv6_is_enabled() ? AF_UNSPEC : AF_INET, - }; - - r = resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, NULL, m); - -From d52a6931643a384b1184b1c30badb739ff885f78 Mon Sep 17 00:00:00 2001 -From: Clayton Craft -Date: Fri, 14 Aug 2026 14:25:01 -0700 -Subject: [PATCH 4/4] test: cover both of timesyncd's resolver paths - -This checks that we resolve through resolved when it's running, and fall back -to getaddrinfo when it isn't. ---- - test/units/TEST-45-TIMEDATE.sh | 71 ++++++++++++++++++++++++++++++++++ - 1 file changed, 71 insertions(+) - -diff --git a/test/units/TEST-45-TIMEDATE.sh b/test/units/TEST-45-TIMEDATE.sh -index 820c3ae9f52e..0af99fc96ce7 100755 ---- a/test/units/TEST-45-TIMEDATE.sh -+++ b/test/units/TEST-45-TIMEDATE.sh -@@ -248,6 +248,19 @@ assert_timesyncd_state() { - return 1 - } - -+assert_timesyncd_log() { -+ local cursor="${1:?}" -+ local match="${2:?}" -+ -+ for _ in {0..29}; do -+ journalctl --sync -+ journalctl -q -u systemd-timesyncd.service --after-cursor="$(<"$cursor")" --grep "$match" >/dev/null && return 0 -+ sleep .5 -+ done -+ -+ return 1 -+} -+ - testcase_ntp() { - # timesyncd has ConditionVirtualization=!container by default; drop/mock that for testing - if systemd-detect-virt --container --quiet; then -@@ -409,6 +422,64 @@ EOF - rm -f /run/systemd/network/ntp99.* - } - -+teardown_timesyncd_resolve() { -+ set +eu -+ -+ systemctl start systemd-resolved-varlink.socket -+ systemctl start systemd-resolved.service -+ -+ rm -rf /run/systemd/system/systemd-timesyncd.service.d -+ systemctl daemon-reload -+ systemctl stop systemd-timesyncd -+} -+ -+testcase_timesyncd_resolve() { -+ local cursor -+ -+ if systemd-detect-virt -cq; then -+ echo "This test case requires a VM, skipping..." -+ return 0 -+ fi -+ -+ if ! command -v resolvectl >/dev/null; then -+ echo "This test requires systemd-resolved, skipping..." -+ return 0 -+ fi -+ -+ trap teardown_timesyncd_resolve RETURN -+ -+ mkdir -p /run/systemd/system/systemd-timesyncd.service.d -+ cat >/run/systemd/system/systemd-timesyncd.service.d/10-debug.conf <