From f6e4aa7b0370c8b39739e9d5dda780932489507a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Nov 2022 12:53:07 +0900 Subject: [PATCH 1/6] resolve: drop redundant call of socket_ipv6_is_supported() As link_relevant() is called with AF_INET6, which returns true only when the link has at least one relevant IPv6 address. --- src/resolve/resolved-link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 5b34677cbe..94ad939c5e 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -152,8 +152,7 @@ void link_allocate_scopes(Link *l) { if (link_relevant(l, AF_INET6, true) && l->llmnr_support != RESOLVE_SUPPORT_NO && - l->manager->llmnr_support != RESOLVE_SUPPORT_NO && - socket_ipv6_is_supported()) { + l->manager->llmnr_support != RESOLVE_SUPPORT_NO) { if (!l->llmnr_ipv6_scope) { r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6); if (r < 0) From bce459e3275249574f2142236275b2c33a9f88e3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Nov 2022 12:53:07 +0900 Subject: [PATCH 2/6] resolve: introduce link_get_llmnr_support() and link_get_mdns_support() --- src/resolve/resolved-link.c | 49 ++++++++++++++++++++++--------------- src/resolve/resolved-link.h | 3 +++ src/shared/resolve-util.h | 3 ++- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 94ad939c5e..d41f6f3e54 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -140,8 +140,7 @@ void link_allocate_scopes(Link *l) { l->unicast_scope = dns_scope_free(l->unicast_scope); if (link_relevant(l, AF_INET, true) && - l->llmnr_support != RESOLVE_SUPPORT_NO && - l->manager->llmnr_support != RESOLVE_SUPPORT_NO) { + link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) { if (!l->llmnr_ipv4_scope) { r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET); if (r < 0) @@ -151,8 +150,7 @@ void link_allocate_scopes(Link *l) { l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope); if (link_relevant(l, AF_INET6, true) && - l->llmnr_support != RESOLVE_SUPPORT_NO && - l->manager->llmnr_support != RESOLVE_SUPPORT_NO) { + link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) { if (!l->llmnr_ipv6_scope) { r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6); if (r < 0) @@ -162,8 +160,7 @@ void link_allocate_scopes(Link *l) { l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope); if (link_relevant(l, AF_INET, true) && - l->mdns_support != RESOLVE_SUPPORT_NO && - l->manager->mdns_support != RESOLVE_SUPPORT_NO) { + link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) { if (!l->mdns_ipv4_scope) { r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET); if (r < 0) @@ -173,8 +170,7 @@ void link_allocate_scopes(Link *l) { l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope); if (link_relevant(l, AF_INET6, true) && - l->mdns_support != RESOLVE_SUPPORT_NO && - l->manager->mdns_support != RESOLVE_SUPPORT_NO) { + link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) { if (!l->mdns_ipv6_scope) { r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6); if (r < 0) @@ -191,8 +187,7 @@ void link_add_rrs(Link *l, bool force_remove) { link_address_add_rrs(a, force_remove); if (!force_remove && - l->mdns_support == RESOLVE_SUPPORT_YES && - l->manager->mdns_support == RESOLVE_SUPPORT_YES) { + link_get_mdns_support(l) == RESOLVE_SUPPORT_YES) { if (l->mdns_ipv4_scope) { r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope); @@ -651,13 +646,13 @@ int link_update(Link *l) { if (r < 0) return r; - if (l->llmnr_support != RESOLVE_SUPPORT_NO) { + if (link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) { r = manager_llmnr_start(l->manager); if (r < 0) return r; } - if (l->mdns_support != RESOLVE_SUPPORT_NO) { + if (link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) { r = manager_mdns_start(l->manager); if (r < 0) return r; @@ -802,6 +797,24 @@ bool link_dnssec_supported(Link *l) { return true; } +ResolveSupport link_get_llmnr_support(Link *link) { + assert(link); + assert(link->manager); + + /* This provides the effective LLMNR support level for the link, instead of the 'internal' per-link setting. */ + + return MIN(link->llmnr_support, link->manager->llmnr_support); +} + +ResolveSupport link_get_mdns_support(Link *link) { + assert(link); + assert(link->manager); + + /* This provides the effective mDNS support level for the link, instead of the 'internal' per-link setting. */ + + return MIN(link->mdns_support, link->manager->mdns_support); +} + int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) { LinkAddress *a; @@ -885,8 +898,7 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) { if (!force_remove && link_address_relevant(a, true) && a->link->llmnr_ipv4_scope && - a->link->llmnr_support == RESOLVE_SUPPORT_YES && - a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { + link_get_llmnr_support(a->link) == RESOLVE_SUPPORT_YES) { if (!a->link->manager->llmnr_host_ipv4_key) { a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname); @@ -939,8 +951,7 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) { if (!force_remove && link_address_relevant(a, true) && a->link->mdns_ipv4_scope && - a->link->mdns_support == RESOLVE_SUPPORT_YES && - a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) { + link_get_mdns_support(a->link) == RESOLVE_SUPPORT_YES) { if (!a->link->manager->mdns_host_ipv4_key) { a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname); if (!a->link->manager->mdns_host_ipv4_key) { @@ -995,8 +1006,7 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) { if (!force_remove && link_address_relevant(a, true) && a->link->llmnr_ipv6_scope && - a->link->llmnr_support == RESOLVE_SUPPORT_YES && - a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { + link_get_llmnr_support(a->link) == RESOLVE_SUPPORT_YES) { if (!a->link->manager->llmnr_host_ipv6_key) { a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname); @@ -1049,8 +1059,7 @@ void link_address_add_rrs(LinkAddress *a, bool force_remove) { if (!force_remove && link_address_relevant(a, true) && a->link->mdns_ipv6_scope && - a->link->mdns_support == RESOLVE_SUPPORT_YES && - a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) { + link_get_mdns_support(a->link) == RESOLVE_SUPPORT_YES) { if (!a->link->manager->mdns_host_ipv6_key) { a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname); diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index b5299e0b5b..d2043a1000 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -104,6 +104,9 @@ bool link_dnssec_supported(Link *l); DnsOverTlsMode link_get_dns_over_tls_mode(Link *l); +ResolveSupport link_get_llmnr_support(Link *link); +ResolveSupport link_get_mdns_support(Link *link); + int link_save_user(Link *l); int link_load_user(Link *l); void link_remove_user(Link *l); diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h index d9ab387301..e58173d864 100644 --- a/src/shared/resolve-util.h +++ b/src/shared/resolve-util.h @@ -25,10 +25,11 @@ typedef enum ResolveSupport ResolveSupport; typedef enum DnssecMode DnssecMode; typedef enum DnsOverTlsMode DnsOverTlsMode; +/* Do not change the order, see link_get_llmnr_support() or link_get_mdns_support(). */ enum ResolveSupport { RESOLVE_SUPPORT_NO, - RESOLVE_SUPPORT_YES, RESOLVE_SUPPORT_RESOLVE, + RESOLVE_SUPPORT_YES, _RESOLVE_SUPPORT_MAX, _RESOLVE_SUPPORT_INVALID = -EINVAL, }; From dc167037c4e7407bf597a65224c736874abeca11 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Nov 2022 12:53:07 +0900 Subject: [PATCH 3/6] resolve: provide effective supporting levels of mDNS and LLMNR The per-link settings are ignored if the feature is disabled by the global setting. Let's announce the effective level, to make not users confused. Closes #24863. --- src/resolve/resolved-link-bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index 5b1096daf6..9b6d14f20c 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -22,6 +22,8 @@ static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported); static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string); +static BUS_DEFINE_PROPERTY_GET2(property_get_llmnr_support, "s", Link, link_get_llmnr_support, resolve_support_to_string); +static BUS_DEFINE_PROPERTY_GET2(property_get_mdns_support, "s", Link, link_get_mdns_support, resolve_support_to_string); static int property_get_dns_over_tls_mode( sd_bus *bus, @@ -864,8 +866,8 @@ static const sd_bus_vtable link_vtable[] = { SD_BUS_PROPERTY("CurrentDNSServerEx", "(iayqs)", property_get_current_dns_server_ex, offsetof(Link, current_dns_server), 0), SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0), SD_BUS_PROPERTY("DefaultRoute", "b", property_get_default_route, 0, 0), - SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0), - SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0), + SD_BUS_PROPERTY("LLMNR", "s", property_get_llmnr_support, 0, 0), + SD_BUS_PROPERTY("MulticastDNS", "s", property_get_mdns_support, 0, 0), SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0), SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0), SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0), From c38a03df4af78721f45947ffa2013554d81954a4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Nov 2022 13:11:55 +0900 Subject: [PATCH 4/6] resolvectl: warn if the global mDNS or LLMNR support level is lower than the requested one --- src/resolve/resolvectl.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index dd0a8e121e..c76ab1b018 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -33,6 +33,7 @@ #include "pretty-print.h" #include "process-util.h" #include "resolvconf-compat.h" +#include "resolve-util.h" #include "resolvectl.h" #include "resolved-def.h" #include "resolved-dns-packet.h" @@ -2277,6 +2278,8 @@ static int verb_default_route(int argc, char **argv, void *userdata) { static int verb_llmnr(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *global_llmnr_support_str = NULL; + ResolveSupport global_llmnr_support, llmnr_support; sd_bus *bus = ASSERT_PTR(userdata); int r; @@ -2292,6 +2295,22 @@ static int verb_llmnr(int argc, char **argv, void *userdata) { if (argc < 3) return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL); + llmnr_support = resolve_support_from_string(argv[2]); + if (llmnr_support < 0) + return log_error_errno(llmnr_support, "Invalid LLMNR setting: %s", argv[2]); + + r = bus_get_property_string(bus, bus_resolve_mgr, "LLMNR", &error, &global_llmnr_support_str); + if (r < 0) + return log_error_errno(r, "Failed to get the global LLMNR support state: %s", bus_error_message(&error, r)); + + global_llmnr_support = resolve_support_from_string(global_llmnr_support_str); + if (global_llmnr_support < 0) + return log_error_errno(global_llmnr_support, "Received invalid global LLMNR setting: %s", global_llmnr_support_str); + + if (global_llmnr_support < llmnr_support) + log_warning("Setting LLMNR support level \"%s\" for \"%s\", but the global support level is \"%s\".", + argv[2], arg_ifname, global_llmnr_support_str); + r = bus_call_method(bus, bus_resolve_mgr, "SetLinkLLMNR", &error, NULL, "is", arg_ifindex, argv[2]); if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { sd_bus_error_free(&error); @@ -2311,6 +2330,8 @@ static int verb_llmnr(int argc, char **argv, void *userdata) { static int verb_mdns(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *global_mdns_support_str = NULL; + ResolveSupport global_mdns_support, mdns_support; sd_bus *bus = ASSERT_PTR(userdata); int r; @@ -2326,6 +2347,22 @@ static int verb_mdns(int argc, char **argv, void *userdata) { if (argc < 3) return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL); + mdns_support = resolve_support_from_string(argv[2]); + if (mdns_support < 0) + return log_error_errno(mdns_support, "Invalid mDNS setting: %s", argv[2]); + + r = bus_get_property_string(bus, bus_resolve_mgr, "MulticastDNS", &error, &global_mdns_support_str); + if (r < 0) + return log_error_errno(r, "Failed to get the global mDNS support state: %s", bus_error_message(&error, r)); + + global_mdns_support = resolve_support_from_string(global_mdns_support_str); + if (global_mdns_support < 0) + return log_error_errno(global_mdns_support, "Received invalid global mDNS setting: %s", global_mdns_support_str); + + if (global_mdns_support < mdns_support) + log_warning("Setting mDNS support level \"%s\" for \"%s\", but the global support level is \"%s\".", + argv[2], arg_ifname, global_mdns_support_str); + r = bus_call_method(bus, bus_resolve_mgr, "SetLinkMulticastDNS", &error, NULL, "is", arg_ifindex, argv[2]); if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { sd_bus_error_free(&error); From e4b3f0dfe91ae0b95f30594c7671be39c0a599b1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 10 Nov 2022 15:51:30 +0900 Subject: [PATCH 5/6] test: create config under /run --- test/units/testsuite-75.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index 04a8b6e9cc..53ceced641 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -79,11 +79,13 @@ DNSSEC=allow-downgrade DNS=10.0.0.1 EOF +mkdir -p /run/systemd/resolved.conf.d { + echo "[Resolve]" echo "FallbackDNS=" echo "DNSSEC=allow-downgrade" echo "DNSOverTLS=opportunistic" -} >>/etc/systemd/resolved.conf +} >/run/systemd/resolved.conf.d/test.conf ln -svf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf # Override the default NTA list, which turns off DNSSEC validation for (among # others) the test. domain From b77899af0d75ea59c35ba454d869fa759fe7b3a1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 10 Nov 2022 15:52:57 +0900 Subject: [PATCH 6/6] test: add tests for mDNS and LLMNR settings --- test/units/testsuite-75.sh | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index 53ceced641..1a656fcdc1 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -55,6 +55,79 @@ echo nameserver 10.0.3.1 10.0.3.2 | "$RESOLVCONF" -a hoge.inet.ipsec.192.168.35 echo nameserver 10.0.3.3 10.0.3.4 | "$RESOLVCONF" -a hoge.foo.dhcp assert_in '10.0.3.1 10.0.3.2' "$(resolvectl dns hoge)" assert_in '10.0.3.3 10.0.3.4' "$(resolvectl dns hoge.foo)" + +# Tests for mDNS and LLMNR settings +mkdir -p /run/systemd/resolved.conf.d +{ + echo "[Resolve]" + echo "MulticastDNS=yes" + echo "LLMNR=yes" +} >/run/systemd/resolved.conf.d/mdns-llmnr.conf +systemctl restart systemd-resolved.service +systemctl service-log-level systemd-resolved.service debug +# make sure networkd is not running. +systemctl stop systemd-networkd.service +# defaults to yes (both the global and per-link settings are yes) +assert_in 'yes' "$(resolvectl mdns hoge)" +assert_in 'yes' "$(resolvectl llmnr hoge)" +# set per-link setting +resolvectl mdns hoge yes +resolvectl llmnr hoge yes +assert_in 'yes' "$(resolvectl mdns hoge)" +assert_in 'yes' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge resolve +resolvectl llmnr hoge resolve +assert_in 'resolve' "$(resolvectl mdns hoge)" +assert_in 'resolve' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge no +resolvectl llmnr hoge no +assert_in 'no' "$(resolvectl mdns hoge)" +assert_in 'no' "$(resolvectl llmnr hoge)" +# downgrade global setting to resolve +{ + echo "[Resolve]" + echo "MulticastDNS=resolve" + echo "LLMNR=resolve" +} >/run/systemd/resolved.conf.d/mdns-llmnr.conf +systemctl restart systemd-resolved.service +systemctl service-log-level systemd-resolved.service debug +# set per-link setting +resolvectl mdns hoge yes +resolvectl llmnr hoge yes +assert_in 'resolve' "$(resolvectl mdns hoge)" +assert_in 'resolve' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge resolve +resolvectl llmnr hoge resolve +assert_in 'resolve' "$(resolvectl mdns hoge)" +assert_in 'resolve' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge no +resolvectl llmnr hoge no +assert_in 'no' "$(resolvectl mdns hoge)" +assert_in 'no' "$(resolvectl llmnr hoge)" +# downgrade global setting to no +{ + echo "[Resolve]" + echo "MulticastDNS=no" + echo "LLMNR=no" +} >/run/systemd/resolved.conf.d/mdns-llmnr.conf +systemctl restart systemd-resolved.service +systemctl service-log-level systemd-resolved.service debug +# set per-link setting +resolvectl mdns hoge yes +resolvectl llmnr hoge yes +assert_in 'no' "$(resolvectl mdns hoge)" +assert_in 'no' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge resolve +resolvectl llmnr hoge resolve +assert_in 'no' "$(resolvectl mdns hoge)" +assert_in 'no' "$(resolvectl llmnr hoge)" +resolvectl mdns hoge no +resolvectl llmnr hoge no +assert_in 'no' "$(resolvectl mdns hoge)" +assert_in 'no' "$(resolvectl llmnr hoge)" + +# Cleanup +rm -f /run/systemd/resolved.conf.d/mdns-llmnr.conf ip link del hoge ip link del hoge.foo