diff options
Diffstat (limited to 'src/resolve')
26 files changed, 199 insertions, 155 deletions
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 07e4cd7d1d..9d4d04220c 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -395,7 +395,7 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) { return 0; } -static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) { +static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char ifname[IF_NAMESIZE] = ""; @@ -430,7 +430,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { - log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); + if (warn_missing || r != -ENXIO) + log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); return r; } @@ -488,7 +489,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ return bus_log_parse_error(r); if (n == 0) { - log_error("%s: no records found", name); + if (warn_missing) + log_error("%s: no records found", name); return -ESRCH; } @@ -618,7 +620,7 @@ static int resolve_rfc4501(sd_bus *bus, const char *name) { if (type == 0) type = arg_type ?: DNS_TYPE_A; - return resolve_record(bus, n, class, type); + return resolve_record(bus, n, class, type, true); invalid: log_error("Invalid DNS URI: %s", name); @@ -778,7 +780,6 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons if (r < 0) return bus_log_parse_error(r); - c = 0; while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) { _cleanup_free_ char *escaped = NULL; @@ -787,7 +788,6 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons return log_oom(); printf("%*s%s\n", (int) indent, "", escaped); - c++; } if (r < 0) return bus_log_parse_error(r); @@ -840,16 +840,34 @@ static int resolve_openpgp(sd_bus *bus, const char *address) { } domain++; - r = string_hashsum_sha224(address, domain - 1 - address, &hashed); + r = string_hashsum_sha256(address, domain - 1 - address, &hashed); if (r < 0) return log_error_errno(r, "Hashing failed: %m"); + strshorten(hashed, 56); + full = strjoina(hashed, "._openpgpkey.", domain); log_debug("Looking up \"%s\".", full); - return resolve_record(bus, full, - arg_class ?: DNS_CLASS_IN, - arg_type ?: DNS_TYPE_OPENPGPKEY); + r = resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, false); + + if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */ + hashed = NULL; + r = string_hashsum_sha224(address, domain - 1 - address, &hashed); + if (r < 0) + return log_error_errno(r, "Hashing failed: %m"); + + full = strjoina(hashed, "._openpgpkey.", domain); + log_debug("Looking up \"%s\".", full); + + return resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, true); + } + + return r; } static int resolve_tlsa(sd_bus *bus, const char *address) { @@ -881,7 +899,7 @@ static int resolve_tlsa(sd_bus *bus, const char *address) { return resolve_record(bus, full, arg_class ?: DNS_CLASS_IN, - arg_type ?: DNS_TYPE_TLSA); + arg_type ?: DNS_TYPE_TLSA, true); } static int show_statistics(sd_bus *bus) { @@ -1877,7 +1895,7 @@ int main(int argc, char **argv) { while (argv[optind]) { int k; - k = resolve_record(bus, argv[optind], arg_class, arg_type); + k = resolve_record(bus, argv[optind], arg_class, arg_type, true); if (r == 0) r = k; diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index dd233e7c4a..abf3263178 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -23,8 +23,19 @@ #include "extract-word.h" #include "parse-util.h" #include "resolved-conf.h" +#include "string-table.h" #include "string-util.h" +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); + int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { union in_addr_union address; int family, r, ifindex = 0; @@ -221,7 +232,7 @@ int manager_parse_config_file(Manager *m) { assert(m); - r = config_parse_many(PKGSYSCONFDIR "/resolved.conf", + r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf", CONF_PATHS_NULSTR("systemd/resolved.conf.d"), "Resolve\0", config_item_perf_lookup, resolved_gperf_lookup, diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index e1fd2cceec..fc425a36b2 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -19,7 +19,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +typedef enum DnsStubListenerMode DnsStubListenerMode; + +enum DnsStubListenerMode { + DNS_STUB_LISTENER_NO, + DNS_STUB_LISTENER_UDP, + DNS_STUB_LISTENER_TCP, + DNS_STUB_LISTENER_YES, + _DNS_STUB_LISTENER_MODE_MAX, + _DNS_STUB_LISTENER_MODE_INVALID = -1 +}; + #include "resolved-manager.h" +#include "resolved-dns-server.h" int manager_parse_config_file(Manager *m); @@ -33,4 +45,7 @@ const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned len int config_parse_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); int config_parse_search_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); -int config_parse_dnssec(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); +int config_parse_dns_stub_listener_mode(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); + +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-packet.c b/src/resolve/resolved-dns-packet.c index a8ad8fe342..337a8c473f 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -2143,7 +2143,7 @@ int dns_packet_extract(DnsPacket *p) { for (i = 0; i < n; i++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; - bool cache_flush; + bool cache_flush = false; r = dns_packet_read_rr(p, &rr, &cache_flush, NULL); if (r < 0) @@ -2289,6 +2289,7 @@ static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = { [DNS_RCODE_BADNAME] = "BADNAME", [DNS_RCODE_BADALG] = "BADALG", [DNS_RCODE_BADTRUNC] = "BADTRUNC", + [DNS_RCODE_BADCOOKIE] = "BADCOOKIE", }; DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int); diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 7b7d4e14c9..054dc88a85 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -263,6 +263,7 @@ enum { DNS_RCODE_BADNAME = 20, DNS_RCODE_BADALG = 21, DNS_RCODE_BADTRUNC = 22, + DNS_RCODE_BADCOOKIE = 23, _DNS_RCODE_MAX_DEFINED, _DNS_RCODE_MAX = 4095 /* 4 bit rcode in the header plus 8 bit rcode in OPT, makes 12 bit */ }; diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 53be18efc6..e03db4d003 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -83,9 +83,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (c->scope) LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); - free(c); - - return NULL; + return mfree(c); } static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { @@ -421,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { q->manager->n_dns_queries--; } - free(q); - - return NULL; + return mfree(q); } int dns_query_new( diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 5687588a7d..87e4abec6e 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -73,10 +73,8 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D return dns_resource_key_ref((DnsResourceKey*) key); k = dns_resource_key_new_consume(key->class, key->type, destination); - if (!k) { - free(destination); - return NULL; - } + if (!k) + return mfree(destination); return k; } @@ -513,9 +511,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { } free(rr->to_string); - free(rr); - - return NULL; + return mfree(rr); } int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index ed0c6aa105..8dbc7f623b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -128,9 +128,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_zone_flush(&s->zone); LIST_REMOVE(scopes, s->manager->dns_scopes, s); - free(s); - - return NULL; + return mfree(s); } DnsServer *dns_scope_get_dns_server(DnsScope *s) { @@ -407,6 +405,7 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { DnsSearchDomain *d; + DnsServer *dns_server; assert(s); assert(domain); @@ -447,6 +446,13 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co if (dns_name_endswith(domain, d->name) > 0) return DNS_SCOPE_YES; + /* If the DNS server has route-only domains, don't send other requests + * to it. This would be a privacy violation, will most probably fail + * anyway, and adds unnecessary load. */ + dns_server = dns_scope_get_dns_server(s); + if (dns_server && dns_server_limited_domains(dns_server)) + return DNS_SCOPE_NO; + switch (s->protocol) { case DNS_PROTOCOL_DNS: diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 538bc61f81..01a83a76b2 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -26,7 +26,10 @@ typedef struct DnsScope DnsScope; #include "resolved-dns-cache.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" +#include "resolved-dns-query.h" +#include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" +#include "resolved-dns-stream.h" #include "resolved-dns-zone.h" #include "resolved-link.h" diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c index 732471027b..1386e6a17b 100644 --- a/src/resolve/resolved-dns-search-domain.c +++ b/src/resolve/resolved-dns-search-domain.c @@ -104,9 +104,7 @@ DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) { return NULL; free(d->name); - free(d); - - return NULL; + return mfree(d); } void dns_search_domain_unlink(DnsSearchDomain *d) { diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 9b7b471600..22c64e8491 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -139,8 +139,7 @@ DnsServer* dns_server_unref(DnsServer *s) { return NULL; free(s->server_string); - free(s); - return NULL; + return mfree(s); } void dns_server_unlink(DnsServer *s) { @@ -576,6 +575,26 @@ void dns_server_warn_downgrade(DnsServer *server) { server->warned_downgrade = true; } +bool dns_server_limited_domains(DnsServer *server) { + DnsSearchDomain *domain; + bool domain_restricted = false; + + /* Check if the server has route-only domains without ~., i. e. whether + * it should only be used for particular domains */ + if (!server->link) + return false; + + LIST_FOREACH(domains, domain, server->link->search_domains) + if (domain->route_only) { + domain_restricted = true; + /* ~. means "any domain", thus it is a global server */ + if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain))) + return false; + } + + return domain_restricted; +} + static void dns_server_hash_func(const void *p, struct siphash *state) { const DnsServer *s = p; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index c1732faffd..83e288a202 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -128,6 +128,8 @@ bool dns_server_dnssec_supported(DnsServer *server); void dns_server_warn_downgrade(DnsServer *server); +bool dns_server_limited_domains(DnsServer *server); + DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex); void dns_server_unlink_all(DnsServer *first); diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index dd0e0b90e3..878bae47dc 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -343,9 +343,7 @@ DnsStream *dns_stream_unref(DnsStream *s) { dns_packet_unref(s->write_packet); dns_packet_unref(s->read_packet); - free(s); - - return NULL; + return mfree(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref); diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h index e6569678fa..4cdb4f6806 100644 --- a/src/resolve/resolved-dns-stream.h +++ b/src/resolve/resolved-dns-stream.h @@ -25,6 +25,7 @@ typedef struct DnsStream DnsStream; #include "resolved-dns-packet.h" #include "resolved-dns-transaction.h" +#include "resolved-manager.h" /* Streams are used by three subsystems: * diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index d263cedcd9..e76de6c06a 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -25,6 +25,9 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) +static int manager_dns_stub_udp_fd(Manager *m); +static int manager_dns_stub_tcp_fd(Manager *m); + static int dns_stub_make_reply_packet( uint16_t id, int rcode, @@ -354,66 +357,48 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void return 0; } -int manager_dns_stub_udp_fd(Manager *m) { +static int manager_dns_stub_udp_fd(Manager *m) { static const int one = 1; - union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(53), .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), }; - + _cleanup_close_ int fd = -1; int r; if (m->dns_stub_udp_fd >= 0) return m->dns_stub_udp_fd; - m->dns_stub_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (m->dns_stub_udp_fd < 0) + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) return -errno; - r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0) + return -errno; /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0) + return -errno; - r = bind(m->dns_stub_udp_fd, &sa.sa, sizeof(sa.in)); - if (r < 0) { - r = -errno; - goto fail; - } + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; - r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, m->dns_stub_udp_fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); if (r < 0) - goto fail; + return r; (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp"); + m->dns_stub_udp_fd = fd; + fd = -1; return m->dns_stub_udp_fd; - -fail: - m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); - return r; } static int on_dns_stub_stream_packet(DnsStream *s) { @@ -461,102 +446,83 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void return 0; } -int manager_dns_stub_tcp_fd(Manager *m) { +static int manager_dns_stub_tcp_fd(Manager *m) { static const int one = 1; - union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), .in.sin_port = htobe16(53), }; - + _cleanup_close_ int fd = -1; int r; if (m->dns_stub_tcp_fd >= 0) return m->dns_stub_tcp_fd; - m->dns_stub_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (m->dns_stub_tcp_fd < 0) + fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0) + return -errno; /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0) + return -errno; - r = bind(m->dns_stub_tcp_fd, &sa.sa, sizeof(sa.in)); - if (r < 0) { - r = -errno; - goto fail; - } + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; - r = listen(m->dns_stub_tcp_fd, SOMAXCONN); - if (r < 0) { - r = -errno; - goto fail; - } + if (listen(fd, SOMAXCONN) < 0) + return -errno; - r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, m->dns_stub_tcp_fd, EPOLLIN, on_dns_stub_stream, m); + r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m); if (r < 0) - goto fail; + return r; (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); + m->dns_stub_tcp_fd = fd; + fd = -1; return m->dns_stub_tcp_fd; - -fail: - m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); - return r; } int manager_dns_stub_start(Manager *m) { - int r; + const char *t = "UDP"; + int r = 0; assert(m); - r = manager_dns_stub_udp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; - - r = manager_dns_stub_tcp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; + if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) + r = manager_dns_stub_udp_fd(m); - return 0; + if (r >= 0 && + IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + t = "TCP"; + r = manager_dns_stub_tcp_fd(m); + } -eaddrinuse: - log_warning("Another process is already listening on 127.0.0.53:53. Turning off local DNS stub support."); - manager_dns_stub_stop(m); + if (IN_SET(r, -EADDRINUSE, -EPERM)) { + if (r == -EADDRINUSE) + log_warning_errno(r, + "Another process is already listening on %s socket 127.0.0.53:53.\n" + "Turning off local DNS stub support.", t); + else + log_warning_errno(r, + "Failed to listen on %s socket 127.0.0.53:53: %m.\n" + "Turning off local DNS stub support.", t); + manager_dns_stub_stop(m); + } else if (r < 0) + return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); return 0; } diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index fce4d25ede..12b86f6753 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -24,8 +24,5 @@ /* 127.0.0.53 in native endian */ #define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U) -int manager_dns_stub_udp_fd(Manager *m); -int manager_dns_stub_tcp_fd(Manager *m); - void manager_dns_stub_stop(Manager *m); int manager_dns_stub_start(Manager *m); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index d455b6b1fa..2fce44ec8b 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -134,8 +134,7 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) { dns_answer_unref(t->validated_keys); dns_resource_key_unref(t->key); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index 96b066845d..5a1df70422 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -59,6 +59,8 @@ enum DnsTransactionSource { #include "resolved-dns-packet.h" #include "resolved-dns-question.h" #include "resolved-dns-scope.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stream.h" struct DnsTransaction { DnsScope *scope; diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index 77370e7dd5..9917b9e984 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -127,6 +127,9 @@ static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) { "31.172.in-addr.arpa\0" "168.192.in-addr.arpa\0" + /* The same, but for IPv6. */ + "d.f.ip6.arpa\0" + /* RFC 6762 reserves the .local domain for Multicast * DNS, it hence cannot appear in the root zone. (Note * that we by default do not route .local traffic to diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf index 2fd56bce26..446f85cdf4 100644 --- a/src/resolve/resolved-gperf.gperf +++ b/src/resolve/resolved-gperf.gperf @@ -14,9 +14,10 @@ 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.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) -Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache) +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.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) +Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache) +Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index ea4a007139..13e1f91192 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -101,8 +101,7 @@ Link *link_free(Link *l) { free(l->state_file); - free(l); - return NULL; + return mfree(l); } void link_allocate_scopes(Link *l) { @@ -698,8 +697,7 @@ LinkAddress *link_address_free(LinkAddress *a) { dns_resource_record_unref(a->llmnr_address_rr); dns_resource_record_unref(a->llmnr_ptr_rr); - free(a); - return NULL; + return mfree(a); } void link_address_add_rrs(LinkAddress *a, bool force_remove) { diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 6a2343f9f7..c9b2a58c34 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -29,6 +29,7 @@ typedef struct Link Link; typedef struct LinkAddress LinkAddress; #include "resolved-dns-rr.h" +#include "resolved-dns-scope.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" #include "resolved-manager.h" diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 9bb623c321..6630585d13 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -501,6 +501,7 @@ int manager_new(Manager **ret) { m->mdns_support = RESOLVE_SUPPORT_NO; m->dnssec_mode = DEFAULT_DNSSEC_MODE; m->enable_cache = true; + m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP; m->read_resolv_conf = true; m->need_builtin_fallbacks = true; m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY; @@ -629,9 +630,7 @@ Manager *manager_free(Manager *m) { dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); - free(m); - - return NULL; + return mfree(m); } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index deebd8e484..6b2208ed94 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -30,6 +30,7 @@ typedef struct Manager Manager; +#include "resolved-conf.h" #include "resolved-dns-query.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" @@ -47,6 +48,7 @@ struct Manager { ResolveSupport mdns_support; DnssecMode dnssec_mode; bool enable_cache; + DnsStubListenerMode dns_stub_listener_mode; /* Network */ Hashmap *links; diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 31b25ca50f..801014caf5 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -154,6 +154,16 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { return; } + /* Check if the DNS server is limited to particular domains; + * resolv.conf does not have a syntax to express that, so it must not + * appear as a global name server to avoid routing unrelated domains to + * it (which is a privacy violation, will most probably fail anyway, + * and adds unnecessary load) */ + if (dns_server_limited_domains(s)) { + log_debug("DNS server %s has route-only domains, not using as global name server", dns_server_string(s)); + return; + } + if (*count == MAXNS) fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f); (*count)++; diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in index 3bd8389c88..60afa151e3 100644 --- a/src/resolve/resolved.conf.in +++ b/src/resolve/resolved.conf.in @@ -18,3 +18,4 @@ #LLMNR=yes #DNSSEC=@DEFAULT_DNSSEC_MODE@ #Cache=yes +#DNSStubListener=udp |