+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
#include "mkdir.h"
#include "parse-util.h"
#include "resolved-link.h"
+#include "resolved-llmnr.h"
+#include "resolved-mdns.h"
#include "string-util.h"
#include "strv.h"
}
void link_allocate_scopes(Link *l) {
+ bool unicast_relevant;
int r;
assert(l);
- if (link_relevant(l, AF_UNSPEC, false) &&
- l->dns_servers) {
+ /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
+ * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
+ * now, even if they have the same addresses as before. */
+
+ unicast_relevant = link_relevant(l, AF_UNSPEC, false);
+ if (unicast_relevant != l->unicast_relevant) {
+ l->unicast_relevant = unicast_relevant;
+
+ dns_server_reset_features_all(l->manager->fallback_dns_servers);
+ dns_server_reset_features_all(l->manager->dns_servers);
+ }
+
+ /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
+ * need anymore */
+
+ if (unicast_relevant && l->dns_servers) {
if (!l->unicast_scope) {
+ dns_server_reset_features_all(l->dns_servers);
+
r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
if (r < 0)
log_warning_errno(r, "Failed to allocate DNS scope: %m");
assert(l);
+#if ! HAVE_GCRYPT
+ if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE))
+ log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
+ return;
+#endif
+
if (l->dnssec_mode == mode)
return;
}
int link_update(Link *l) {
+ int r;
+
assert(l);
link_read_settings(l);
link_load_user(l);
+
+ if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
+ r = manager_llmnr_start(l->manager);
+ if (r < 0)
+ return r;
+ }
+
+ if (l->mdns_support != RESOLVE_SUPPORT_NO) {
+ r = manager_mdns_start(l->manager);
+ if (r < 0)
+ return r;
+ }
+
link_allocate_scopes(l);
link_add_rrs(l, false);
assert(l);
- /* A link is relevant for local multicast traffic if it isn't a loopback or pointopoint device, has a link
+ /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
* beat, can do multicast and has at least one link-local (or better) IP address.
*
* A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
- * least one routable address.*/
+ * least one routable address. */
if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
return false;
return false;
if (local_multicast) {
- if (l->flags & IFF_POINTOPOINT)
- return false;
-
if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
return false;
}
return s;
if (s)
- log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
+ log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
dns_server_unref(l->current_dns_server);
l->current_dns_server = dns_server_ref(s);
a->link = l;
LIST_PREPEND(addresses, l->addresses, a);
+ l->n_addresses++;
if (ret)
*ret = a;
if (a->link) {
LIST_REMOVE(addresses, a->link->addresses, a);
+ assert(a->link->n_addresses > 0);
+ a->link->n_addresses--;
+
if (a->llmnr_address_rr) {
if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
if (r < 0)
goto fail;
- fputs("# This is private data. Do not parse.\n", f);
+ fputs_unlocked("# This is private data. Do not parse.\n", f);
v = resolve_support_to_string(l->llmnr_support);
if (v)
if (l->dns_servers) {
DnsServer *server;
- fputs("SERVERS=", f);
+ fputs_unlocked("SERVERS=", f);
LIST_FOREACH(servers, server, l->dns_servers) {
if (server != l->dns_servers)
- fputc(' ', f);
+ fputc_unlocked(' ', f);
v = dns_server_string(server);
if (!v) {
goto fail;
}
- fputs(v, f);
+ fputs_unlocked(v, f);
}
- fputc('\n', f);
+ fputc_unlocked('\n', f);
}
if (l->search_domains) {
DnsSearchDomain *domain;
- fputs("DOMAINS=", f);
+ fputs_unlocked("DOMAINS=", f);
LIST_FOREACH(domains, domain, l->search_domains) {
if (domain != l->search_domains)
- fputc(' ', f);
+ fputc_unlocked(' ', f);
if (domain->route_only)
- fputc('~', f);
+ fputc_unlocked('~', f);
- fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
+ fputs_unlocked(DNS_SEARCH_DOMAIN_NAME(domain), f);
}
- fputc('\n', f);
+ fputc_unlocked('\n', f);
}
if (!set_isempty(l->dnssec_negative_trust_anchors)) {
Iterator i;
char *nta;
- fputs("NTAS=", f);
+ fputs_unlocked("NTAS=", f);
SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
if (space)
- fputc(' ', f);
+ fputc_unlocked(' ', f);
- fputs(nta, f);
+ fputs_unlocked(nta, f);
space = true;
}
- fputc('\n', f);
+ fputc_unlocked('\n', f);
}
r = fflush_and_check(f);