From 36aaabc35e524184a896e1505997b6a3b526b889 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Sep 2020 19:00:47 +0200 Subject: [PATCH 1/3] =?UTF-8?q?resolve:=20DNSStubListenerExtra=20=E2=86=92?= =?UTF-8?q?=20DnsStubListenerExtra?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All our other struct types use the "Dns" spelling, rather than "DNS". Do the same for this struct. --- src/resolve/resolved-conf.c | 8 ++++---- src/resolve/resolved-dns-stub.c | 14 +++++++------- src/resolve/resolved-dns-stub.h | 4 ++-- src/resolve/resolved-manager.h | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 639fd34178..68fb9c918b 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -29,7 +29,7 @@ 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) { +static void dns_stub_listener_extra_hash_func(const DnsStubListenerExtra *a, struct siphash *state) { assert(a); siphash24_compress(&a->mode, sizeof(a->mode), state); @@ -38,7 +38,7 @@ static void dns_stub_listener_extra_hash_func(const DNSStubListenerExtra *a, str siphash24_compress(&a->port, sizeof(a->port), state); } -static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) { +static int dns_stub_listener_extra_compare_func(const DnsStubListenerExtra *a, const DnsStubListenerExtra *b) { int r; assert(a); @@ -61,7 +61,7 @@ static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, c DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( dns_stub_listener_extra_hash_ops, - DNSStubListenerExtra, + DnsStubListenerExtra, dns_stub_listener_extra_hash_func, dns_stub_listener_extra_compare_func, dns_stub_listener_extra_free); @@ -436,7 +436,7 @@ int config_parse_dns_stub_listener_extra( void *data, void *userdata) { - _cleanup_free_ DNSStubListenerExtra *stub = NULL; + _cleanup_free_ DnsStubListenerExtra *stub = NULL; Manager *m = userdata; const char *p; int r; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index b09cbcff64..68b8678b5f 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -14,10 +14,10 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) -int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) { - DNSStubListenerExtra *l; +int dns_stub_listener_extra_new(DnsStubListenerExtra **ret) { + DnsStubListenerExtra *l; - l = new0(DNSStubListenerExtra, 1); + l = new0(DnsStubListenerExtra, 1); if (!l) return -ENOMEM; @@ -26,7 +26,7 @@ int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) { return 0; } -DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p) { +DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) { if (!p) return NULL; @@ -483,7 +483,7 @@ static int manager_dns_stub_udp_fd(Manager *m) { return TAKE_FD(fd); } -static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { +static int manager_dns_stub_udp_fd_extra(Manager *m, DnsStubListenerExtra *l) { _cleanup_free_ char *pretty = NULL; _cleanup_close_ int fd = -1; union sockaddr_union sa; @@ -659,7 +659,7 @@ static int manager_dns_stub_tcp_fd(Manager *m) { return TAKE_FD(fd); } -static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { +static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { _cleanup_free_ char *pretty = NULL; _cleanup_close_ int fd = -1; union sockaddr_union sa; @@ -773,7 +773,7 @@ int manager_dns_stub_start(Manager *m) { 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; + DnsStubListenerExtra *l; log_debug("Creating extra stub listeners."); diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index 96d65af152..c3b4c5afd9 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -3,8 +3,8 @@ #include "resolved-manager.h" -int dns_stub_listener_extra_new(DNSStubListenerExtra **ret); -DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p); +int dns_stub_listener_extra_new(DnsStubListenerExtra **ret); +DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p); void manager_dns_stub_stop(Manager *m); int manager_dns_stub_start(Manager *m); diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 80665876b2..905b55aa7a 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -31,7 +31,7 @@ typedef struct EtcHosts { Set *no_address; } EtcHosts; -typedef struct DNSStubListenerExtra { +typedef struct DnsStubListenerExtra { DnsStubListenerMode mode; int family; @@ -40,7 +40,7 @@ typedef struct DNSStubListenerExtra { sd_event_source *udp_event_source; sd_event_source *tcp_event_source; -} DNSStubListenerExtra; +} DnsStubListenerExtra; struct Manager { sd_event *event; From ae8f0ec323f3cc1b75e2d25d4832fd9bc232261b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Sep 2020 19:13:29 +0200 Subject: [PATCH 2/3] resolved: move dns stub definitions to resolved-dns-stub.[ch] Just some moving around, no logic changes. --- src/resolve/resolved-conf.c | 45 ------------------------------- src/resolve/resolved-conf.h | 14 ---------- src/resolve/resolved-dns-stub.c | 47 +++++++++++++++++++++++++++++++++ src/resolve/resolved-dns-stub.h | 29 ++++++++++++++++++++ src/resolve/resolved-dnssd.c | 1 + src/resolve/resolved-manager.h | 13 +-------- 6 files changed, 78 insertions(+), 71 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 68fb9c918b..6caae5d111 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -21,51 +21,6 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); -static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { - [DNS_STUB_LISTENER_NO] = "no", - [DNS_STUB_LISTENER_UDP] = "udp", - [DNS_STUB_LISTENER_TCP] = "tcp", - [DNS_STUB_LISTENER_YES] = "yes", -}; -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) { - assert(a); - - siphash24_compress(&a->mode, sizeof(a->mode), state); - siphash24_compress(&a->family, sizeof(a->family), state); - siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); - siphash24_compress(&a->port, sizeof(a->port), state); -} - -static int dns_stub_listener_extra_compare_func(const DnsStubListenerExtra *a, const DnsStubListenerExtra *b) { - int r; - - assert(a); - assert(b); - - r = CMP(a->mode, b->mode); - if (r != 0) - return r; - - r = CMP(a->family, b->family); - if (r != 0) - return r; - - r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); - if (r != 0) - return r; - - return CMP(a->port, b->port); -} - -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, - dns_stub_listener_extra_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; diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index 50a0caaf16..09ae8d7a5b 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -3,17 +3,6 @@ #include "conf-parser.h" -typedef enum DnsStubListenerMode DnsStubListenerMode; - -enum DnsStubListenerMode { - DNS_STUB_LISTENER_NO, - DNS_STUB_LISTENER_UDP = 1 << 0, - DNS_STUB_LISTENER_TCP = 1 << 1, - DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP, - _DNS_STUB_LISTENER_MODE_MAX, - _DNS_STUB_LISTENER_MODE_INVALID = -1 -}; - #include "resolved-dns-server.h" int manager_parse_config_file(Manager *m); @@ -31,6 +20,3 @@ 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_; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 68b8678b5f..c89bf6c13f 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -9,12 +9,51 @@ #include "resolved-dns-stub.h" #include "socket-netlink.h" #include "socket-util.h" +#include "string-table.h" /* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet, * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) +static void dns_stub_listener_extra_hash_func(const DnsStubListenerExtra *a, struct siphash *state) { + assert(a); + + siphash24_compress(&a->mode, sizeof(a->mode), state); + siphash24_compress(&a->family, sizeof(a->family), state); + siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); + siphash24_compress(&a->port, sizeof(a->port), state); +} + +static int dns_stub_listener_extra_compare_func(const DnsStubListenerExtra *a, const DnsStubListenerExtra *b) { + int r; + + assert(a); + assert(b); + + r = CMP(a->mode, b->mode); + if (r != 0) + return r; + + r = CMP(a->family, b->family); + if (r != 0) + return r; + + r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + return CMP(a->port, b->port); +} + +DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( + dns_stub_listener_extra_hash_ops, + DnsStubListenerExtra, + dns_stub_listener_extra_hash_func, + dns_stub_listener_extra_compare_func, + dns_stub_listener_extra_free); + int dns_stub_listener_extra_new(DnsStubListenerExtra **ret) { + DnsStubListenerExtra *l; l = new0(DnsStubListenerExtra, 1); @@ -794,3 +833,11 @@ void manager_dns_stub_stop(Manager *m) { m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source); m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source); } + +static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { + [DNS_STUB_LISTENER_NO] = "no", + [DNS_STUB_LISTENER_UDP] = "udp", + [DNS_STUB_LISTENER_TCP] = "tcp", + [DNS_STUB_LISTENER_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index c3b4c5afd9..0ff0289550 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -1,10 +1,39 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include "hash-funcs.h" + +typedef struct DnsStubListenerExtra DnsStubListenerExtra; + +typedef enum DnsStubListenerMode { + DNS_STUB_LISTENER_NO, + DNS_STUB_LISTENER_UDP = 1 << 0, + DNS_STUB_LISTENER_TCP = 1 << 1, + DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP, + _DNS_STUB_LISTENER_MODE_MAX, + _DNS_STUB_LISTENER_MODE_INVALID = -1 +} DnsStubListenerMode; + #include "resolved-manager.h" +struct DnsStubListenerExtra { + DnsStubListenerMode mode; + + int family; + union in_addr_union address; + uint16_t port; + + sd_event_source *udp_event_source; + sd_event_source *tcp_event_source; +}; + +extern const struct hash_ops dns_stub_listener_extra_hash_ops; + int dns_stub_listener_extra_new(DnsStubListenerExtra **ret); DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p); void manager_dns_stub_stop(Manager *m); int manager_dns_stub_start(Manager *m); + +const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; +DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c index 7d482ac5da..945be07740 100644 --- a/src/resolve/resolved-dnssd.c +++ b/src/resolve/resolved-dnssd.c @@ -6,6 +6,7 @@ #include "resolved-dnssd.h" #include "resolved-dns-rr.h" #include "resolved-manager.h" +#include "resolved-conf.h" #include "specifier.h" #include "strv.h" diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 905b55aa7a..c30052195a 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -15,10 +15,10 @@ typedef struct Manager Manager; -#include "resolved-conf.h" #include "resolved-dns-query.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-stream.h" +#include "resolved-dns-stub.h" #include "resolved-dns-trust-anchor.h" #include "resolved-link.h" @@ -31,17 +31,6 @@ typedef struct EtcHosts { Set *no_address; } EtcHosts; -typedef struct DnsStubListenerExtra { - DnsStubListenerMode mode; - - int family; - union in_addr_union address; - uint16_t port; - - sd_event_source *udp_event_source; - sd_event_source *tcp_event_source; -} DnsStubListenerExtra; - struct Manager { sd_event *event; From 0354029bf572489bf968a39c537ec0cbdef828ce Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Sep 2020 19:41:44 +0200 Subject: [PATCH 3/3] resolved: don't store udp/tcp fd in DnsPacket object DnsPacket should better be a "dead" object, i.e. list facts, not track resources. By including an fd in its fields it started tracking resources however, without actually taking a ref to the fd (i.e. no dup() or so was called on it). Let's hence rework things so that we don#t have to keep track of the fd a packet came in from. Instead, pass around the DnsStubListenerExtra object wherever we need to. This should be useful as soon as we start caching whole DnsPacket objects to allow replying to DNSSEC/CO packets, i.e. where we have to keep a copy of the original DnsPacket around for a long time in cache, potentially much longer than the fds the packet was received on. --- src/resolve/resolved-conf.c | 2 +- src/resolve/resolved-dns-packet.h | 1 - src/resolve/resolved-dns-query.h | 2 + src/resolve/resolved-dns-stream.h | 3 + src/resolve/resolved-dns-stub.c | 120 ++++++++++++++++++------------ src/resolve/resolved-dns-stub.h | 4 +- src/resolve/resolved-manager.c | 1 - 7 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 6caae5d111..184df0337f 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -406,7 +406,7 @@ int config_parse_dns_stub_listener_extra( return 0; } - r = dns_stub_listener_extra_new(&stub); + r = dns_stub_listener_extra_new(m, &stub); if (r < 0) return log_oom(); diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 359cdcfd04..56614c4a07 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -66,7 +66,6 @@ struct DnsPacket { DnsResourceRecord *opt; /* Packet reception metadata */ - int fd; /* Used by UDP extra DNS stub listners */ int ifindex; int family, ipproto; union in_addr_union sender, destination; diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h index 95e5f5bbeb..36a9b7be8f 100644 --- a/src/resolve/resolved-dns-query.h +++ b/src/resolve/resolved-dns-query.h @@ -8,6 +8,7 @@ typedef struct DnsQueryCandidate DnsQueryCandidate; typedef struct DnsQuery DnsQuery; +typedef struct DnsStubListenerExtra DnsStubListenerExtra; #include "resolved-dns-answer.h" #include "resolved-dns-question.h" @@ -82,6 +83,7 @@ struct DnsQuery { DnsPacket *request_dns_packet; DnsStream *request_dns_stream; DnsPacket *reply_dns_packet; + DnsStubListenerExtra *stub_listener_extra; /* Completion callback */ void (*complete)(DnsQuery* q); diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h index 9fd8f5a342..de193931c1 100644 --- a/src/resolve/resolved-dns-stream.h +++ b/src/resolve/resolved-dns-stream.h @@ -10,6 +10,7 @@ typedef struct DnsServer DnsServer; typedef struct DnsStream DnsStream; typedef struct DnsTransaction DnsTransaction; typedef struct Manager Manager; +typedef struct DnsStubListenerExtra DnsStubListenerExtra; #include "resolved-dns-packet.h" #include "resolved-dnstls.h" @@ -75,6 +76,8 @@ struct DnsStream { /* used when DNS-over-TLS is enabled */ bool encrypted:1; + DnsStubListenerExtra *stub_listener_extra; + LIST_FIELDS(DnsStream, streams); }; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index c89bf6c13f..59ced33847 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -15,6 +15,8 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) +static int manager_dns_stub_udp_fd_extra(Manager *m, DnsStubListenerExtra *l); + static void dns_stub_listener_extra_hash_func(const DnsStubListenerExtra *a, struct siphash *state) { assert(a); @@ -52,16 +54,21 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( dns_stub_listener_extra_compare_func, dns_stub_listener_extra_free); -int dns_stub_listener_extra_new(DnsStubListenerExtra **ret) { +int dns_stub_listener_extra_new( + Manager *m, + DnsStubListenerExtra **ret) { DnsStubListenerExtra *l; - l = new0(DnsStubListenerExtra, 1); + l = new(DnsStubListenerExtra, 1); if (!l) return -ENOMEM; - *ret = TAKE_PTR(l); + *l = (DnsStubListenerExtra) { + .manager = m, + }; + *ret = TAKE_PTR(l); return 0; } @@ -190,7 +197,13 @@ static int dns_stub_finish_reply_packet( return 0; } -static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *reply) { +static int dns_stub_send( + Manager *m, + DnsStubListenerExtra *l, + DnsStream *s, + DnsPacket *p, + DnsPacket *reply) { + int r; assert(m); @@ -199,20 +212,29 @@ static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *repl if (s) r = dns_stream_write_packet(s, reply); - else { + else /* Note that it is essential here that we explicitly choose the source IP address for this packet. This * is because otherwise the kernel will choose it automatically based on the routing table and will * thus pick 127.0.0.1 rather than 127.0.0.53. */ - - r = manager_send(m, p->fd, p->ifindex, p->family, &p->sender, p->sender_port, &p->destination, reply); - } + r = manager_send(m, + manager_dns_stub_udp_fd_extra(m, l), + l ? p->ifindex : LOOPBACK_IFINDEX, /* force loopback iface if this is the main listener stub */ + p->family, &p->sender, p->sender_port, &p->destination, + reply); if (r < 0) return log_debug_errno(r, "Failed to send reply packet: %m"); return 0; } -static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rcode, bool authenticated) { +static int dns_stub_send_failure( + Manager *m, + DnsStubListenerExtra *l, + DnsStream *s, + DnsPacket *p, + int rcode, + bool authenticated) { + _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; int r; @@ -227,7 +249,7 @@ static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rco if (r < 0) return log_debug_errno(r, "Failed to build failure packet: %m"); - return dns_stub_send(m, s, p, reply); + return dns_stub_send(m, l, s, p, reply); } static void dns_stub_query_complete(DnsQuery *q) { @@ -250,7 +272,7 @@ static void dns_stub_query_complete(DnsQuery *q) { if (!truncated) { r = dns_query_process_cname(q); if (r == -ELOOP) { - (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); + (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); break; } if (r < 0) { @@ -274,16 +296,16 @@ static void dns_stub_query_complete(DnsQuery *q) { break; } - (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); + (void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); break; } case DNS_TRANSACTION_RCODE_FAILURE: - (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q)); + (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q)); break; case DNS_TRANSACTION_NOT_FOUND: - (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q)); + (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q)); break; case DNS_TRANSACTION_TIMEOUT: @@ -299,7 +321,7 @@ static void dns_stub_query_complete(DnsQuery *q) { case DNS_TRANSACTION_NO_TRUST_ANCHOR: case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: case DNS_TRANSACTION_NETWORK_DOWN: - (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); + (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); break; case DNS_TRANSACTION_NULL: @@ -333,7 +355,7 @@ static int dns_stub_stream_complete(DnsStream *s, int error) { return 0; } -static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool is_extra) { +static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStream *s, DnsPacket *p) { _cleanup_(dns_query_freep) DnsQuery *q = NULL; int r; @@ -341,56 +363,56 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool assert(p); assert(p->protocol == DNS_PROTOCOL_DNS); - if (!is_extra && + if (!l && /* l == NULL if this is the main stub */ (in_addr_is_localhost(p->family, &p->sender) <= 0 || in_addr_is_localhost(p->family, &p->destination) <= 0)) { log_error("Got packet on unexpected IP range, refusing."); - dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); return; } r = dns_packet_extract(p); if (r < 0) { log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m"); - dns_stub_send_failure(m, s, p, DNS_RCODE_FORMERR, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_FORMERR, false); return; } if (!DNS_PACKET_VERSION_SUPPORTED(p)) { log_debug("Got EDNS OPT field with unsupported version number."); - dns_stub_send_failure(m, s, p, DNS_RCODE_BADVERS, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_BADVERS, false); return; } if (dns_type_is_obsolete(p->question->keys[0]->type)) { log_debug("Got message with obsolete key type, refusing."); - dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); return; } if (dns_type_is_zone_transer(p->question->keys[0]->type)) { log_debug("Got request for zone transfer, refusing."); - dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); return; } if (!DNS_PACKET_RD(p)) { /* If the "rd" bit is off (i.e. recursion was not requested), then refuse operation */ log_debug("Got request with recursion disabled, refusing."); - dns_stub_send_failure(m, s, p, DNS_RCODE_REFUSED, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false); return; } if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) { log_debug("Got request with DNSSEC CD bit set, refusing."); - dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); return; } r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH); if (r < 0) { log_error_errno(r, "Failed to generate query object: %m"); - dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); return; } @@ -399,6 +421,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool q->request_dns_packet = dns_packet_ref(p); q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */ + q->stub_listener_extra = l; q->complete = dns_stub_query_complete; if (s) { @@ -416,7 +439,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool r = dns_query_go(q); if (r < 0) { log_error_errno(r, "Failed to start query: %m"); - dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); return; } @@ -424,7 +447,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool TAKE_PTR(q); } -static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) { +static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, DnsStubListenerExtra *l) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; int r; @@ -435,7 +458,7 @@ static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t reve if (dns_packet_validate_query(p) > 0) { log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p)); - dns_stub_process_query(m, NULL, p, is_extra); + dns_stub_process_query(m, l, NULL, p); } else log_debug("Invalid DNS stub UDP packet, ignoring."); @@ -443,11 +466,15 @@ static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t reve } static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - return on_dns_stub_packet_internal(s, fd, revents, userdata, false); + return on_dns_stub_packet_internal(s, fd, revents, userdata, NULL); } static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - return on_dns_stub_packet_internal(s, fd, revents, userdata, true); + DnsStubListenerExtra *l = userdata; + + assert(l); + + return on_dns_stub_packet_internal(s, fd, revents, l->manager, l); } static int set_dns_stub_common_socket_options(int fd, int family) { @@ -528,6 +555,11 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DnsStubListenerExtra *l) { union sockaddr_union sa; int r; + assert(m); + + if (!l) + return manager_dns_stub_udp_fd(m); + if (l->udp_event_source) return 0; @@ -565,7 +597,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DnsStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, m); + r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, l); if (r < 0) goto fail; @@ -590,7 +622,7 @@ fail: return log_warning_errno(r, "Failed to listen on UDP socket %s: %m", strnull(pretty)); } -static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) { +static int on_dns_stub_stream_packet(DnsStream *s) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; assert(s); @@ -601,22 +633,14 @@ static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) { if (dns_packet_validate_query(p) > 0) { log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p)); - dns_stub_process_query(s->manager, s, p, is_extra); + dns_stub_process_query(s->manager, s->stub_listener_extra, s, p); } else log_debug("Invalid DNS stub TCP packet, ignoring."); return 0; } -static int on_dns_stub_stream_packet(DnsStream *s) { - return on_dns_stub_stream_packet_internal(s, false); -} - -static int on_dns_stub_stream_packet_extra(DnsStream *s) { - return on_dns_stub_stream_packet_internal(s, true); -} - -static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) { +static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, DnsStubListenerExtra *l) { DnsStream *stream; int cfd, r; @@ -634,7 +658,8 @@ static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t reve return r; } - stream->on_packet = is_extra ? on_dns_stub_stream_packet_extra : on_dns_stub_stream_packet; + stream->stub_listener_extra = l; + stream->on_packet = on_dns_stub_stream_packet; stream->complete = dns_stub_stream_complete; /* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */ @@ -643,11 +668,14 @@ static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t reve } static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - return on_dns_stub_stream_internal(s, fd, revents, userdata, false); + return on_dns_stub_stream_internal(s, fd, revents, userdata, NULL); } static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - return on_dns_stub_stream_internal(s, fd, revents, userdata, true); + DnsStubListenerExtra *l = userdata; + + assert(l); + return on_dns_stub_stream_internal(s, fd, revents, l->manager, l); } static int manager_dns_stub_tcp_fd(Manager *m) { @@ -750,7 +778,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, m); + r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, l); if (r < 0) goto fail; diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index 0ff0289550..6686de5e58 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -17,6 +17,8 @@ typedef enum DnsStubListenerMode { #include "resolved-manager.h" struct DnsStubListenerExtra { + Manager *manager; + DnsStubListenerMode mode; int family; @@ -29,7 +31,7 @@ struct DnsStubListenerExtra { extern const struct hash_ops dns_stub_listener_extra_hash_ops; -int dns_stub_listener_extra_new(DnsStubListenerExtra **ret); +int dns_stub_listener_extra_new(Manager *m, DnsStubListenerExtra **ret); DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p); void manager_dns_stub_stop(Manager *m); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 3e63f90dda..97e046c647 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -788,7 +788,6 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { p->size = (size_t) l; - p->fd = fd; p->family = sa.sa.sa_family; p->ipproto = IPPROTO_UDP; if (p->family == AF_INET) {