]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolve: allow configurable bind address 16044/head
authorSusant Sahani <ssahani@vmware.com>
Sat, 29 Aug 2020 07:12:10 +0000 (07:12 +0000)
committerSusant Sahani <ssahani@vmware.com>
Thu, 3 Sep 2020 08:27:41 +0000 (08:27 +0000)
man/resolved.conf.xml
src/resolve/resolved-conf.c
src/resolve/resolved-conf.h
src/resolve/resolved-dns-stub.c
src/resolve/resolved-dns-stub.h
src/resolve/resolved-gperf.gperf
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
test/fuzz/fuzz-unit-file/directives.service

index 535a23f500a12853fe081b744a31c4846ad7c159..338bee6c38abd50790edb47c27f7849675c0efea 100644 (file)
         in use.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>DNSStubListenerExtra=</varname></term>
+        <listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may optionally be prefixed by <literal>:</literal> and
+        a protocol name (<literal>udp</literal> or <literal>tcp</literal>). When an IPv6 address is specified with a port number, then the
+        address must be in the square brackets. This option can be specified multiple times. If an empty string is assigned, then the all
+        previous assignments are cleared. It may also be optionally suffixed by a numeric port number with separator <literal>:</literal>.
+        If the protocol is not specified, the service will listen on both <literal>UDP</literal> and <literal>TCP</literal>. If the port is not
+        specified, then the service takes port as 53. This option may be used multiple times. Note that this is independent of the
+        primary DNS stub configured with <varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
+        sockets to listen on. Defaults to unset.</para>
+
+        <para>If the string in the format <literal>udp</literal>:[<replaceable>x</replaceable>]:<replaceable>y</replaceable>,
+        it is read as protocol <literal>udp</literal> and IPv6 address x on a port y.</para>
+
+        <para>If the string in the format [<replaceable>x</replaceable>]:<replaceable>y</replaceable>, it is read as both protocol
+        <literal>udp</literal> and <literal>tcp</literal>, IPv6 address x on a port y.</para>
+
+        <para>If the string in the format <replaceable>x</replaceable>, it is read as protocol both <literal>udp</literal> and
+        <literal>tcp</literal>, IPv6/IPv4 address x on a port 53.</para>
+
+        <para>If the string in the format <literal>udp</literal>:<replaceable>x</replaceable>:<replaceable>y</replaceable>,
+        it is read as protocol <literal>udp</literal> and IPv4 address x on a port y.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>ReadEtcHosts=</varname></term>
         <listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default),
index 6b99271245716d25f6f46ae02d43de4e92bb341a..3b2b4d2063e8ca368a4e30eb413b2d6e451992a8 100644 (file)
 #include "resolved-dnssd.h"
 #include "resolved-manager.h"
 #include "resolved-dns-search-domain.h"
+#include "resolved-dns-stub.h"
 #include "dns-domain.h"
 #include "socket-netlink.h"
 #include "specifier.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strv.h"
 #include "utf8.h"
 
 DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting");
@@ -27,6 +29,51 @@ static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MA
 };
 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES);
 
+static void dns_stub_listener_extra_hash_func(const DNSStubListenerExtra *a, struct siphash *state) {
+        unsigned port;
+
+        assert(a);
+
+        siphash24_compress(&a->mode, sizeof(a->mode), state);
+        siphash24_compress(&socket_address_family(&a->address), sizeof(a->address.type), state);
+        siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)), state);
+
+        (void) sockaddr_port(&a->address.sockaddr.sa, &port);
+        siphash24_compress(&port, sizeof(port), state);
+}
+
+static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) {
+        unsigned p, q;
+        int r;
+
+        assert(a);
+        assert(b);
+
+        r = CMP(a->mode, b->mode);
+        if (r != 0)
+                return r;
+
+        r = CMP(socket_address_family(&a->address), socket_address_family(&b->address));
+        if (r != 0)
+                return r;
+
+        r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)));
+        if (r != 0)
+                return r;
+
+        (void) sockaddr_port(&a->address.sockaddr.sa, &p);
+        (void) sockaddr_port(&b->address.sockaddr.sa, &q);
+
+        return CMP(p, q);
+}
+
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+                dns_stub_listener_extra_hash_ops,
+                DNSStubListenerExtra,
+                dns_stub_listener_extra_hash_func,
+                dns_stub_listener_extra_compare_func,
+                free);
+
 static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
         _cleanup_free_ char *server_name = NULL;
         union in_addr_union address;
@@ -385,6 +432,111 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line
         return 0;
 }
 
+int config_parse_dns_stub_listener_extra(
+                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) {
+
+        _cleanup_free_ DNSStubListenerExtra *udp = NULL, *tcp = NULL;
+        _cleanup_free_ char *word = NULL;
+        Manager *m = userdata;
+        bool both = false;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                m->dns_extra_stub_listeners = ordered_set_free(m->dns_extra_stub_listeners);
+                return 0;
+        }
+
+        p = rvalue;
+        r = extract_first_word(&p, &word, ":", 0);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r <= 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Invalid DNSStubListenExtra='%s', ignoring assignment", rvalue);
+                return 0;
+        }
+
+        /*  First look for udp/tcp. If not specified then turn both TCP and UDP */
+        if (!STR_IN_SET(word, "tcp", "udp")) {
+                both = true;
+                p = rvalue;
+        }
+
+        if (streq(word, "tcp") || both) {
+                r = dns_stub_extra_new(&tcp);
+                if (r < 0)
+                        return log_oom();
+
+                tcp->mode = DNS_STUB_LISTENER_TCP;
+        }
+
+        if (streq(word, "udp") || both) {
+                r = dns_stub_extra_new(&udp);
+                if (r < 0)
+                        return log_oom();
+
+                udp->mode = DNS_STUB_LISTENER_UDP;
+        }
+
+        if (tcp) {
+                r = socket_addr_port_from_string_auto(p, 53, &tcp->address);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
+                        return 0;
+                }
+        }
+
+        if (udp) {
+                r = socket_addr_port_from_string_auto(p, 53, &udp->address);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
+                        return 0;
+                }
+        }
+
+        if (tcp) {
+                r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, tcp);
+                if (r < 0) {
+                        if (r == -ENOMEM)
+                                return log_oom();
+
+                        log_warning_errno(r, "Failed to store TCP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+        }
+
+        if (udp) {
+                r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, udp);
+                if (r < 0) {
+                        if (r == -ENOMEM)
+                                return log_oom();
+
+                        log_warning_errno(r, "Failed to store UDP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+        }
+
+        TAKE_PTR(tcp);
+        TAKE_PTR(udp);
+
+        return 0;
+}
+
 int manager_parse_config_file(Manager *m) {
         int r;
 
index ac3937cfaeec8e6053b062af12fa19dd61923a19..f8d16b5a8edf01244ec57bcf83cbd18d6e54a50a 100644 (file)
@@ -30,6 +30,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra);
 
 const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_;
 DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_;
index 03edbe26dc0d245ae7011288be8126c7a946c5b9..9cb8797458849b144fe6004c416baa82f6831248 100644 (file)
@@ -4,6 +4,7 @@
 #include "fd-util.h"
 #include "missing_network.h"
 #include "resolved-dns-stub.h"
+#include "socket-netlink.h"
 #include "socket-util.h"
 
 /* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet,
 static int manager_dns_stub_udp_fd(Manager *m);
 static int manager_dns_stub_tcp_fd(Manager *m);
 
+int dns_stub_extra_new(DNSStubListenerExtra **ret) {
+        DNSStubListenerExtra *l;
+
+        l = new(DNSStubListenerExtra, 1);
+        if (!l)
+                return -ENOMEM;
+
+        *l = (DNSStubListenerExtra) {
+                .fd = -1,
+        };
+
+        *ret = TAKE_PTR(l);
+
+        return 0;
+}
+
 static int dns_stub_make_reply_packet(
                 DnsPacket **p,
                 size_t max_size,
@@ -386,6 +403,22 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void
         return 0;
 }
 
+static int set_dns_stub_common_socket_options(int fd) {
+        int r;
+
+        assert(fd >= 0);
+
+        r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
+        if (r < 0)
+                return r;
+
+        r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
+        if (r < 0)
+                return r;
+
+        return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
+}
+
 static int manager_dns_stub_udp_fd(Manager *m) {
         union sockaddr_union sa = {
                 .in.sin_family = AF_INET,
@@ -402,15 +435,7 @@ static int manager_dns_stub_udp_fd(Manager *m) {
         if (fd < 0)
                 return -errno;
 
-        r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
-        if (r < 0)
-                return r;
-
-        r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
-        if (r < 0)
-                return r;
-
-        r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
+        r = set_dns_stub_common_socket_options(fd);
         if (r < 0)
                 return r;
 
@@ -431,6 +456,64 @@ static int manager_dns_stub_udp_fd(Manager *m) {
         return m->dns_stub_udp_fd = TAKE_FD(fd);
 }
 
+static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
+        _cleanup_free_ char *pretty = NULL;
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        if (l->fd >= 0)
+                return 0;
+
+        fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
+        if (r < 0)
+                goto fail;
+
+        r = set_dns_stub_common_socket_options(fd);
+        if (r < 0)
+                goto fail;
+
+        if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-udp-extra");
+
+        l->fd = TAKE_FD(fd);
+
+        if (DEBUG_LOGGING) {
+                (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
+                log_debug("Listening on UDP socket %s.", strnull(pretty));
+        }
+
+        return 0;
+
+ fail:
+       (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
+       if (r == -EADDRINUSE)
+               return log_warning_errno(r,
+                                        "Another process is already listening on UDP socket %s.\n"
+                                        "Turning off local DNS stub extra support.", strnull(pretty));
+       if (r == -EPERM)
+               return log_warning_errno(r,
+                                        "Failed to listen on UDP socket %s: %m.\n"
+                                        "Turning off local DNS stub extra support.", strnull(pretty));
+
+       assert(r < 0);
+
+       return log_warning_errno(r, "Failed to listen on UDP socket %s, ignoring: %m", strnull(pretty));
+}
+
 static int on_dns_stub_stream_packet(DnsStream *s) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
 
@@ -492,19 +575,11 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
         if (fd < 0)
                 return -errno;
 
-        r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
+        r = set_dns_stub_common_socket_options(fd);
         if (r < 0)
                 return r;
 
-        r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
-        if (r < 0)
-                return r;
-
-        r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
-        if (r < 0)
-                return r;
-
-        r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
+        r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
         if (r < 0)
                 return r;
 
@@ -528,6 +603,73 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
         return m->dns_stub_tcp_fd = TAKE_FD(fd);
 }
 
+static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
+        _cleanup_free_ char *pretty = NULL;
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        if (l->fd >= 0)
+                return 0;
+
+        fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = set_dns_stub_common_socket_options(fd);
+        if (r < 0)
+                goto fail;
+
+        r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
+        if (r < 0)
+                goto fail;
+
+        r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
+        if (r < 0)
+                goto fail;
+
+        if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        if (listen(fd, SOMAXCONN) < 0) {
+                r = -errno;
+                goto fail;
+        }
+
+        r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-tcp-extra");
+
+        l->fd = TAKE_FD(fd);
+
+        if (DEBUG_LOGGING) {
+                (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
+                log_debug("Listening on TCP socket %s.", strnull(pretty));
+        }
+
+        return 0;
+
+ fail:
+       (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
+       if (r == -EADDRINUSE)
+               return log_warning_errno(r,
+                                        "Another process is already listening on TCP socket %s.\n"
+                                        "Turning off local DNS stub extra support.", strnull(pretty));
+       if (r == -EPERM)
+               return log_warning_errno(r,
+                                        "Failed to listen on TCP socket %s: %m.\n"
+                                        "Turning off local DNS stub extra support.", strnull(pretty));
+
+       assert(r < 0);
+
+       return log_warning_errno(r, "Failed to listen on TCP socket %s, ignoring: %m", strnull(pretty));
+}
+
 int manager_dns_stub_start(Manager *m) {
         const char *t = "UDP";
         int r = 0;
@@ -564,6 +706,22 @@ int manager_dns_stub_start(Manager *m) {
         } else if (r < 0)
                 return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t);
 
+        if (!ordered_set_isempty(m->dns_extra_stub_listeners)) {
+                DNSStubListenerExtra *l;
+                Iterator i;
+
+                log_debug("Creating stub listener extra using %s.",
+                          m->dns_stub_listener_mode == DNS_STUB_LISTENER_UDP ? "UDP" :
+                          m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
+                          "UDP/TCP");
+
+                ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i)
+                        if (l->mode == DNS_STUB_LISTENER_UDP)
+                                (void) manager_dns_stub_udp_fd_extra(m, l);
+                        else
+                                (void) manager_dns_stub_tcp_fd_extra(m, l);
+        }
+
         return 0;
 }
 
@@ -576,3 +734,15 @@ void manager_dns_stub_stop(Manager *m) {
         m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd);
         m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd);
 }
+
+void manager_dns_stub_stop_extra(Manager *m) {
+        DNSStubListenerExtra *l;
+        Iterator i;
+
+        assert(m);
+
+        ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) {
+                l->dns_stub_extra_event_source = sd_event_source_unref(l->dns_stub_extra_event_source);
+                l->fd = safe_close(l->fd);
+        }
+}
index f34e9db1af121f9901661b375fa003f34b624237..e589df383198376fac46436c6cef4de94e4bac27 100644 (file)
@@ -3,5 +3,8 @@
 
 #include "resolved-manager.h"
 
+int dns_stub_extra_new(DNSStubListenerExtra **ret);
+
 void manager_dns_stub_stop(Manager *m);
+void manager_dns_stub_stop_extra(Manager *m);
 int manager_dns_stub_start(Manager *m);
index 553da8d251826a01f234324617454de67a578d55..b54fa1ba99bbf38c195264190deaffadfccb5820 100644 (file)
@@ -18,14 +18,15 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Resolve.DNS,                       config_parse_dns_servers,            DNS_SERVER_SYSTEM,   0
-Resolve.FallbackDNS,               config_parse_dns_servers,            DNS_SERVER_FALLBACK, 0
-Resolve.Domains,                   config_parse_search_domains,         0,                   0
-Resolve.LLMNR,                     config_parse_resolve_support,        0,                   offsetof(Manager, llmnr_support)
-Resolve.MulticastDNS,              config_parse_resolve_support,        0,                   offsetof(Manager, mdns_support)
-Resolve.DNSSEC,                    config_parse_dnssec_mode,            0,                   offsetof(Manager, dnssec_mode)
-Resolve.DNSOverTLS,                config_parse_dns_over_tls_mode,      0,                   offsetof(Manager, dns_over_tls_mode)
-Resolve.Cache,                     config_parse_dns_cache_mode,         DNS_CACHE_MODE_YES,  offsetof(Manager, enable_cache)
-Resolve.DNSStubListener,           config_parse_dns_stub_listener_mode, 0,                   offsetof(Manager, dns_stub_listener_mode)
-Resolve.ReadEtcHosts,              config_parse_bool,                   0,                   offsetof(Manager, read_etc_hosts)
-Resolve.ResolveUnicastSingleLabel, config_parse_bool,                   0,                   offsetof(Manager, resolve_unicast_single_label)
+Resolve.DNS,                       config_parse_dns_servers,             DNS_SERVER_SYSTEM,   0
+Resolve.FallbackDNS,               config_parse_dns_servers,             DNS_SERVER_FALLBACK, 0
+Resolve.Domains,                   config_parse_search_domains,          0,                   0
+Resolve.LLMNR,                     config_parse_resolve_support,         0,                   offsetof(Manager, llmnr_support)
+Resolve.MulticastDNS,              config_parse_resolve_support,         0,                   offsetof(Manager, mdns_support)
+Resolve.DNSSEC,                    config_parse_dnssec_mode,             0,                   offsetof(Manager, dnssec_mode)
+Resolve.DNSOverTLS,                config_parse_dns_over_tls_mode,       0,                   offsetof(Manager, dns_over_tls_mode)
+Resolve.Cache,                     config_parse_dns_cache_mode,          DNS_CACHE_MODE_YES,  offsetof(Manager, enable_cache)
+Resolve.DNSStubListener,           config_parse_dns_stub_listener_mode,  0,                   offsetof(Manager, dns_stub_listener_mode)
+Resolve.ReadEtcHosts,              config_parse_bool,                    0,                   offsetof(Manager, read_etc_hosts)
+Resolve.ResolveUnicastSingleLabel, config_parse_bool,                    0,                   offsetof(Manager, resolve_unicast_single_label)
+Resolve.DNSStubListenerExtra,      config_parse_dns_stub_listener_extra, 0,                   offsetof(Manager, dns_extra_stub_listeners)
index 17bdb67ed5642533101331929930d67801942883..5c09de0c3484b244ddf89db951b918aca4d414a6 100644 (file)
@@ -701,6 +701,7 @@ Manager *manager_free(Manager *m) {
 
         hashmap_free(m->links);
         hashmap_free(m->dns_transactions);
+        ordered_set_free(m->dns_extra_stub_listeners);
 
         sd_event_source_unref(m->network_event_source);
         sd_network_monitor_unref(m->network_monitor);
@@ -713,6 +714,8 @@ Manager *manager_free(Manager *m) {
         manager_dns_stub_stop(m);
         manager_varlink_done(m);
 
+        manager_dns_stub_stop_extra(m);
+
         bus_verify_polkit_async_registry_free(m->polkit_registry);
 
         sd_bus_flush_close_unref(m->bus);
index 390fac4a523b66fb5b187710ec4c49020aa1c3b2..a3a2e08123c6e20ca1556624a9668f03c1a271e7 100644 (file)
@@ -31,6 +31,14 @@ typedef struct EtcHosts {
         Set *no_address;
 } EtcHosts;
 
+typedef struct DNSStubListenerExtra {
+        int fd;
+
+        DnsStubListenerMode mode;
+        SocketAddress address;
+        sd_event_source *dns_stub_extra_event_source;
+} DNSStubListenerExtra;
+
 struct Manager {
         sd_event *event;
 
@@ -137,6 +145,8 @@ struct Manager {
         int dns_stub_udp_fd;
         int dns_stub_tcp_fd;
 
+        OrderedSet *dns_extra_stub_listeners;
+
         sd_event_source *dns_stub_udp_event_source;
         sd_event_source *dns_stub_tcp_event_source;
 
index 224ccffb929b57140844a18aec52d3af1fb9aaee..21a04cfba7c365ad9b1f2eb3aeb2ed032f50860c 100644 (file)
@@ -385,6 +385,7 @@ DNSLifetimeSec=
 DNSSEC=
 DNSSECNegativeTrustAnchors=
 DNSStubListener=
+DNSStubListenerExtra=
 DUIDRawData=
 DUIDType=
 DefaultLeaseTimeSec=