ResetStatistics();
FlushCaches();
ResetServerFeatures();
+ GetDelegate(in s id,
+ out o path);
+ ListDelegates(out a(so) delegates);
properties:
readonly s LLMNRHostname = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
<variablelist class="dbus-method" generated="True" extra-ref="ResetServerFeatures()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="GetDelegate()"/>
+
+ <variablelist class="dbus-method" generated="True" extra-ref="ListDelegates()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="LLMNRHostname"/>
<variablelist class="dbus-property" generated="True" extra-ref="LLMNR"/>
<para>The <function>RevertLink()</function> method may be used to revert all per-link settings
described above to the defaults.</para>
- <para>The <function>FlushCaches()</function> flushes all resource record caches maintained by the
+ <para>The <function>FlushCaches()</function> method flushes all resource record caches maintained by the
resolver, and ensures that any subsequent lookups re-request their responses from their sources.</para>
- <para>The <function>ResetServerFeatures()</function> flushes any feature information learned about
- remote DNS servers. This ensures that subsequent lookups will be initially attempted at the highest DNS
- protocol feature level again, possibly requiring a (potentially slow) downgrade cycle to recognize the
- supported feature level again.</para>
+ <para>The <function>ResetServerFeatures()</function> method flushes any feature information learned
+ about remote DNS servers. This ensures that subsequent lookups will be initially attempted at the
+ highest DNS protocol feature level again, possibly requiring a (potentially slow) downgrade cycle to
+ recognize the supported feature level again.</para>
<para>The <function>RegisterService()</function> method may be used to register a DNS-SD service on the
host. This functionality is closely related to the functionality provided by
<function>RegisterService()</function> and deletes a DNS-SD service previously created via IPC
again.</para>
+ <para>The <function>GetDelegate()</function> method returns the D-Bus object path for the specified DNS
+ delegate ID.</para>
+
+ <para>The <function>ListDelegates()</function> method returns a list of the IDs and D-Bus object paths
+ of the currently configured DNS delegates.</para>
+
<refsect3>
<title>The Flags Parameter</title>
<xi:include href="org.freedesktop.locale1.xml" xpointer="versioning"/>
+ <refsect1>
+ <title>History</title>
+ <refsect2>
+ <title>The Manager Object</title>
+
+ <para><function>GetDelegate()</function> and <function>ListDelegates()</function> were added in version 258.</para>
+ </refsect2>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
SD_BUS_ERROR_MAP(BUS_ERROR_STUB_LOOP, ELOOP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DELEGATE, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_DNS_FORMERR, EBADMSG),
SD_BUS_ERROR_MAP(BUS_ERROR_DNS_SERVFAIL, EHOSTDOWN),
#define BUS_ERROR_STUB_LOOP "org.freedesktop.resolve1.StubLoop"
#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
+#define BUS_ERROR_NO_SUCH_DELEGATE "org.freedesktop.resolve1.NoSuchDelegate"
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
#define BUS_ERROR_DNS_FORMERR _BUS_ERROR_DNS "FORMERR"
'resolved-conf.c',
'resolved-dns-answer.c',
'resolved-dns-cache.c',
+ 'resolved-dns-delegate.c',
+ 'resolved-dns-delegate-bus.c',
'resolved-dns-dnssec.c',
'resolved-dns-packet.c',
'resolved-dns-query.c',
output : 'resolved-dnssd-gperf.c',
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
-generated_sources += [dns_type_from_name_h, dns_type_to_name_h, resolved_gperf_c, resolved_dnssd_gperf_c]
-systemd_resolved_extract_sources += [dns_type_from_name_h, dns_type_to_name_h, resolved_gperf_c, resolved_dnssd_gperf_c]
+resolved_dns_delegate_gperf_c = custom_target(
+ 'resolved-dns-delegate-gperf.c',
+ input : 'resolved-dns-delegate-gperf.gperf',
+ output : 'resolved-dns-delegate-gperf.c',
+ command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
+
+generated_sources += [dns_type_from_name_h, dns_type_to_name_h, resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
+systemd_resolved_extract_sources += [dns_type_from_name_h, dns_type_to_name_h, resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
if conf.get('ENABLE_DNS_OVER_TLS') == 1
systemd_resolved_extract_sources += files(
#include "resolved-bus.h"
#include "resolved-def.h"
#include "resolved-dns-answer.h"
+#include "resolved-dns-delegate.h"
+#include "resolved-dns-delegate-bus.h"
#include "resolved-dns-dnssec.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-query.h"
return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
}
+static int bus_method_get_delegate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_free_ char *p = NULL;
+ Manager *m = ASSERT_PTR(userdata);
+ int r;
+
+ assert(message);
+
+ const char *id;
+ r = sd_bus_message_read(message, "s", &id);
+ if (r < 0)
+ return r;
+
+ DnsDelegate *d = hashmap_get(m->delegates, id);
+ if (!d)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DELEGATE, "Delegate '%s' not known", id);
+
+ p = dns_delegate_bus_path(d);
+ if (!p)
+ return -ENOMEM;
+
+ return sd_bus_reply_method_return(message, "o", p);
+}
+
+static int bus_method_list_delegates(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ Manager *m = ASSERT_PTR(userdata);
+ int r;
+
+ assert(message);
+
+ r = sd_bus_message_new_method_return(message, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_open_container(reply, 'a', "(so)");
+ if (r < 0)
+ return r;
+
+ DnsDelegate *d;
+ HASHMAP_FOREACH(d, m->delegates) {
+ _cleanup_free_ char *p = NULL;
+
+ p = dns_delegate_bus_path(d);
+ if (!p)
+ return -ENOMEM;
+
+ r = sd_bus_message_append(reply, "(so)", d->id, p);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_bus_message_close_container(reply);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_send(reply);
+}
+
static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_NO_RESULT,
bus_method_reset_server_features,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("GetDelegate",
+ SD_BUS_ARGS("s", id),
+ SD_BUS_RESULT("o", path),
+ bus_method_get_delegate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("ListDelegates",
+ SD_BUS_NO_ARGS,
+ SD_BUS_RESULT("a(so)", delegates),
+ bus_method_list_delegates,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END,
};
"org.freedesktop.resolve1.Manager",
.vtables = BUS_VTABLES(resolve_vtable),
.children = BUS_IMPLEMENTATIONS(&link_object,
- &dnssd_object),
+ &dnssd_object,
+ &dns_delegate_object),
};
static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bus-get-properties.h"
+#include "resolved-bus.h"
+#include "resolved-dns-delegate.h"
+#include "resolved-dns-delegate-bus.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
+#include "resolved-manager.h"
+#include "strv.h"
+
+static int property_get_dns(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsDelegate *d = ASSERT_PTR(userdata);
+ int r;
+
+ assert(reply);
+
+ r = sd_bus_message_open_container(reply, 'a', "(iiayqs)");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(servers, s, d->dns_servers) {
+ r = bus_dns_server_append(reply, s, /* with_ifindex= */ true, /* extended= */ true);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(reply);
+}
+
+static int property_get_current_dns_server(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsDelegate *d = ASSERT_PTR(userdata);
+
+ assert(reply);
+
+ return bus_dns_server_append(reply, d->current_dns_server, /* with_ifindex= */ true, /* extended= */ true);
+}
+
+static int property_get_domains(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsDelegate *delegate = ASSERT_PTR(userdata);
+ int r;
+
+ assert(reply);
+
+ r = sd_bus_message_open_container(reply, 'a', "(sb)");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(domains, d, delegate->search_domains) {
+ r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_bus_message_close_container(reply);
+}
+
+static int dns_delegate_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+ Manager *m = ASSERT_PTR(userdata);
+
+ assert(bus);
+ assert(path);
+ assert(interface);
+ assert(found);
+
+ _cleanup_free_ char *e = NULL;
+ if (sd_bus_path_decode(path, "/org/freedesktop/resolve1/dns_delegate", &e) <= 0)
+ return 0;
+
+ DnsDelegate *d = hashmap_get(m->delegates, e);
+ if (!d)
+ return 0;
+
+ *found = d;
+ return 1;
+}
+
+char* dns_delegate_bus_path(const DnsDelegate *d) {
+ char *p;
+
+ assert(d);
+
+ if (sd_bus_path_encode("/org/freedesktop/resolve1/dns_delegate", d->id, &p) < 0)
+ return NULL;
+
+ return p;
+}
+
+static int dns_delegate_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+ Manager *m = ASSERT_PTR(userdata);
+ int r;
+
+ assert(bus);
+ assert(path);
+ assert(nodes);
+
+ _cleanup_strv_free_ char **l = NULL;
+ DnsDelegate *d;
+ HASHMAP_FOREACH(d, m->delegates) {
+ _cleanup_free_ char *p = NULL;
+
+ p = dns_delegate_bus_path(d);
+ if (!p)
+ return -ENOMEM;
+
+ r = strv_consume(&l, TAKE_PTR(p));
+ if (r < 0)
+ return r;
+ }
+
+ *nodes = TAKE_PTR(l);
+
+ return 1;
+}
+
+static const sd_bus_vtable dns_delegate_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+
+ SD_BUS_PROPERTY("DNS", "a(iiayqs)", property_get_dns, 0, 0),
+ SD_BUS_PROPERTY("CurrentDNSServer", "(iiayqs)", property_get_current_dns_server, 0, 0),
+ SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
+ SD_BUS_PROPERTY("DefaultRoute", "b", bus_property_get_tristate, offsetof(DnsDelegate, default_route), 0),
+
+ SD_BUS_VTABLE_END
+};
+
+const BusObjectImplementation dns_delegate_object = {
+ "/org/freedesktop/resolve1/dns_delegate",
+ "org.freedesktop.resolve1.DnsDelegate",
+ .fallback_vtables = BUS_FALLBACK_VTABLES({dns_delegate_vtable, dns_delegate_object_find}),
+ .node_enumerator = dns_delegate_node_enumerator,
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+typedef struct BusObjectImplementation BusObjectImplementation;
+typedef struct DnsDelegate DnsDelegate;
+
+extern const BusObjectImplementation dns_delegate_object;
+
+char* dns_delegate_bus_path(const DnsDelegate *d);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+%{
+#if __GNUC__ >= 15
+_Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
+#endif
+#include <stddef.h>
+#include "conf-parser.h"
+#include "resolved-dns-delegate.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name resolved_dns_delegate_gperf_hash
+%define lookup-function-name resolved_dns_delegate_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+Delegate.DNS, config_parse_delegate_dns_servers, 0, 0
+Delegate.Domains, config_parse_delegate_domains, 0, 0
+Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route)
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "conf-files.h"
+#include "dns-domain.h"
+#include "in-addr-util.h"
+#include "path-util.h"
+#include "resolved-dns-delegate.h"
+#include "resolved-dns-scope.h"
+#include "resolved-dns-search-domain.h"
+#include "resolved-dns-server.h"
+#include "resolved-manager.h"
+#include "socket-netlink.h"
+#include "strv.h"
+
+#define DNS_DELEGATES_MAX 4096U
+#define DNS_DELEGATE_SEARCH_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/dns-delegate.d"))
+
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ dns_delegate_hash_ops,
+ char,
+ string_hash_func,
+ string_compare_func,
+ DnsDelegate,
+ dns_delegate_free);
+
+int dns_delegate_new(Manager *m, const char *id, DnsDelegate **ret) {
+ int r;
+
+ assert(m);
+ assert(id);
+
+ if (hashmap_size(m->delegates) >= DNS_DELEGATES_MAX)
+ return -E2BIG;
+
+ _cleanup_free_ char *id_copy = strdup(id);
+ if (!id_copy)
+ return -ENOMEM;
+
+ _cleanup_(dns_delegate_freep) DnsDelegate *d = new(DnsDelegate, 1);
+ if (!d)
+ return -ENOMEM;
+
+ *d = (DnsDelegate) {
+ .id = TAKE_PTR(id_copy),
+ .default_route = -1,
+ };
+
+ r = dns_scope_new(
+ m,
+ &d->scope,
+ DNS_SCOPE_DELEGATE,
+ /* link= */ NULL,
+ d,
+ DNS_PROTOCOL_DNS,
+ AF_UNSPEC);
+ if (r < 0)
+ return r;
+
+ r = hashmap_ensure_put(&m->delegates, &dns_delegate_hash_ops, d->id, d);
+ if (r < 0)
+ return r;
+
+ d->manager = m;
+
+ log_debug("New delegate '%s'.", id);
+
+ if (ret)
+ *ret = d;
+
+ TAKE_PTR(d);
+ return 0;
+}
+
+DnsDelegate *dns_delegate_free(DnsDelegate *d) {
+ if (!d)
+ return NULL;
+
+ Manager *m = d->manager;
+
+ log_debug("Removing delegate '%s'.", d->id);
+
+ dns_server_unlink_all(d->dns_servers);
+ dns_search_domain_unlink_all(d->search_domains);
+
+ dns_scope_free(d->scope);
+
+ if (m)
+ hashmap_remove(m->delegates, d->id);
+
+ free(d->id);
+
+ return mfree(d);
+}
+
+DnsServer* dns_delegate_set_dns_server(DnsDelegate *d, DnsServer *s) {
+ assert(d);
+
+ if (d->current_dns_server == s)
+ return s;
+
+ if (s)
+ log_debug("Switching delegate '%s' to DNS server %s.", d->id, strna(dns_server_string_full(s)));
+
+ dns_server_unref(d->current_dns_server);
+ d->current_dns_server = dns_server_ref(s);
+
+ /* Skip flushing the cache if server stale feature is enabled. */
+ if (d->manager->stale_retention_usec == 0)
+ dns_cache_flush(&d->scope->cache);
+
+ return s;
+}
+
+DnsServer *dns_delegate_get_dns_server(DnsDelegate *d) {
+ assert(d);
+
+ if (!d->current_dns_server)
+ dns_delegate_set_dns_server(d, d->dns_servers);
+
+ return d->current_dns_server;
+}
+
+void dns_delegate_next_dns_server(DnsDelegate *d, DnsServer *if_current) {
+ assert(d);
+
+ /* If we have issues with a DNS server, let's switch to the next one (in a round robin scheme). If
+ * non-NULL if_current points to the DNS server that was selected at the beginning of whatever bigger
+ * operation we are currently executing, and hence if we already switched away from it we suppress
+ * switching again, so that each operation only results in a single switch, not multiple. */
+
+ /* If the current server of the transaction is specified, and we already are at a different one,
+ * don't do anything */
+ if (if_current && d->current_dns_server != if_current)
+ return;
+
+ /* If currently have no DNS server, then don't do anything, we'll pick it lazily the next time a DNS
+ * server is needed. */
+ if (!d->current_dns_server)
+ return;
+
+ /* Change to the next one, but make sure to follow the linked list only if this server is actually
+ * still linked. */
+ if (d->current_dns_server->linked && d->current_dns_server->servers_next) {
+ dns_delegate_set_dns_server(d, d->current_dns_server->servers_next);
+ return;
+ }
+
+ /* Pick the first one again, after we reached the end */
+ dns_delegate_set_dns_server(d, d->dns_servers);
+}
+
+static int dns_delegate_load(Manager *m, const char *path) {
+ int r;
+
+ assert(m);
+ assert(path);
+
+ _cleanup_free_ char *fn = NULL;
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
+
+ const char *e = endswith(fn, ".dns-delegate");
+ if (!e)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DNS delegate file name does not end in .dns-delegate, refusing: %s", fn);
+
+ _cleanup_free_ char *id = strndup(fn, e - fn);
+ if (!string_is_safe(id))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DNS delegate file name contains weird characters, refusing: %s", fn);
+
+ _cleanup_free_ char *dropin_dirname = strjoin(id, ".dns-delegate.d");
+ if (!dropin_dirname)
+ return log_oom();
+
+ _cleanup_(dns_delegate_freep) DnsDelegate *d = NULL;
+ r = dns_delegate_new(m, id, &d);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate delegate '%s': %m", id);
+
+ r = config_parse_many(
+ STRV_MAKE_CONST(path),
+ DNS_DELEGATE_SEARCH_DIRS,
+ dropin_dirname,
+ /* root= */ NULL,
+ "Delegate\0",
+ config_item_perf_lookup,
+ resolved_dns_delegate_gperf_lookup,
+ /* flags= */ 0,
+ d,
+ /* ret_stats_by_path= */ NULL,
+ /* ret_drop_in_files= */ NULL);
+ if (r < 0)
+ return r;
+
+ log_info("Successfully loaded delegate '%s'.", d->id);
+
+ TAKE_PTR(d);
+ return 0;
+}
+
+int manager_load_delegates(Manager *m) {
+ _cleanup_strv_free_ char **files = NULL;
+ int r;
+
+ assert(m);
+
+ r = conf_files_list_strv(&files, ".dns-delegate", /* root= */ NULL, /* flags= */ 0, DNS_DELEGATE_SEARCH_DIRS);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate .dns-delegate files: %m");
+
+ STRV_FOREACH(f, files)
+ (void) dns_delegate_load(m, *f);
+
+ return 0;
+}
+
+int config_parse_delegate_dns_servers(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ DnsDelegate *d = ASSERT_PTR(userdata);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ /* Empty assignment means clear the list */
+ if (isempty(rvalue)) {
+ dns_server_unlink_all(d->dns_servers);
+ return 0;
+ }
+
+ /* Otherwise, add to the list */
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ r = extract_first_word(&rvalue, &word, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse DNS server string '%s', ignoring.", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ break;
+
+ _cleanup_free_ char *server_name = NULL;
+ union in_addr_union address;
+ int family, ifindex = 0;
+ uint16_t port;
+ r = in_addr_port_ifindex_name_from_string_auto(word, &family, &address, &port, &ifindex, &server_name);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse DNS server string '%s', ignoring.", word);
+ continue;
+ }
+
+ /* Silently filter out 0.0.0.0, 127.0.0.53, 127.0.0.54 (our own stub DNS listener) */
+ if (!dns_server_address_valid(family, &address))
+ continue;
+
+ /* By default, the port number is determined with the transaction feature level.
+ * See dns_transaction_port() and dns_server_port(). */
+ if (IN_SET(port, 53, 853))
+ port = 0;
+
+ /* Filter out duplicates */
+ DnsServer *s = dns_server_find(d->dns_servers, family, &address, port, ifindex, server_name);
+ if (s) {
+ /* Drop the marker. This is used to find the servers that ceased to exist, see
+ * manager_mark_dns_servers() and manager_flush_marked_dns_servers(). */
+ dns_server_move_back_and_unmark(s);
+ return 0;
+ }
+
+ r = dns_server_new(
+ d->manager,
+ /* ret= */ NULL,
+ DNS_SERVER_DELEGATE,
+ /* link= */ NULL,
+ d,
+ family,
+ &address,
+ port,
+ ifindex,
+ server_name,
+ RESOLVE_CONFIG_SOURCE_FILE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add DNS server: %m");
+ }
+
+ return 0;
+}
+
+int config_parse_delegate_domains(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ DnsDelegate *d = ASSERT_PTR(userdata);
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ /* Empty assignment means clear the list */
+ if (isempty(rvalue)) {
+ dns_search_domain_unlink_all(d->search_domains);
+ return 0;
+ }
+
+ /* Otherwise, add to the list */
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ r = extract_first_word(&rvalue, &word, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse search domains string '%s', ignoring.", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ break;
+
+ const char *name = word;
+
+ bool route_only = name[0] == '~';
+ if (route_only)
+ name++;
+
+ if (dns_name_is_root(name) || streq(name, "*")) {
+ route_only = true;
+ name = ".";
+ }
+
+ DnsSearchDomain *domain;
+ r = dns_search_domain_find(d->search_domains, name, &domain);
+ if (r < 0)
+ return log_error_errno(r, "Failed to find search domain: %m");
+ if (r > 0)
+ dns_search_domain_move_back_and_unmark(domain);
+ else {
+ r = dns_search_domain_new(d->manager, &domain, DNS_SEARCH_DOMAIN_DELEGATE, /* link= */ NULL, d, name);
+ if (r < 0)
+ return r;
+ }
+
+ domain->route_only = route_only;
+ }
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "conf-parser.h"
+#include "list.h"
+
+typedef struct DnsDelegate DnsDelegate;
+typedef struct DnsScope DnsScope;
+typedef struct DnsSearchDomain DnsSearchDomain;
+typedef struct DnsServer DnsServer;
+typedef struct Manager Manager;
+
+#define DELEGATE_SEARCH_DOMAINS_MAX 256
+#define DELEGATE_DNS_SERVERS_MAX 256
+
+/* A DnsDelegate object is used to manage additional, explicitly configured unicast DNS lookup scopes,
+ * independent from any network link and from the global scope. */
+
+struct DnsDelegate {
+ Manager *manager;
+ char *id;
+
+ LIST_HEAD(DnsServer, dns_servers);
+ unsigned n_dns_servers;
+ DnsServer *current_dns_server;
+
+ LIST_HEAD(DnsSearchDomain, search_domains);
+ unsigned n_search_domains;
+
+ int default_route;
+
+ DnsScope *scope;
+
+ LIST_FIELDS(DnsDelegate, delegates);
+};
+
+int dns_delegate_new(Manager *m, const char *id, DnsDelegate **ret);
+DnsDelegate *dns_delegate_free(DnsDelegate *d);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(DnsDelegate*, dns_delegate_free);
+
+DnsServer* dns_delegate_set_dns_server(DnsDelegate *d, DnsServer *s);
+DnsServer *dns_delegate_get_dns_server(DnsDelegate *d);
+void dns_delegate_next_dns_server(DnsDelegate *d, DnsServer *if_current);
+
+int manager_load_delegates(Manager *m);
+
+const struct ConfigPerfItem* resolved_dns_delegate_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_delegate_dns_servers);
+CONFIG_PARSER_PROTOTYPE(config_parse_delegate_domains);
#include "missing_network.h"
#include "random-util.h"
#include "resolved-dns-answer.h"
+#include "resolved-dns-delegate.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-query.h"
#include "resolved-dns-question.h"
DnsScope **ret,
DnsScopeOrigin origin,
Link *link,
+ DnsDelegate *delegate,
DnsProtocol protocol,
int family) {
assert(origin < _DNS_SCOPE_ORIGIN_MAX);
assert(!!link == (origin == DNS_SCOPE_LINK));
+ assert(!!delegate == (origin == DNS_SCOPE_DELEGATE));
s = new(DnsScope, 1);
if (!s)
*s = (DnsScope) {
.manager = m,
.link = link,
+ .delegate = delegate,
.origin = origin,
.protocol = protocol,
.family = family,
dns_scope_llmnr_membership(s, true);
dns_scope_mdns_membership(s, true);
- log_debug("New scope on link %s, protocol %s, family %s, origin %s",
+ log_debug("New scope on link %s, protocol %s, family %s, origin %s, delegate %s",
link ? link->ifname : "*",
dns_protocol_to_string(protocol),
family == AF_UNSPEC ? "*" : af_to_name(family),
- dns_scope_origin_to_string(origin));
+ dns_scope_origin_to_string(origin),
+ s->delegate ? s->delegate->id : "n/a");
*ret = s;
return 0;
if (!s)
return NULL;
- log_debug("Removing scope on link %s, protocol %s, family %s, origin %s",
+ log_debug("Removing scope on link %s, protocol %s, family %s, origin %s, delegate %s",
s->link ? s->link->ifname : "*",
dns_protocol_to_string(s->protocol),
s->family == AF_UNSPEC ? "*" : af_to_name(s->family),
- dns_scope_origin_to_string(s->origin));
+ dns_scope_origin_to_string(s->origin),
+ s->delegate ? s->delegate->id : "n/a");
dns_scope_llmnr_membership(s, false);
dns_scope_mdns_membership(s, false);
if (s->protocol != DNS_PROTOCOL_DNS)
return NULL;
- if (s->link)
+ if (s->link) {
+ assert(!s->delegate);
return link_get_dns_server(s->link);
+ } else if (s->delegate)
+ return dns_delegate_get_dns_server(s->delegate);
else
return manager_get_dns_server(s->manager);
}
if (s->protocol != DNS_PROTOCOL_DNS)
return 0;
- if (s->link)
+ if (s->link) {
+ assert(!s->delegate);
return s->link->n_dns_servers;
+ } else if (s->delegate)
+ return s->delegate->n_dns_servers;
else
return s->manager->n_dns_servers;
}
if (s->link)
link_next_dns_server(s->link, if_current);
+ else if (s->delegate)
+ dns_delegate_next_dns_server(s->delegate, if_current);
else
manager_next_dns_server(s->manager, if_current);
}
if (fd < 0)
return fd;
+ assert(s->link);
r = manager_send(s->manager, fd, s->link->ifindex, family, &addr, LLMNR_PORT, NULL, p);
if (r < 0)
return r;
if (fd < 0)
return fd;
+ assert(s->link);
r = manager_send(s->manager, fd, s->link->ifindex, family, &addr, p->destination_port ?: MDNS_PORT, NULL, p);
if (r < 0)
return r;
fputs(" origin=", f);
fputs(dns_scope_origin_to_string(s->origin), f);
+
+ if (s->delegate) {
+ fputs(" id=", f);
+ fputs(s->delegate->id, f);
+ }
+
fputs("]\n", f);
if (!dns_zone_is_empty(&s->zone)) {
if (s->link)
return s->link->search_domains;
+ if (s->delegate)
+ return s->delegate->search_domains;
return s->manager->search_domains;
}
if (scope->link)
first = scope->link->search_domains;
+ else if (scope->delegate)
+ first = scope->delegate->search_domains;
else
first = scope->manager->search_domains;
if (scope->protocol != DNS_PROTOCOL_DNS)
return false;
- /* The global DNS scope is always suitable as default route */
- if (!scope->link)
- return true;
+ if (scope->link) {
+
+ /* Honour whatever is explicitly configured. This is really the best approach, and trumps any
+ * automatic logic. */
+ if (scope->link->default_route >= 0)
+ return scope->link->default_route;
+
+ /* Otherwise check if we have any route-only domains, as a sensible heuristic: if so, let's not
+ * volunteer as default route. */
+ return !dns_scope_has_route_only_domains(scope);
+
+ } else if (scope->delegate) {
- /* Honour whatever is explicitly configured. This is really the best approach, and trumps any
- * automatic logic. */
- if (scope->link->default_route >= 0)
- return scope->link->default_route;
+ if (scope->delegate->default_route >= 0)
+ return scope->delegate->default_route;
- /* Otherwise check if we have any route-only domains, as a sensible heuristic: if so, let's not
- * volunteer as default route. */
- return !dns_scope_has_route_only_domains(scope);
+ /* Delegates are by default not used as default route */
+ return false;
+ } else
+ /* The global DNS scope is always suitable as default route */
+ return true;
}
int dns_scope_dump_cache_to_json(DnsScope *scope, sd_json_variant **ret) {
}
static const char* const dns_scope_origin_table[_DNS_SCOPE_ORIGIN_MAX] = {
- [DNS_SCOPE_GLOBAL] = "global",
- [DNS_SCOPE_LINK] = "link",
+ [DNS_SCOPE_GLOBAL] = "global",
+ [DNS_SCOPE_LINK] = "link",
+ [DNS_SCOPE_DELEGATE] = "delegate",
};
DEFINE_STRING_TABLE_LOOKUP(dns_scope_origin, DnsScopeOrigin);
#include "resolved-dns-zone.h"
#include "socket-util.h"
+typedef struct DnsDelegate DnsDelegate;
typedef struct DnsQuery DnsQuery;
typedef struct DnsQueryCandidate DnsQueryCandidate;
typedef struct DnsQuestion DnsQuestion;
typedef enum DnsScopeOrigin {
DNS_SCOPE_GLOBAL,
DNS_SCOPE_LINK,
+ DNS_SCOPE_DELEGATE,
_DNS_SCOPE_ORIGIN_MAX,
_DNS_SCOPE_ORIGIN_INVALID = -EINVAL,
} DnsScopeOrigin;
DnsOverTlsMode dns_over_tls_mode;
Link *link;
+ DnsDelegate *delegate;
DnsCache cache;
DnsZone zone;
bool announced;
};
-int dns_scope_new(Manager *m, DnsScope **ret, DnsScopeOrigin origin, Link *link, DnsProtocol protocol, int family);
+int dns_scope_new(Manager *m, DnsScope **ret, DnsScopeOrigin origin, Link *link, DnsDelegate *delegate, DnsProtocol protocol, int family);
DnsScope* dns_scope_free(DnsScope *s);
void dns_scope_packet_received(DnsScope *s, usec_t rtt);
#include "alloc-util.h"
#include "dns-domain.h"
+#include "resolved-dns-delegate.h"
#include "resolved-dns-search-domain.h"
#include "resolved-link.h"
#include "resolved-manager.h"
Manager *m,
DnsSearchDomain **ret,
DnsSearchDomainType type,
- Link *l,
+ Link *link,
+ DnsDelegate *delegate,
const char *name) {
_cleanup_free_ char *normalized = NULL;
int r;
assert(m);
- assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l);
+ assert((type == DNS_SEARCH_DOMAIN_LINK) == !!link);
+ assert((type == DNS_SEARCH_DOMAIN_DELEGATE) == !!delegate);
assert(name);
r = dns_name_normalize(name, 0, &normalized);
if (r < 0)
return r;
- if (l) {
- if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
+ if (link) {
+ if (link->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
+ return -E2BIG;
+ } else if (delegate) {
+ if (delegate->n_search_domains >= DELEGATE_SEARCH_DOMAINS_MAX)
return -E2BIG;
} else {
if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX)
switch (type) {
case DNS_SEARCH_DOMAIN_LINK:
- d->link = l;
- LIST_APPEND(domains, l->search_domains, d);
- l->n_search_domains++;
+ d->link = link;
+ LIST_APPEND(domains, link->search_domains, d);
+ link->n_search_domains++;
break;
case DNS_SEARCH_DOMAIN_SYSTEM:
m->n_search_domains++;
break;
+ case DNS_SEARCH_DOMAIN_DELEGATE:
+ d->delegate = delegate;
+ LIST_APPEND(domains, delegate->search_domains, d);
+ delegate->n_search_domains++;
+ break;
+
default:
assert_not_reached();
}
LIST_REMOVE(domains, d->manager->search_domains, d);
d->manager->n_search_domains--;
break;
+
+ case DNS_SEARCH_DOMAIN_DELEGATE:
+ assert(d->delegate);
+ assert(d->delegate->n_search_domains > 0);
+ LIST_REMOVE(domains, d->delegate->search_domains, d);
+ d->delegate->n_search_domains--;
+ break;
}
d->linked = false;
LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d);
break;
+ case DNS_SEARCH_DOMAIN_DELEGATE:
+ assert(d->delegate);
+ tail = LIST_FIND_TAIL(domains, d);
+ LIST_REMOVE(domains, d->delegate->search_domains, d);
+ LIST_INSERT_AFTER(domains, d->delegate->search_domains, tail, d);
+ break;
+
default:
assert_not_reached();
}
#include "macro.h"
#include "memory-util.h"
+typedef struct DnsDelegate DnsDelegate;
typedef struct DnsSearchDomain DnsSearchDomain;
typedef struct Link Link;
typedef struct Manager Manager;
typedef enum DnsSearchDomainType {
DNS_SEARCH_DOMAIN_SYSTEM,
DNS_SEARCH_DOMAIN_LINK,
+ DNS_SEARCH_DOMAIN_DELEGATE,
} DnsSearchDomainType;
struct DnsSearchDomain {
DnsSearchDomainType type;
Link *link;
+ DnsDelegate *delegate;
char *name;
DnsSearchDomain **ret,
DnsSearchDomainType type,
Link *link,
+ DnsDelegate *delegate,
const char *name);
DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d);
#include "json-util.h"
#include "resolved-bus.h"
#include "resolved-dns-cache.h"
+#include "resolved-dns-delegate.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-scope.h"
#include "resolved-dns-search-domain.h"
Manager *m,
DnsServer **ret,
DnsServerType type,
- Link *l,
+ Link *link,
+ DnsDelegate *delegate,
int family,
const union in_addr_union *in_addr,
uint16_t port,
DnsServer *s;
assert(m);
- assert((type == DNS_SERVER_LINK) == !!l);
+ assert((type == DNS_SERVER_LINK) == !!link);
+ assert((type == DNS_SERVER_DELEGATE) == !!delegate);
assert(in_addr);
if (!IN_SET(family, AF_INET, AF_INET6))
return -EAFNOSUPPORT;
- if (l) {
- if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
+ if (link) {
+ if (link->n_dns_servers >= LINK_DNS_SERVERS_MAX)
+ return -E2BIG;
+ } else if (delegate) {
+ if (delegate->n_dns_servers >= DELEGATE_DNS_SERVERS_MAX)
return -E2BIG;
} else {
if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
switch (type) {
case DNS_SERVER_LINK:
- s->link = l;
- LIST_APPEND(servers, l->dns_servers, s);
- l->n_dns_servers++;
+ s->link = link;
+ LIST_APPEND(servers, link->dns_servers, s);
+ link->n_dns_servers++;
break;
case DNS_SERVER_SYSTEM:
m->n_dns_servers++;
break;
+ case DNS_SERVER_DELEGATE:
+ s->delegate = delegate;
+ LIST_APPEND(servers, delegate->dns_servers, s);
+ delegate->n_dns_servers++;
+ break;
default:
assert_not_reached();
}
s->linked = true;
- /* A new DNS server that isn't fallback is added and the one
- * we used so far was a fallback one? Then let's try to pick
- * the new one */
- if (type != DNS_SERVER_FALLBACK && dns_server_is_fallback(m->current_dns_server))
+ /* A new non-fallback DNS server is added and the one we used so far was a fallback one? Then
+ * let's try to pick the new one */
+ if (type == DNS_SERVER_SYSTEM && dns_server_is_fallback(m->current_dns_server))
manager_set_dns_server(m, NULL);
if (ret)
LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
s->manager->n_dns_servers--;
break;
+
+ case DNS_SERVER_DELEGATE:
+ assert(s->delegate);
+ assert(s->delegate->n_dns_servers > 0);
+ LIST_REMOVE(servers, s->delegate->dns_servers, s);
+ s->delegate->n_dns_servers--;
+ break;
+
default:
assert_not_reached();
}
if (s->manager->current_dns_server == s)
manager_set_dns_server(s->manager, NULL);
+ if (s->delegate && s->delegate->current_dns_server == s)
+ dns_delegate_set_dns_server(s->delegate, NULL);
+
/* No need to keep a default stream around anymore */
dns_server_unref_stream(s);
if (!s->linked || !s->servers_next)
return;
- /* Move us to the end of the list, so that the order is
- * strictly kept, if we are not at the end anyway. */
+ /* Move us to the end of the list, so that the order is strictly kept, if we are not at the end
+ * anyway. */
switch (s->type) {
LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s);
break;
+ case DNS_SERVER_DELEGATE:
+ assert(s->delegate);
+ tail = LIST_FIND_TAIL(servers, s);
+ LIST_REMOVE(servers, s->delegate->dns_servers, s);
+ LIST_INSERT_AFTER(servers, s->delegate->dns_servers, tail, s);
+ break;
+
default:
assert_not_reached();
}
return 0;
}
- return dns_server_new(m, NULL, type, NULL, family, &address, port, ifindex, server_name, RESOLVE_CONFIG_SOURCE_FILE);
+ return dns_server_new(
+ m,
+ /* ret= */ NULL,
+ type,
+ /* link= */ NULL,
+ /* delegate= */ NULL,
+ family,
+ &address,
+ port,
+ ifindex,
+ server_name,
+ RESOLVE_CONFIG_SOURCE_FILE);
}
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
- r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
+ r = dns_search_domain_new(
+ m,
+ &d,
+ DNS_SEARCH_DOMAIN_SYSTEM,
+ /* link= */ NULL,
+ /* delegate= */ NULL,
+ domain);
if (r < 0)
return r;
}
return s;
}
+static bool manager_search_default_route_dns_server(Manager *m) {
+ assert(m);
+
+ LIST_FOREACH(scopes, scope, m->dns_scopes) {
+ /* Ignore the global scope, it's handled separately */
+ if (scope->origin == DNS_SCOPE_GLOBAL)
+ continue;
+
+ /* Scope has no DNS server? */
+ if (dns_scope_get_n_dns_servers(scope) == 0)
+ continue;
+
+ /* If this is suitable as default route, we found what we are looking for */
+ if (dns_scope_is_default_route(scope))
+ return true;
+ }
+
+ return false;
+}
+
DnsServer *manager_get_dns_server(Manager *m) {
- Link *l;
assert(m);
/* Try to read updates resolv.conf */
manager_set_dns_server(m, NULL);
}
- if (!m->current_dns_server) {
- bool found = false;
-
- /* No DNS servers configured, let's see if there are
- * any on any links. If not, we use the fallback
- * servers */
-
- HASHMAP_FOREACH(l, m->links)
- if (l->dns_servers && l->default_route) {
- found = true;
- break;
- }
-
- if (!found)
- manager_set_dns_server(m, m->fallback_dns_servers);
- }
+ /* If no DNS servers are configured, let's see if there are any on any links or delegates. If not, we
+ * use the fallback servers */
+ if (!m->current_dns_server && !manager_search_default_route_dns_server(m))
+ manager_set_dns_server(m, m->fallback_dns_servers);
return m->current_dns_server;
}
/* Flush the cache of the scope this server belongs to */
- current = s->link ? s->link->current_dns_server : s->manager->current_dns_server;
+ current = s->link ? s->link->current_dns_server :
+ s->delegate ? s->delegate->current_dns_server :
+ s->manager->current_dns_server;
if (current != s)
return;
- scope = s->link ? s->link->unicast_scope : s->manager->unicast_scope;
+ scope = s->link ? s->link->unicast_scope :
+ s->delegate ? s->delegate->scope :
+ s->manager->unicast_scope;
if (!scope)
return;
DnsScope *dns_server_scope(DnsServer *s) {
assert(s);
+ assert(s->linked);
assert((s->type == DNS_SERVER_LINK) == !!s->link);
+ assert((s->type == DNS_SERVER_DELEGATE) == !!s->delegate);
if (s->link)
return s->link->unicast_scope;
+ if (s->delegate)
+ return s->delegate->scope;
return s->manager->unicast_scope;
}
#include "resolved-dnstls.h"
#include "time-util.h"
+typedef struct DnsDelegate DnsDelegate;
+typedef struct DnsPacket DnsPacket;
typedef struct DnsScope DnsScope;
typedef struct DnsServer DnsServer;
typedef struct DnsStream DnsStream;
-typedef struct DnsPacket DnsPacket;
typedef struct Link Link;
typedef struct Manager Manager;
DNS_SERVER_SYSTEM,
DNS_SERVER_FALLBACK,
DNS_SERVER_LINK,
+ DNS_SERVER_DELEGATE,
_DNS_SERVER_TYPE_MAX,
_DNS_SERVER_TYPE_INVALID = -EINVAL,
} DnsServerType;
DnsServerType type;
Link *link;
+ DnsDelegate *delegate;
int family;
union in_addr_union address;
DnsServer **ret,
DnsServerType type,
Link *link,
+ DnsDelegate *delegate,
int family,
const union in_addr_union *address,
uint16_t port,
if (s)
dns_server_move_back_and_unmark(s);
else {
- r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name, RESOLVE_CONFIG_SOURCE_DBUS);
+ r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, /* delegate= */ NULL, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name, RESOLVE_CONFIG_SOURCE_DBUS);
if (r < 0) {
dns_server_unlink_all(l->dns_servers);
goto finalize;
changed = true;
}
-
}
changed = dns_server_unlink_marked(l->dns_servers) || changed;
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
- r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
+ r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, /* delegate= */ NULL, name);
if (r < 0)
goto clear;
if (!l->unicast_scope) {
dns_server_reset_features_all(l->dns_servers);
- r = dns_scope_new(l->manager, &l->unicast_scope, DNS_SCOPE_LINK, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
+ r = dns_scope_new(l->manager, &l->unicast_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
if (r < 0)
log_link_warning_errno(l, r, "Failed to allocate DNS scope, ignoring: %m");
}
if (link_relevant(l, AF_INET, true) &&
link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) {
if (!l->llmnr_ipv4_scope) {
- r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, DNS_SCOPE_LINK, l, DNS_PROTOCOL_LLMNR, AF_INET);
+ r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_LLMNR, AF_INET);
if (r < 0)
log_link_warning_errno(l, r, "Failed to allocate LLMNR IPv4 scope, ignoring: %m");
}
if (link_relevant(l, AF_INET6, true) &&
link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) {
if (!l->llmnr_ipv6_scope) {
- r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, DNS_SCOPE_LINK, l, DNS_PROTOCOL_LLMNR, AF_INET6);
+ r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_LLMNR, AF_INET6);
if (r < 0)
log_link_warning_errno(l, r, "Failed to allocate LLMNR IPv6 scope, ignoring: %m");
}
if (link_relevant(l, AF_INET, true) &&
link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) {
if (!l->mdns_ipv4_scope) {
- r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, DNS_SCOPE_LINK, l, DNS_PROTOCOL_MDNS, AF_INET);
+ r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_MDNS, AF_INET);
if (r < 0)
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv4 scope, ignoring: %m");
}
if (link_relevant(l, AF_INET6, true) &&
link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) {
if (!l->mdns_ipv6_scope) {
- r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, DNS_SCOPE_LINK, l, DNS_PROTOCOL_MDNS, AF_INET6);
+ r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_MDNS, AF_INET6);
if (r < 0)
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv6 scope, ignoring: %m");
}
return 0;
}
- return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, port, 0, name, RESOLVE_CONFIG_SOURCE_NETWORKD);
+ return dns_server_new(l->manager, /* ret= */ NULL, DNS_SERVER_LINK, l, /* delegate= */ NULL, family, &a, port, 0, name, RESOLVE_CONFIG_SOURCE_NETWORKD);
}
static int link_update_dns_servers(Link *l) {
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
- r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
+ r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, /* delegate= */ NULL, name);
if (r < 0)
return r;
}
#include "resolved-bus.h"
#include "resolved-conf.h"
#include "resolved-dns-answer.h"
+#include "resolved-dns-delegate.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-query.h"
#include "resolved-dns-question.h"
HASHMAP_FOREACH(l, m->links)
LIST_FOREACH(servers, server, l->dns_servers)
dns_server_dump(server, f);
+ DnsDelegate *delegate;
+ HASHMAP_FOREACH(delegate, m->delegates)
+ LIST_FOREACH(servers, server, delegate->dns_servers)
+ dns_server_dump(server, f);
return memstream_dump(LOG_INFO, &ms);
}
m->dns_extra_stub_listeners = ordered_set_free(m->dns_extra_stub_listeners);
dnssd_service_clear_on_reload(m->dnssd_services);
m->unicast_scope = dns_scope_free(m->unicast_scope);
+ m->delegates = hashmap_free(m->delegates);
dns_trust_anchor_flush(&m->trust_anchor);
if (r < 0)
log_warning_errno(r, "Failed to load DNS-SD configuration files: %m");
+ manager_load_delegates(m);
+
/* The default scope configuration is influenced by the manager's configuration (modes, etc.), so
* recreate it on reload. */
- r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
+ r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
if (r < 0)
return r;
if (r < 0)
log_warning_errno(r, "Failed to load DNS-SD configuration files: %m");
- r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
+ manager_load_delegates(m);
+
+ r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
if (r < 0)
return r;
Manager *manager_free(Manager *m) {
Link *l;
- DnssdService *s;
if (!m)
return NULL;
while ((l = hashmap_first(m->links)))
link_free(l);
+ m->delegates = hashmap_free(m->delegates);
+
while (m->dns_queries)
dns_query_free(m->dns_queries);
m->stub_queries_by_packet = hashmap_free(m->stub_queries_by_packet);
-
- dns_scope_free(m->unicast_scope);
+ m->unicast_scope = dns_scope_free(m->unicast_scope);
/* At this point only orphaned streams should remain. All others should have been freed already by their
* owners */
free(m->llmnr_hostname);
free(m->mdns_hostname);
+ DnssdService *s;
while ((s = hashmap_first(m->dnssd_services)))
dnssd_service_free(s);
hashmap_free(m->dnssd_services);
}
/* Then, add the per-link servers */
- HASHMAP_FOREACH(l, m->links) {
+ HASHMAP_FOREACH(l, m->links)
LIST_FOREACH(servers, s, l->dns_servers) {
r = ordered_set_put(*dns, s);
if (r == -EEXIST)
if (r < 0)
return r;
}
- }
+
+ /* Third, add the delegate servers and domains */
+ DnsDelegate *d;
+ HASHMAP_FOREACH(d, m->delegates)
+ LIST_FOREACH(servers, s, d->dns_servers) {
+ r = ordered_set_put(*dns, s);
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return r;
+ }
/* If we found nothing, add the fallback servers */
if (ordered_set_isempty(*dns)) {
* > 0 or true: return only domains which are for routing only
*/
int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) {
- Link *l;
int r;
assert(m);
return r;
}
- HASHMAP_FOREACH(l, m->links) {
+ DnsDelegate *delegate;
+ HASHMAP_FOREACH(delegate, m->delegates)
+ LIST_FOREACH(domains, d, delegate->search_domains) {
+
+ if (filter_route >= 0 &&
+ d->route_only != !!filter_route)
+ continue;
+
+ r = ordered_set_put(*domains, d->name);
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return r;
+ }
+ Link *l;
+ HASHMAP_FOREACH(l, m->links)
LIST_FOREACH(domains, d, l->search_domains) {
if (filter_route >= 0 &&
if (r < 0)
return r;
}
- }
return 0;
}
}
void manager_reset_server_features(Manager *m) {
- Link *l;
dns_server_reset_features_all(m->dns_servers);
dns_server_reset_features_all(m->fallback_dns_servers);
+ Link *l;
HASHMAP_FOREACH(l, m->links)
dns_server_reset_features_all(l->dns_servers);
+ DnsDelegate *d;
+ HASHMAP_FOREACH(d, m->delegates)
+ dns_server_reset_features_all(d->dns_servers);
+
log_info("Resetting learnt feature levels on all servers.");
}
LIST_HEAD(DnsScope, dns_scopes);
DnsScope *unicast_scope;
+ Hashmap *delegates; /* id string → DnsDelegate objects */
+
/* LLMNR */
int llmnr_ipv4_udp_fd;
int llmnr_ipv6_udp_fd;
}
if (cfg->has_scope) {
- ASSERT_OK(dns_scope_new(&env->manager, &env->scope, env->link ? DNS_SCOPE_LINK : DNS_SCOPE_GLOBAL, env->link, env->protocol, env->family));
+ ASSERT_OK(dns_scope_new(&env->manager, &env->scope, env->link ? DNS_SCOPE_LINK : DNS_SCOPE_GLOBAL, env->link, /* delegate= */ NULL, env->protocol, env->family));
ASSERT_NOT_NULL(env->scope);
env->server_addr.in.s_addr = htobe32(0x7f000001);
env->server_port = 53;
ASSERT_OK(dns_server_new(&env->manager, &env->server, env->server_type,
- env->link, env->family, &env->server_addr, env->server_port,
+ env->link, /* delegate= */ NULL, env->family, &env->server_addr, env->server_port,
env->ifindex, env->server_name, RESOLVE_CONFIG_SOURCE_DBUS));
ASSERT_NOT_NULL(env->server);
for (size_t i = 0 ; i < env->n_search_domains; i++) {
DnsSearchDomainType type = (env->link == NULL) ? DNS_SEARCH_DOMAIN_SYSTEM : DNS_SEARCH_DOMAIN_LINK;
- ASSERT_OK(dns_search_domain_new(&env->manager, &env->search_domains[i], type, env->link, SEARCH_DOMAINS[i]));
+ ASSERT_OK(dns_search_domain_new(&env->manager, &env->search_domains[i], type, env->link, /* delegate= */ NULL, SEARCH_DOMAINS[i]));
ASSERT_NOT_NULL(env->search_domains[i]);
}
}
Manager manager = {};
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd = NULL;
- ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local"));
+ ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local"));
ASSERT_NOT_NULL(sd);
ASSERT_TRUE(sd->linked);
DnsSearchDomain *sd = NULL;
for (size_t i = 0; i < MANAGER_SEARCH_DOMAINS_MAX; i++) {
- ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local"));
+ ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local"));
ASSERT_NOT_NULL(sd);
ASSERT_EQ(manager.n_search_domains, i + 1);
}
- ASSERT_ERROR(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local"), E2BIG);
+ ASSERT_ERROR(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local"), E2BIG);
ASSERT_NOT_NULL(sd);
dns_search_domain_unlink_all(manager.search_domains);
ASSERT_OK(link_new(&manager, &link, 1));
ASSERT_NOT_NULL(link);
- ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, "local."));
+ ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "local."));
ASSERT_NOT_NULL(sd);
ASSERT_TRUE(sd->linked);
ASSERT_NOT_NULL(link);
for (size_t i = 0; i < LINK_SEARCH_DOMAINS_MAX; i++) {
- ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, "local"));
+ ASSERT_OK(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "local"));
ASSERT_NOT_NULL(sd);
ASSERT_EQ(link->n_search_domains, i + 1);
}
- ASSERT_ERROR(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, "local"), E2BIG);
+ ASSERT_ERROR(dns_search_domain_new(&manager, &sd, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "local"), E2BIG);
ASSERT_NOT_NULL(sd);
}
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd1 = NULL, *sd3 = NULL;
DnsSearchDomain *sd2 = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
ASSERT_TRUE(sd2->linked);
ASSERT_OK(link_new(&manager, &link, 1));
ASSERT_NOT_NULL(link);
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_LINK, link, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_LINK, link, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_LINK, link, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_LINK, link, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
ASSERT_TRUE(sd2->linked);
Manager manager = {};
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd1 = NULL, *sd2 = NULL, *sd3 = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
ASSERT_FALSE(sd1->marked);
Manager manager = {};
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd1 = NULL, *sd2 = NULL, *sd3 = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
dns_search_domain_move_back_and_unmark(sd1);
DnsSearchDomain *sd1 = NULL, *sd2 = NULL;
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd3 = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
dns_search_domain_unlink_marked(sd1);
Manager manager = {};
DnsSearchDomain *sd1 = NULL, *sd2 = NULL, *sd3 = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
dns_search_domain_unlink_all(sd1);
Manager manager = {};
_cleanup_(dns_search_domain_unrefp) DnsSearchDomain *sd1 = NULL, *sd2 = NULL, *sd3 = NULL, *ret = NULL;
- dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "local");
+ dns_search_domain_new(&manager, &sd1, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "local");
ASSERT_NOT_NULL(sd1);
- dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "vpn.example.com");
+ dns_search_domain_new(&manager, &sd2, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "vpn.example.com");
ASSERT_NOT_NULL(sd2);
- dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, NULL, "org");
+ dns_search_domain_new(&manager, &sd3, DNS_SEARCH_DOMAIN_SYSTEM, /* link= */ NULL, /* delegate= */ NULL, "org");
ASSERT_NOT_NULL(sd3);
ASSERT_TRUE(dns_search_domain_find(sd1, "local", &ret));
DnsZoneItem *item = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- ASSERT_OK(dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET));
+ ASSERT_OK(dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET));
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
DnsZone *zone = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
DnsZone *zone = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
DnsZone *zone = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr_in = NULL, *rr_out = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
DnsZone *zone = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr_in = NULL, *rr_out = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
DnsZone *zone = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr_in = NULL, *rr_out = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr1 = NULL, *rr2 = NULL, *rr3 = NULL;
DnsResourceKey *key = NULL;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
zone = &scope->zone;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
bool tentative;
- dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
+ dns_scope_new(&manager, &scope, DNS_SCOPE_GLOBAL, /* link= */ NULL, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_INET);
ASSERT_NOT_NULL(scope);
add_zone_rrs(scope);
link = env->link;
ASSERT_OK(dns_server_new(&env->manager, &env->server, env->server_type,
- link, family, &env->server_addr, env->server_port,
+ link, /* delegate= */ NULL, family, &env->server_addr, env->server_port,
env->ifindex, env->server_name, RESOLVE_CONFIG_SOURCE_DBUS));
ASSERT_NOT_NULL(env->server);