summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/resolve-tool.c44
-rw-r--r--src/resolve/resolved-conf.c13
-rw-r--r--src/resolve/resolved-conf.h17
-rw-r--r--src/resolve/resolved-dns-packet.c3
-rw-r--r--src/resolve/resolved-dns-packet.h1
-rw-r--r--src/resolve/resolved-dns-query.c8
-rw-r--r--src/resolve/resolved-dns-rr.c10
-rw-r--r--src/resolve/resolved-dns-scope.c12
-rw-r--r--src/resolve/resolved-dns-scope.h3
-rw-r--r--src/resolve/resolved-dns-search-domain.c4
-rw-r--r--src/resolve/resolved-dns-server.c23
-rw-r--r--src/resolve/resolved-dns-server.h2
-rw-r--r--src/resolve/resolved-dns-stream.c4
-rw-r--r--src/resolve/resolved-dns-stream.h1
-rw-r--r--src/resolve/resolved-dns-stub.c162
-rw-r--r--src/resolve/resolved-dns-stub.h3
-rw-r--r--src/resolve/resolved-dns-transaction.c3
-rw-r--r--src/resolve/resolved-dns-transaction.h2
-rw-r--r--src/resolve/resolved-dns-trust-anchor.c3
-rw-r--r--src/resolve/resolved-gperf.gperf13
-rw-r--r--src/resolve/resolved-link.c6
-rw-r--r--src/resolve/resolved-link.h1
-rw-r--r--src/resolve/resolved-manager.c5
-rw-r--r--src/resolve/resolved-manager.h2
-rw-r--r--src/resolve/resolved-resolv-conf.c10
-rw-r--r--src/resolve/resolved.conf.in1
26 files changed, 200 insertions, 156 deletions
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 6ae3750417..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) {
@@ -1542,7 +1560,7 @@ static void help(void) {
"%1$s [OPTIONS...] --statistics\n"
"%1$s [OPTIONS...] --reset-statistics\n"
"\n"
- "Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
+ "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
@@ -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