happen regularly. On other systems it is recommended to set
<varname>DNSSEC=</varname> to
<literal>allow-downgrade</literal>.</para>
+
+ <para>In addition to this global DNSSEC setting
+ <citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ also maintains per-interface DNSSEC settings. For system DNS
+ servers (see above), only the global DNSSEC setting is in
+ effect. For per-interface DNS servers the per-interface
+ setting is in effect, unless it is unset in which case the
+ global setting is used instead.</para>
+
+ <para>Defaults to off.</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>DNSSEC=</varname></term>
+ <listitem>
+ <para>A boolean or
+ <literal>allow-downgrade</literal>. When true, enables
+ <ulink
+ url="https://tools.ietf.org/html/rfc4033">DNSSEC</ulink>
+ DNS validation support on the link. When set to
+ <literal>allow-downgrade</literal>, compatibility with
+ non-DNSSEC capable networks is increased, by automatically
+ turning off DNSEC in this case. This option defines a
+ per-interface setting for
+ <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
+ global <varname>DNSSEC=</varname> option. Defaults to
+ false. This setting is read by
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>LLDP=</varname></term>
<listitem>
<para>A boolean. When true, enables LLDP link receive support.
return network_link_get_string(ifindex, "MDNS", mdns);
}
+_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
+ return network_link_get_string(ifindex, "DNSSEC", dnssec);
+}
+
_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
_cleanup_free_ char *s = NULL, *p = NULL;
size_t size;
fprintf(f, "MDNS=%s\n",
resolve_support_to_string(link->network->mdns));
+ if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID)
+ fprintf(f, "DNSSEC=%s\n",
+ dnssec_mode_to_string(link->network->dnssec_mode));
+
fputs("ADDRESSES=", f);
space = false;
SET_FOREACH(a, link->addresses, i) {
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
+Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
network->llmnr = RESOLVE_SUPPORT_YES;
network->mdns = RESOLVE_SUPPORT_NO;
+ network->dnssec_mode = _DNSSEC_MODE_INVALID;
network->link_local = ADDRESS_FAMILY_IPV6;
ResolveSupport llmnr;
ResolveSupport mdns;
+ DnssecMode dnssec_mode;
LIST_FIELDS(Network, networks);
};
return 0;
}
-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) {
-
- Manager *m = data;
- DnssecMode mode;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- mode = dnssec_mode_from_string(rvalue);
- if (mode < 0) {
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNSSEC mode '%s'. Ignoring.", rvalue);
- return 0;
- }
-
- mode = r ? DNSSEC_YES : DNSSEC_NO;
- }
-
- m->unicast_scope->dnssec_mode = mode;
- return 0;
-}
-
int manager_parse_config_file(Manager *m) {
int r;
return 0;
}
-static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
- [DNSSEC_NO] = "no",
- [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade",
- [DNSSEC_YES] = "yes",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode);
-
static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
[DNSSEC_VALIDATED] = "validated",
[DNSSEC_INVALID] = "invalid",
#include "resolved-dns-answer.h"
#include "resolved-dns-rr.h"
-enum DnssecMode {
- /* No DNSSEC validation is done */
- DNSSEC_NO,
-
- /* Validate locally, if the server knows DO, but if not,
- * don't. Don't trust the AD bit. If the server doesn't do
- * DNSSEC properly, downgrade to non-DNSSEC operation. Of
- * course, we then are vulnerable to a downgrade attack, but
- * that's life and what is configured. */
- DNSSEC_ALLOW_DOWNGRADE,
-
- /* Insist on DNSSEC server support, and rather fail than downgrading. */
- DNSSEC_YES,
-
- _DNSSEC_MODE_MAX,
- _DNSSEC_MODE_INVALID = -1
-};
-
enum DnssecResult {
/* These four are returned by dnssec_verify_rrset() */
DNSSEC_VALIDATED,
int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-const char* dnssec_mode_to_string(DnssecMode m) _const_;
-DnssecMode dnssec_mode_from_string(const char *s) _pure_;
-
const char* dnssec_result_to_string(DnssecResult m) _const_;
DnssecResult dnssec_result_from_string(const char *s) _pure_;
s->family = family;
s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
+ s->dnssec_mode = _DNSSEC_MODE_INVALID;
+
+ if (protocol == DNS_PROTOCOL_DNS) {
+ /* Copy DNSSEC mode from the link if it is set there,
+ * otherwise take the manager's DNSSEC mode. Note that
+ * we copy this only at scope creation time, and do
+ * not update it from the on, even if the setting
+ * changes. */
+
+ if (l)
+ s->dnssec_mode = l->dnssec_mode;
+ if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
+ s->dnssec_mode = m->dnssec_mode;
+ if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
+ s->dnssec_mode = DNSSEC_NO;
+ }
+
LIST_PREPEND(scopes, m->dns_scopes, s);
dns_scope_llmnr_membership(s, true);
%struct-type
%includes
%%
-Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
-Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
-Resolve.Domains, config_parse_search_domains, 0, 0
-Resolve.LLMNR, config_parse_resolve_support,0, offsetof(Manager, llmnr_support)
-Resolve.MulticastDNS, config_parse_resolve_support,0, offsetof(Manager, mdns_support)
-Resolve.DNSSEC, config_parse_dnssec, 0, 0
+Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
+Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
+Resolve.Domains, config_parse_search_domains, 0, 0
+Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
+Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
+Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
l->ifindex = ifindex;
l->llmnr_support = RESOLVE_SUPPORT_YES;
+ l->mdns_support = RESOLVE_SUPPORT_NO;
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
if (r < 0)
return r;
}
+static int link_update_dnssec_mode(Link *l) {
+ _cleanup_free_ char *m = NULL;
+ int r;
+
+ assert(l);
+
+ r = sd_network_link_get_dnssec(l->ifindex, &m);
+ if (r == -ENODATA) {
+ r = 0;
+ goto clear;
+ }
+ if (r < 0)
+ goto clear;
+
+ l->dnssec_mode = dnssec_mode_from_string(m);
+ if (l->dnssec_mode < 0) {
+ r = -EINVAL;
+ goto clear;
+ }
+
+ return 0;
+
+clear:
+ l->dnssec_mode = _DNSSEC_MODE_INVALID;
+ return r;
+}
+
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **domains = NULL;
char **i;
if (r < 0)
log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
- link_allocate_scopes(l);
+ r = link_update_dnssec_mode(l);
+ if (r < 0)
+ log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
r = link_update_search_domains(l);
if (r < 0)
log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
+ link_allocate_scopes(l);
link_add_rrs(l, false);
return 0;
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
+ DnssecMode dnssec_mode;
DnsScope *unicast_scope;
DnsScope *llmnr_ipv4_scope;
m->hostname_fd = -1;
m->llmnr_support = RESOLVE_SUPPORT_YES;
+ m->mdns_support = RESOLVE_SUPPORT_NO;
+ m->dnssec_mode = DNSSEC_NO;
m->read_resolv_conf = true;
m->need_builtin_fallbacks = true;
if (r < 0)
return r;
+ r = manager_parse_config_file(m);
+ if (r < 0)
+ return r;
+
r = sd_event_default(&m->event);
if (r < 0)
return r;
ResolveSupport llmnr_support;
ResolveSupport mdns_support;
+ DnssecMode dnssec_mode;
/* Network */
Hashmap *links;
goto finish;
}
- r = manager_parse_config_file(m);
- if (r < 0) {
- log_error_errno(r, "Failed to parse configuration file: %m");
- goto finish;
- }
-
r = manager_start(m);
if (r < 0) {
log_error_errno(r, "Failed to start manager: %m");
#include "string-table.h"
DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting");
static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
[RESOLVE_SUPPORT_NO] = "no",
[RESOLVE_SUPPORT_RESOLVE] = "resolve",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES);
+
+static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = {
+ [DNSSEC_NO] = "no",
+ [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade",
+ [DNSSEC_YES] = "yes",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
#include "macro.h"
typedef enum ResolveSupport ResolveSupport;
+typedef enum DnssecMode DnssecMode;
enum ResolveSupport {
RESOLVE_SUPPORT_NO,
_RESOLVE_SUPPORT_INVALID = -1
};
+enum DnssecMode {
+ /* No DNSSEC validation is done */
+ DNSSEC_NO,
+
+ /* Validate locally, if the server knows DO, but if not,
+ * don't. Don't trust the AD bit. If the server doesn't do
+ * DNSSEC properly, downgrade to non-DNSSEC operation. Of
+ * course, we then are vulnerable to a downgrade attack, but
+ * that's life and what is configured. */
+ DNSSEC_ALLOW_DOWNGRADE,
+
+ /* Insist on DNSSEC server support, and rather fail than downgrading. */
+ DNSSEC_YES,
+
+ _DNSSEC_MODE_MAX,
+ _DNSSEC_MODE_INVALID = -1
+};
+
int config_parse_resolve_support(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_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* resolve_support_to_string(ResolveSupport p) _const_;
ResolveSupport resolve_support_from_string(const char *s) _pure_;
+
+const char* dnssec_mode_to_string(DnssecMode p) _const_;
+DnssecMode dnssec_mode_from_string(const char *s) _pure_;
*/
int sd_network_link_get_llmnr(int ifindex, char **llmnr);
-/* Indicates whether or not MDNS should be enabled for the link
+/* Indicates whether or not MulticastDNS should be enabled for the
+ * link.
* Possible levels of support: yes, no, resolve
* Possible return codes:
* -ENODATA: networkd is not aware of the link
*/
int sd_network_link_get_mdns(int ifindex, char **mdns);
+/* Indicates whether or not DNSSEC should be enabled for the link
+ * Possible levels of support: yes, no, allow-downgrade
+ * Possible return codes:
+ * -ENODATA: networkd is not aware of the link
+ */
+int sd_network_link_get_dnssec(int ifindex, char **dnssec);
+
int sd_network_link_get_lldp(int ifindex, char **lldp);
/* Get the DNS domain names for a given link. */