summaryrefslogtreecommitdiff
path: root/src/grp-resolve
diff options
context:
space:
mode:
Diffstat (limited to 'src/grp-resolve')
-rw-r--r--src/grp-resolve/libbasic-dns/include/basic-dns/resolved-dns-packet.h1
-rw-r--r--src/grp-resolve/libbasic-dns/src/resolved-dns-packet.c3
-rw-r--r--src/grp-resolve/libbasic-dns/src/resolved-dns-rr.c10
-rw-r--r--src/grp-resolve/nss-resolve/Makefile2
-rw-r--r--src/grp-resolve/nss-resolve/nss-resolve.c20
-rw-r--r--src/grp-resolve/nss-resolve/nss-resolve.xml11
-rw-r--r--src/grp-resolve/systemd-resolve/resolve-tool.c44
-rw-r--r--src/grp-resolve/systemd-resolve/systemd-resolve.completion.bash4
-rw-r--r--src/grp-resolve/systemd-resolve/systemd-resolve.xml4
-rw-r--r--src/grp-resolve/systemd-resolved/dnssec-trust-anchors.d.xml14
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-conf.c13
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-conf.h17
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-query.c8
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-scope.c12
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-scope.h2
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-search-domain.c4
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-server.c23
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-server.h2
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-stream.c4
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-stub.c162
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-stub.h3
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-transaction.c3
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-transaction.h2
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-trust-anchor.c3
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-gperf.gperf13
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-link.c6
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-manager.c5
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-manager.h2
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-resolv-conf.c10
-rw-r--r--src/grp-resolve/systemd-resolved/resolved.conf.in1
-rw-r--r--src/grp-resolve/systemd-resolved/resolved.conf.xml14
-rw-r--r--src/grp-resolve/systemd-resolved/systemd-resolved.service.m4.in8
-rw-r--r--src/grp-resolve/systemd-resolved/systemd-resolved.service.xml8
33 files changed, 252 insertions, 186 deletions
diff --git a/src/grp-resolve/libbasic-dns/include/basic-dns/resolved-dns-packet.h b/src/grp-resolve/libbasic-dns/include/basic-dns/resolved-dns-packet.h
index cb03de8986..8fc031e013 100644
--- a/src/grp-resolve/libbasic-dns/include/basic-dns/resolved-dns-packet.h
+++ b/src/grp-resolve/libbasic-dns/include/basic-dns/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/grp-resolve/libbasic-dns/src/resolved-dns-packet.c b/src/grp-resolve/libbasic-dns/src/resolved-dns-packet.c
index e142832211..6f356cba7d 100644
--- a/src/grp-resolve/libbasic-dns/src/resolved-dns-packet.c
+++ b/src/grp-resolve/libbasic-dns/src/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/grp-resolve/libbasic-dns/src/resolved-dns-rr.c b/src/grp-resolve/libbasic-dns/src/resolved-dns-rr.c
index 35d389b802..c6ec81ead6 100644
--- a/src/grp-resolve/libbasic-dns/src/resolved-dns-rr.c
+++ b/src/grp-resolve/libbasic-dns/src/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/grp-resolve/nss-resolve/Makefile b/src/grp-resolve/nss-resolve/Makefile
index f1456dd725..310f816b06 100644
--- a/src/grp-resolve/nss-resolve/Makefile
+++ b/src/grp-resolve/nss-resolve/Makefile
@@ -40,7 +40,7 @@ libnss_resolve_la_LIBADD = \
libsystemd-basic.la \
-ldl
-lib_LTLIBRARIES += \
+rootlib_LTLIBRARIES += \
libnss_resolve.la
include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-resolve/nss-resolve/nss-resolve.c b/src/grp-resolve/nss-resolve/nss-resolve.c
index 49ca4767e2..681416e18f 100644
--- a/src/grp-resolve/nss-resolve/nss-resolve.c
+++ b/src/grp-resolve/nss-resolve/nss-resolve.c
@@ -121,6 +121,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ enum nss_status ret = NSS_STATUS_UNAVAIL;
const char *canonical = NULL;
size_t l, ms, idx;
char *r_name;
@@ -167,6 +168,10 @@ enum nss_status _nss_resolve_gethostbyname4_r(
if (bus_error_shall_fallback(&error))
goto fallback;
+ /* Treat all other error conditions as NOTFOUND, and fail. This includes DNSSEC errors and
+ suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf configuration can distuingish
+ such executed but negative replies from complete failure to talk to resolved. */
+ ret = NSS_STATUS_NOTFOUND;
goto fail;
}
@@ -281,7 +286,7 @@ fallback:
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ return ret;
}
enum nss_status _nss_resolve_gethostbyname3_r(
@@ -297,6 +302,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *r_name, *r_aliases, *r_addr, *r_addr_list;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ enum nss_status ret = NSS_STATUS_UNAVAIL;
size_t l, idx, ms, alen;
const char *canonical;
int c, r, i = 0;
@@ -350,6 +356,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
if (bus_error_shall_fallback(&error))
goto fallback;
+ ret = NSS_STATUS_NOTFOUND;
goto fail;
}
@@ -476,7 +483,7 @@ fallback:
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ return ret;
}
enum nss_status _nss_resolve_gethostbyaddr2_r(
@@ -491,6 +498,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char *r_name, *r_aliases, *r_addr, *r_addr_list;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ enum nss_status ret = NSS_STATUS_UNAVAIL;
unsigned c = 0, i = 0;
size_t ms = 0, idx;
const char *n;
@@ -557,10 +565,8 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
if (bus_error_shall_fallback(&error))
goto fallback;
-
- *errnop = -r;
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ ret = NSS_STATUS_NOTFOUND;
+ goto fail;
}
r = sd_bus_message_enter_container(reply, 'a', "(is)");
@@ -668,7 +674,7 @@ fallback:
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
+ return ret;
}
NSS_GETHOSTBYNAME_FALLBACKS(resolve);
diff --git a/src/grp-resolve/nss-resolve/nss-resolve.xml b/src/grp-resolve/nss-resolve/nss-resolve.xml
index d9e56453e8..9f24f65019 100644
--- a/src/grp-resolve/nss-resolve/nss-resolve.xml
+++ b/src/grp-resolve/nss-resolve/nss-resolve.xml
@@ -81,11 +81,11 @@
<para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables <command>nss-resolve</command>
correctly:</para>
-<programlisting>passwd: compat mymachines
-group: compat mymachines
+<programlisting>passwd: compat mymachines systemd
+group: compat mymachines systemd
shadow: compat
-hosts: files mymachines <command>resolve</command> myhostname
+hosts: files mymachines <command>resolve [!UNAVAIL=return]</command> dns myhostname
networks: files
protocols: db files
@@ -95,6 +95,8 @@ rpc: db files
netgroup: nis</programlisting>
+ <para>This keeps the <command>dns</command> module as a fallback for cases where the <command>nss-resolve</command>
+ module is not installed.</para>
</refsect1>
<refsect1>
@@ -102,8 +104,9 @@ netgroup: nis</programlisting>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>nss-systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/grp-resolve/systemd-resolve/resolve-tool.c b/src/grp-resolve/systemd-resolve/resolve-tool.c
index facad18086..3e19b8563c 100644
--- a/src/grp-resolve/systemd-resolve/resolve-tool.c
+++ b/src/grp-resolve/systemd-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/grp-resolve/systemd-resolve/systemd-resolve.completion.bash b/src/grp-resolve/systemd-resolve/systemd-resolve.completion.bash
index 0c501c9405..f59482fe23 100644
--- a/src/grp-resolve/systemd-resolve/systemd-resolve.completion.bash
+++ b/src/grp-resolve/systemd-resolve/systemd-resolve.completion.bash
@@ -36,8 +36,8 @@ _systemd-resolve() {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local -A OPTS=(
[STANDALONE]='-h --help --version -4 -6
- --service --openpgp --tlsa --statistics --reset-statistics
- --service-address=no --service-txt=no
+ --service --openpgp --tlsa --status --statistics
+ --reset-statistics --service-address=no --service-txt=no
--cname=no --search=no --legend=no'
[ARG]='-i --interface -p --protocol -t --type -c --class'
)
diff --git a/src/grp-resolve/systemd-resolve/systemd-resolve.xml b/src/grp-resolve/systemd-resolve/systemd-resolve.xml
index ca26bb4d49..2bc917ac26 100644
--- a/src/grp-resolve/systemd-resolve/systemd-resolve.xml
+++ b/src/grp-resolve/systemd-resolve/systemd-resolve.xml
@@ -135,7 +135,7 @@
TXT).</para>
<para>The <option>--openpgp</option> switch may be used to query PGP keys stored as
- <ulink url="https://tools.ietf.org/html/draft-wouters-dane-openpgp-02">OPENPGPKEY</ulink> resource records.
+ <ulink url="https://tools.ietf.org/html/rfc7929">OPENPGPKEY</ulink> resource records.
When this option is specified one or more e-mail address must be specified.</para>
<para>The <option>--tlsa</option> switch maybe be used to query TLS public
@@ -339,7 +339,7 @@ www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
</example>
<example>
- <title>Retrieve the MX record of the <literal>0pointer.net</literal> domain</title>
+ <title>Retrieve the MX record of the <literal>yahoo.com</literal> domain</title>
<programlisting>$ systemd-resolve -t MX yahoo.com --legend=no
yahoo.com. IN MX 1 mta7.am0.yahoodns.net
diff --git a/src/grp-resolve/systemd-resolved/dnssec-trust-anchors.d.xml b/src/grp-resolve/systemd-resolved/dnssec-trust-anchors.d.xml
index 4bdc167f79..9a28862ceb 100644
--- a/src/grp-resolve/systemd-resolved/dnssec-trust-anchors.d.xml
+++ b/src/grp-resolve/systemd-resolved/dnssec-trust-anchors.d.xml
@@ -160,14 +160,12 @@
<refsect1>
<title>Negative Trust Anchors</title>
- <para>Negative trust anchors define domains where DNSSEC
- validation shall be turned off. Negative trust anchor files are
- found at the same location as positive trust anchor files, and
- follow the same overriding rules. They are text files with the
- <filename>.negative</filename> suffix. Empty lines and lines whose
- first character is <literal>;</literal> are ignored. Each line
- specifies one domain name where DNSSEC validation shall be
- disabled on.</para>
+ <para>Negative trust anchors define domains where DNSSEC validation shall be turned
+ off. Negative trust anchor files are found at the same location as positive trust anchor files,
+ and follow the same overriding rules. They are text files with the
+ <filename>.negative</filename> suffix. Empty lines and lines whose first character is
+ <literal>;</literal> are ignored. Each line specifies one domain name which is the root of a DNS
+ subtree where validation shall be disabled.</para>
<para>Negative trust anchors are useful to support private DNS
subtrees that are not referenced from the Internet DNS hierarchy,
diff --git a/src/grp-resolve/systemd-resolved/resolved-conf.c b/src/grp-resolve/systemd-resolved/resolved-conf.c
index 49667ec128..48aa2da331 100644
--- a/src/grp-resolve/systemd-resolved/resolved-conf.c
+++ b/src/grp-resolve/systemd-resolved/resolved-conf.c
@@ -21,11 +21,22 @@
#include "systemd-basic/def.h"
#include "systemd-basic/extract-word.h"
#include "systemd-basic/parse-util.h"
+#include "systemd-basic/string-table.h"
#include "systemd-basic/string-util.h"
#include "systemd-shared/conf-parser.h"
#include "resolved-conf.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;
@@ -222,7 +233,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/grp-resolve/systemd-resolved/resolved-conf.h b/src/grp-resolve/systemd-resolved/resolved-conf.h
index e1fd2cceec..f62d56a938 100644
--- a/src/grp-resolve/systemd-resolved/resolved-conf.h
+++ b/src/grp-resolve/systemd-resolved/resolved-conf.h
@@ -19,6 +19,18 @@
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-dns-server.h"
#include "resolved-manager.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/grp-resolve/systemd-resolved/resolved-dns-query.c b/src/grp-resolve/systemd-resolved/resolved-dns-query.c
index 7c270ccd2b..2193dc5bcf 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-query.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-query.c
@@ -84,9 +84,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) {
@@ -422,9 +420,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/grp-resolve/systemd-resolved/resolved-dns-scope.c b/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
index 9b7883a410..9f20fd304a 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
@@ -129,9 +129,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) {
@@ -408,6 +406,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);
@@ -448,6 +447,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/grp-resolve/systemd-resolved/resolved-dns-scope.h b/src/grp-resolve/systemd-resolved/resolved-dns-scope.h
index 3ca4623068..69dd6320d3 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-scope.h
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-scope.h
@@ -26,6 +26,8 @@
typedef struct DnsScope DnsScope;
#include "resolved-dns-cache.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"
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-search-domain.c b/src/grp-resolve/systemd-resolved/resolved-dns-search-domain.c
index 5ddbc7504e..a82df4c7a6 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-search-domain.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-search-domain.c
@@ -105,9 +105,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/grp-resolve/systemd-resolved/resolved-dns-server.c b/src/grp-resolve/systemd-resolved/resolved-dns-server.c
index 2274eedae2..b2605c0d46 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-server.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-server.c
@@ -140,8 +140,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) {
@@ -577,6 +576,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/grp-resolve/systemd-resolved/resolved-dns-server.h b/src/grp-resolve/systemd-resolved/resolved-dns-server.h
index 66acd04085..83d0d23bb4 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-server.h
+++ b/src/grp-resolve/systemd-resolved/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/grp-resolve/systemd-resolved/resolved-dns-stream.c b/src/grp-resolve/systemd-resolved/resolved-dns-stream.c
index 353d5f7a45..5f77d47f64 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-stream.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-stream.c
@@ -344,9 +344,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/grp-resolve/systemd-resolved/resolved-dns-stub.c b/src/grp-resolve/systemd-resolved/resolved-dns-stub.c
index e7aa7a1c38..ad49862a70 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-stub.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-stub.c
@@ -26,6 +26,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,
@@ -355,66 +358,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) {
@@ -462,102 +447,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/grp-resolve/systemd-resolved/resolved-dns-stub.h b/src/grp-resolve/systemd-resolved/resolved-dns-stub.h
index fce4d25ede..12b86f6753 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-stub.h
+++ b/src/grp-resolve/systemd-resolved/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/grp-resolve/systemd-resolved/resolved-dns-transaction.c b/src/grp-resolve/systemd-resolved/resolved-dns-transaction.c
index a5ae8d0853..b17493d659 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-transaction.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-transaction.c
@@ -135,8 +135,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/grp-resolve/systemd-resolved/resolved-dns-transaction.h b/src/grp-resolve/systemd-resolved/resolved-dns-transaction.h
index cfd2a35da8..babc206f7f 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-transaction.h
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-transaction.h
@@ -62,6 +62,8 @@ enum DnsTransactionSource {
#include "basic-dns/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/grp-resolve/systemd-resolved/resolved-dns-trust-anchor.c b/src/grp-resolve/systemd-resolved/resolved-dns-trust-anchor.c
index 53cd9d8f55..cb45136788 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-trust-anchor.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-trust-anchor.c
@@ -128,6 +128,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/grp-resolve/systemd-resolved/resolved-gperf.gperf b/src/grp-resolve/systemd-resolved/resolved-gperf.gperf
index 6f8df3b533..79e54d8357 100644
--- a/src/grp-resolve/systemd-resolved/resolved-gperf.gperf
+++ b/src/grp-resolve/systemd-resolved/resolved-gperf.gperf
@@ -16,9 +16,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/grp-resolve/systemd-resolved/resolved-link.c b/src/grp-resolve/systemd-resolved/resolved-link.c
index ccfcc70d1a..99be607b09 100644
--- a/src/grp-resolve/systemd-resolved/resolved-link.c
+++ b/src/grp-resolve/systemd-resolved/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/grp-resolve/systemd-resolved/resolved-manager.c b/src/grp-resolve/systemd-resolved/resolved-manager.c
index a7a2916ce9..eea95a6fd9 100644
--- a/src/grp-resolve/systemd-resolved/resolved-manager.c
+++ b/src/grp-resolve/systemd-resolved/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/grp-resolve/systemd-resolved/resolved-manager.h b/src/grp-resolve/systemd-resolved/resolved-manager.h
index 2e187efeb5..4e9dcd51f1 100644
--- a/src/grp-resolve/systemd-resolved/resolved-manager.h
+++ b/src/grp-resolve/systemd-resolved/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/grp-resolve/systemd-resolved/resolved-resolv-conf.c b/src/grp-resolve/systemd-resolved/resolved-resolv-conf.c
index 01b6481016..5cc79a0040 100644
--- a/src/grp-resolve/systemd-resolved/resolved-resolv-conf.c
+++ b/src/grp-resolve/systemd-resolved/resolved-resolv-conf.c
@@ -155,6 +155,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/grp-resolve/systemd-resolved/resolved.conf.in b/src/grp-resolve/systemd-resolved/resolved.conf.in
index 3bd8389c88..60afa151e3 100644
--- a/src/grp-resolve/systemd-resolved/resolved.conf.in
+++ b/src/grp-resolve/systemd-resolved/resolved.conf.in
@@ -18,3 +18,4 @@
#LLMNR=yes
#DNSSEC=@DEFAULT_DNSSEC_MODE@
#Cache=yes
+#DNSStubListener=udp
diff --git a/src/grp-resolve/systemd-resolved/resolved.conf.xml b/src/grp-resolve/systemd-resolved/resolved.conf.xml
index 7556c6ff31..4fc1ef1b33 100644
--- a/src/grp-resolve/systemd-resolved/resolved.conf.xml
+++ b/src/grp-resolve/systemd-resolved/resolved.conf.xml
@@ -206,13 +206,25 @@
<term><varname>Cache=</varname></term>
<listitem><para>Takes a boolean argument. If "yes" (the default), resolving a domain name which already got
queried earlier will return the previous result as long as it is still valid, and thus does not result in a new
- network request. Be aware that that turning off caching comes at a performance penalty, which is particularly
+ network request. Be aware that turning off caching comes at a performance penalty, which is particularly
high when DNSSEC is used.</para>
<para>Note that caching is turned off implicitly if the configured DNS server is on a host-local IP address
(such as 127.0.0.1 or ::1), in order to avoid duplicate local caching.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DNSStubListener=</varname></term>
+ <listitem><para>Takes a boolean argument or one of <literal>udp</literal> and <literal>tcp</literal>. If
+ <literal>udp</literal> (the default), a DNS stub resolver will listen for UDP requests on address 127.0.0.53
+ port 53. If <literal>tcp</literal>, the stub will listen for TCP requests on the same address and port. If
+ <literal>yes</literal>, the stub listens for both UDP and TCP requests. If <literal>no</literal>, the stub
+ listener is disabled.</para>
+
+ <para>Note that the DNS stub listener is turned off implicitly when its listening address and port are already
+ in use.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
diff --git a/src/grp-resolve/systemd-resolved/systemd-resolved.service.m4.in b/src/grp-resolve/systemd-resolved/systemd-resolved.service.m4.in
index 15ab56a066..0f0440ddaf 100644
--- a/src/grp-resolve/systemd-resolved/systemd-resolved.service.m4.in
+++ b/src/grp-resolve/systemd-resolved/systemd-resolved.service.m4.in
@@ -23,11 +23,17 @@ Type=notify
Restart=always
RestartSec=0
ExecStart=@rootlibexecdir@/systemd-resolved
+WatchdogSec=3min
CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_NET_RAW CAP_NET_BIND_SERVICE
+PrivateTmp=yes
+PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
-WatchdogSec=3min
+ProtectControlGroups=yes
+ProtectKernelTunables=yes
MemoryDenyWriteExecute=yes
+RestrictRealtime=yes
+RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
[Install]
diff --git a/src/grp-resolve/systemd-resolved/systemd-resolved.service.xml b/src/grp-resolve/systemd-resolved/systemd-resolved.service.xml
index aa1c2365e5..56f67960ce 100644
--- a/src/grp-resolve/systemd-resolved/systemd-resolved.service.xml
+++ b/src/grp-resolve/systemd-resolved/systemd-resolved.service.xml
@@ -68,12 +68,12 @@
link-local networking).</para></listitem>
<listitem><para>The glibc
- <citerefentry><refentrytitle>getaddrinfo</refentrytitle><manvolnum>3</manvolnum></citerefentry> API as defined
+ <citerefentry project='man-pages'><refentrytitle>getaddrinfo</refentrytitle><manvolnum>3</manvolnum></citerefentry> API as defined
by <ulink url="https://tools.ietf.org/html/rfc3493">RFC3493</ulink> and its related resolver functions,
- including <citerefentry><refentrytitle>gethostbyname</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
+ including <citerefentry project='man-pages'><refentrytitle>gethostbyname</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
API is widely supported, including beyond the Linux platform. In its current form it does not expose DNSSEC
validation status information however, and is synchronous only. This API is backed by the glibc Name Service
- Switch (<citerefentry><refentrytitle>nss</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Usage of the
+ Switch (<citerefentry project='man-pages'><refentrytitle>nss</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Usage of the
glibc NSS module <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is required in order to allow glibc's NSS resolver functions to resolve host names via
<command>systemd-resolved</command>.</para></listitem>
@@ -164,7 +164,7 @@
<title><filename>/etc/resolv.conf</filename></title>
<para>Three modes of handling <filename>/etc/resolv.conf</filename> (see
- <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>) are
+ <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>) are
supported:</para>
<itemizedlist>