From 38e5900fc6e77b595151ae8e1548c5aace406bf8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Jan 2016 16:43:07 +0100 Subject: sd-network: unify parsing of /run/systemd/netif/links/* string fields --- src/libsystemd/sd-network/sd-network.c | 103 +++++---------------------------- 1 file changed, 14 insertions(+), 89 deletions(-) (limited to 'src/libsystemd/sd-network/sd-network.c') diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index efbceba83d..d01c4ae8e2 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -99,17 +99,17 @@ _public_ int sd_network_get_domains(char ***ret) { return network_get_strv("DOMAINS", ret); } -_public_ int sd_network_link_get_setup_state(int ifindex, char **state) { +static int network_link_get_string(int ifindex, const char *field, char **ret) { _cleanup_free_ char *s = NULL, *p = NULL; int r; assert_return(ifindex > 0, -EINVAL); - assert_return(state, -EINVAL); + assert_return(ret, -EINVAL); - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) + if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0) return -ENOMEM; - r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL); + r = parse_env_file(p, NEWLINE, field, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) @@ -117,82 +117,26 @@ _public_ int sd_network_link_get_setup_state(int ifindex, char **state) { if (isempty(s)) return -ENODATA; - *state = s; + *ret = s; s = NULL; return 0; } -_public_ int sd_network_link_get_network_file(int ifindex, char **filename) { - _cleanup_free_ char *s = NULL, *p = NULL; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(filename, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (isempty(s)) - return -ENODATA; - - *filename = s; - s = NULL; +_public_ int sd_network_link_get_setup_state(int ifindex, char **state) { + return network_link_get_string(ifindex, "ADMIN_STATE", state); +} - return 0; +_public_ int sd_network_link_get_network_file(int ifindex, char **filename) { + return network_link_get_string(ifindex, "NETWORK_FILE", filename); } _public_ int sd_network_link_get_operational_state(int ifindex, char **state) { - _cleanup_free_ char *s = NULL, *p = NULL; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(state, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (isempty(s)) - return -ENODATA; - - *state = s; - s = NULL; - - return 0; + return network_link_get_string(ifindex, "OPER_STATE", state); } _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { - _cleanup_free_ char *s = NULL, *p = NULL; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(llmnr, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (isempty(s)) - return -ENODATA; - - *llmnr = s; - s = NULL; - - return 0; + return network_link_get_string(ifindex, "LLMNR", llmnr); } _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { @@ -221,26 +165,7 @@ _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { } int sd_network_link_get_timezone(int ifindex, char **ret) { - _cleanup_free_ char *s = NULL, *p = NULL; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(ret, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, "TIMEZONE", &s, NULL); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (isempty(s)) - return -ENODATA; - - *ret = s; - s = NULL; - return 0; + return network_link_get_string(ifindex, "TIMEZONE", ret); } static int network_get_link_strv(const char *key, int ifindex, char ***ret) { @@ -298,8 +223,8 @@ _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) { } _public_ int sd_network_link_get_wildcard_domain(int ifindex) { - int r; _cleanup_free_ char *p = NULL, *s = NULL; + int r; assert_return(ifindex > 0, -EINVAL); -- cgit v1.2.3-54-g00ecf From aaa297d4e5401fd4466632555432774863457f1d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Jan 2016 17:32:25 +0100 Subject: networkd,resolved: add a per-interface mdns configuration option --- man/systemd.network.xml | 28 +++++++++++++++++++++++----- src/libsystemd/sd-network/sd-network.c | 4 ++++ src/network/networkd-link.c | 2 ++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + src/resolve/resolved-link.c | 28 ++++++++++++++++++++++++++++ src/systemd/sd-network.h | 7 +++++++ 8 files changed, 67 insertions(+), 5 deletions(-) (limited to 'src/libsystemd/sd-network/sd-network.c') diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 5ad03f75e6..6091f2fdf5 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -277,10 +277,27 @@ LLMNR= - A boolean or resolve. When true, enables - Link-Local Multicast Name Resolution on the link. When set to - resolve, only resolution is enabled, but not - announcement. Defaults to true. + A boolean or resolve. When true, + enables Link-Local + Multicast Name Resolution on the link. When set to + resolve, only resolution is enabled, + but not host registration and announcement. Defaults to + true. This setting is read by + systemd-resolved.service8. + + + + MulticastDNS= + + A boolean or resolve. When true, + enables Multicast + DNS support on the link. When set to + resolve, only resolution is enabled, + but not host or service registration and + announcement. Defaults to false. This setting is read by + systemd-resolved.service8. @@ -1013,7 +1030,8 @@ DHCP=yes systemd1, systemd-networkd8, systemd.link5, - systemd.netdev5 + systemd.netdev5, + systemd-resolved.service8 diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index d01c4ae8e2..a63ff46c68 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -139,6 +139,10 @@ _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { return network_link_get_string(ifindex, "LLMNR", llmnr); } +_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) { + return network_link_get_string(ifindex, "MDNS", mdns); +} + _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { _cleanup_free_ char *s = NULL, *p = NULL; size_t size; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9811526c6d..2013a8eae7 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2868,6 +2868,8 @@ int link_save(Link *link) { fprintf(f, "LLMNR=%s\n", resolve_support_to_string(link->network->llmnr)); + fprintf(f, "MDNS=%s\n", + resolve_support_to_string(link->network->mdns)); fputs("ADDRESSES=", f); space = false; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5c962e5709..c66ca3c1cc 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -46,6 +46,7 @@ Network.Gateway, config_parse_gateway, Network.Domains, config_parse_domains, 0, offsetof(Network, domains) 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.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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 29723a852f..7544280a7a 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -121,6 +121,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->unicast_flood = true; network->llmnr = RESOLVE_SUPPORT_YES; + network->mdns = RESOLVE_SUPPORT_NO; network->link_local = ADDRESS_FAMILY_IPV6; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 297823da24..91e90e6d74 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -145,6 +145,7 @@ struct Network { char **domains, **dns, **ntp, **bind_carrier; ResolveSupport llmnr; + ResolveSupport mdns; LIST_FIELDS(Network, networks); }; diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 6202ddeca1..a1f28633ba 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -246,6 +246,33 @@ clear: return r; } +static int link_update_mdns_support(Link *l) { + _cleanup_free_ char *b = NULL; + int r; + + assert(l); + + r = sd_network_link_get_mdns(l->ifindex, &b); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + l->mdns_support = resolve_support_from_string(b); + if (l->mdns_support < 0) { + r = -EINVAL; + goto clear; + } + + return 0; + +clear: + l->mdns_support = RESOLVE_SUPPORT_NO; + return r; +} + static int link_update_search_domains(Link *l) { _cleanup_strv_free_ char **domains = NULL; char **i; @@ -295,6 +322,7 @@ int link_update_monitor(Link *l) { link_update_dns_servers(l); link_update_llmnr_support(l); + link_update_mdns_support(l); link_allocate_scopes(l); r = link_update_search_domains(l); diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 79b4bf9ea3..6765be041b 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -111,6 +111,13 @@ int sd_network_link_get_ntp(int ifindex, char ***addr); */ int sd_network_link_get_llmnr(int ifindex, char **llmnr); +/* Indicates whether or not MDNS 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); + int sd_network_link_get_lldp(int ifindex, char **lldp); /* Get the DNS domain names for a given link. */ -- cgit v1.2.3-54-g00ecf From ad6c04756115809d615dede330213d73edf732a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Jan 2016 19:57:33 +0100 Subject: resolved,networkd: add a per-interface DNSSEC setting This adds a DNSSEC= setting to .network files, and makes resolved honour them. --- man/resolved.conf.xml | 10 +++++++++ man/systemd.network.xml | 18 ++++++++++++++++ src/libsystemd/sd-network/sd-network.c | 4 ++++ src/network/networkd-link.c | 4 ++++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + src/resolve/resolved-conf.c | 35 -------------------------------- src/resolve/resolved-dns-dnssec.c | 7 ------- src/resolve/resolved-dns-dnssec.h | 21 ------------------- src/resolve/resolved-dns-scope.c | 17 ++++++++++++++++ src/resolve/resolved-gperf.gperf | 12 +++++------ src/resolve/resolved-link.c | 34 ++++++++++++++++++++++++++++++- src/resolve/resolved-link.h | 1 + src/resolve/resolved-manager.c | 6 ++++++ src/resolve/resolved-manager.h | 1 + src/resolve/resolved.c | 6 ------ src/shared/resolve-util.c | 8 ++++++++ src/shared/resolve-util.h | 23 +++++++++++++++++++++ src/systemd/sd-network.h | 10 ++++++++- 20 files changed, 143 insertions(+), 77 deletions(-) (limited to 'src/libsystemd/sd-network/sd-network.c') diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml index c2c277b606..3209f73bc1 100644 --- a/man/resolved.conf.xml +++ b/man/resolved.conf.xml @@ -194,6 +194,16 @@ happen regularly. On other systems it is recommended to set DNSSEC= to allow-downgrade. + + In addition to this global DNSSEC setting + systemd-networkd.service8 + 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. + + Defaults to off. diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 36172ae8b5..1dfa559c8b 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -300,6 +300,24 @@ systemd-resolved.service8. + + DNSSEC= + + A boolean or + allow-downgrade. When true, enables + DNSSEC + DNS validation support on the link. When set to + allow-downgrade, compatibility with + non-DNSSEC capable networks is increased, by automatically + turning off DNSEC in this case. This option defines a + per-interface setting for + resolved.conf5's + global DNSSEC= option. Defaults to + false. This setting is read by + systemd-resolved.service8. + + LLDP= diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index a63ff46c68..517b48a04f 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -143,6 +143,10 @@ _public_ int sd_network_link_get_mdns(int ifindex, char **mdns) { 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; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2013a8eae7..18a82fdeb9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2871,6 +2871,10 @@ int link_save(Link *link) { 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) { diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index c66ca3c1cc..75a2620804 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -47,6 +47,7 @@ Network.Domains, config_parse_domains, 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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 7544280a7a..c91531ca69 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -122,6 +122,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->llmnr = RESOLVE_SUPPORT_YES; network->mdns = RESOLVE_SUPPORT_NO; + network->dnssec_mode = _DNSSEC_MODE_INVALID; network->link_local = ADDRESS_FAMILY_IPV6; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 91e90e6d74..7817b13cc4 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -146,6 +146,7 @@ struct Network { ResolveSupport llmnr; ResolveSupport mdns; + DnssecMode dnssec_mode; LIST_FIELDS(Network, networks); }; diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 6afa61fa56..88df7534c4 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -200,41 +200,6 @@ int config_parse_search_domains( 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; diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index ff571986c0..edbd83ce05 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -1566,13 +1566,6 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *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", diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h index d818d1a906..6977faca75 100644 --- a/src/resolve/resolved-dns-dnssec.h +++ b/src/resolve/resolved-dns-dnssec.h @@ -28,24 +28,6 @@ typedef enum DnssecResult DnssecResult; #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, @@ -101,8 +83,5 @@ typedef enum DnssecNsecResult { 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_; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 13be2a3792..c96bed04b0 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -57,6 +57,23 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int 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); diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf index fb3fe9cfb1..c5ad04afd7 100644 --- a/src/resolve/resolved-gperf.gperf +++ b/src/resolve/resolved-gperf.gperf @@ -14,9 +14,9 @@ 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.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) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 8785079de8..50d3f9096b 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -47,6 +47,8 @@ int link_new(Manager *m, Link **ret, int ifindex) { 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) @@ -273,6 +275,33 @@ clear: 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; @@ -332,12 +361,15 @@ int link_update_monitor(Link *l) { 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; diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index bb3fe8ebff..d17b57253b 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -69,6 +69,7 @@ struct Link { ResolveSupport llmnr_support; ResolveSupport mdns_support; + DnssecMode dnssec_mode; DnsScope *unicast_scope; DnsScope *llmnr_ipv4_scope; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index ed1ac8286f..b32bad456b 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -477,6 +477,8 @@ int manager_new(Manager **ret) { 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; @@ -484,6 +486,10 @@ int manager_new(Manager **ret) { 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; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index d61804fff2..1907d2e1bc 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -47,6 +47,7 @@ struct Manager { ResolveSupport llmnr_support; ResolveSupport mdns_support; + DnssecMode dnssec_mode; /* Network */ Hashmap *links; diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index be406b71fe..472bb32764 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -81,12 +81,6 @@ int main(int argc, char *argv[]) { 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"); diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c index 487de3e077..bf6fc26841 100644 --- a/src/shared/resolve-util.c +++ b/src/shared/resolve-util.c @@ -24,6 +24,7 @@ #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", @@ -31,3 +32,10 @@ static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { [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); diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h index e585c5024f..fd93a13f73 100644 --- a/src/shared/resolve-util.h +++ b/src/shared/resolve-util.h @@ -24,6 +24,7 @@ #include "macro.h" typedef enum ResolveSupport ResolveSupport; +typedef enum DnssecMode DnssecMode; enum ResolveSupport { RESOLVE_SUPPORT_NO, @@ -33,7 +34,29 @@ enum ResolveSupport { _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_; diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 6765be041b..00aaa102ce 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -111,13 +111,21 @@ int sd_network_link_get_ntp(int ifindex, char ***addr); */ 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. */ -- cgit v1.2.3-54-g00ecf From 8a516214c4412e8a40544bd725a6d499a30cbbbf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Jan 2016 18:36:32 +0100 Subject: resolved: introduce support for per-interface negative trust anchors --- man/dnssec-trust-anchors.d.xml | 9 +++- man/systemd.network.xml | 14 ++++++ src/libsystemd/sd-network/sd-network.c | 82 +++++++++++++++++--------------- src/network/networkd-link.c | 15 +++++- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 55 +++++++++++++++++++++ src/network/networkd-network.h | 2 + src/resolve/resolved-dns-transaction.c | 29 +++++++++-- src/resolve/resolved-link.c | 43 +++++++++++++++++ src/resolve/resolved-link.h | 1 + src/systemd/sd-network.h | 6 +++ 11 files changed, 211 insertions(+), 46 deletions(-) (limited to 'src/libsystemd/sd-network/sd-network.c') diff --git a/man/dnssec-trust-anchors.d.xml b/man/dnssec-trust-anchors.d.xml index 5f15d7cd59..51271abc16 100644 --- a/man/dnssec-trust-anchors.d.xml +++ b/man/dnssec-trust-anchors.d.xml @@ -179,6 +179,12 @@ If no negative trust anchor files are configured a built-in set of well-known private DNS zone domains is used as negative trust anchors. + + It is also possibly to define per-interface negative trust + anchors using the DNSSECNegativeTrustAnchors= + setting in + systemd.network5 + files. @@ -186,7 +192,8 @@ systemd1, systemd-resolved.service8, - resolved.conf5 + resolved.conf5, + systemd.network5 diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1dfa559c8b..5a6383cfc2 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -318,6 +318,20 @@ systemd-resolved.service8. + + DNSSECNegativeTrustAnchors= + A space-separated list of DNSSEC negative + trust anchor domains. If specified and DNSSEC is enabled, + look-ups done via the interface's DNS server will be subject + to the list of negative trust anchors, and not require + authentication for the specified domains, or anything below + it. Use this to disable DNSSEC authentication for specific + private domains, that cannot be proven valid using the + Internet DNS hierarchy. Defaults to the empty list. This + setting is read by + systemd-resolved.service8. + + LLDP= diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 517b48a04f..c1f5867ee4 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -123,6 +123,40 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) { return 0; } +static int network_link_get_strv(int ifindex, const char *key, char ***ret) { + _cleanup_free_ char *p = NULL, *s = NULL; + _cleanup_strv_free_ char **a = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(ret, -EINVAL); + + if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) + return -ENOMEM; + + r = parse_env_file(p, NEWLINE, key, &s, NULL); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) { + *ret = NULL; + return 0; + } + + a = strv_split(s, " "); + if (!a) + return -ENOMEM; + + strv_uniq(a); + r = strv_length(a); + + *ret = a; + a = NULL; + + return r; +} + _public_ int sd_network_link_get_setup_state(int ifindex, char **state) { return network_link_get_string(ifindex, "ADMIN_STATE", state); } @@ -147,6 +181,10 @@ _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_dnssec_negative_trust_anchors(int ifindex, char ***nta) { + return network_link_get_strv(ifindex, "DNSSEC_NTA", nta); +} + _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { _cleanup_free_ char *s = NULL, *p = NULL; size_t size; @@ -176,58 +214,24 @@ int sd_network_link_get_timezone(int ifindex, char **ret) { return network_link_get_string(ifindex, "TIMEZONE", ret); } -static int network_get_link_strv(const char *key, int ifindex, char ***ret) { - _cleanup_free_ char *p = NULL, *s = NULL; - _cleanup_strv_free_ char **a = NULL; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(ret, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, key, &s, NULL); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (isempty(s)) { - *ret = NULL; - return 0; - } - - a = strv_split(s, " "); - if (!a) - return -ENOMEM; - - strv_uniq(a); - r = strv_length(a); - - *ret = a; - a = NULL; - - return r; -} - _public_ int sd_network_link_get_dns(int ifindex, char ***ret) { - return network_get_link_strv("DNS", ifindex, ret); + return network_link_get_strv(ifindex, "DNS", ret); } _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) { - return network_get_link_strv("NTP", ifindex, ret); + return network_link_get_strv(ifindex, "NTP", ret); } _public_ int sd_network_link_get_domains(int ifindex, char ***ret) { - return network_get_link_strv("DOMAINS", ifindex, ret); + return network_link_get_strv(ifindex, "DOMAINS", ret); } _public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) { - return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret); + return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret); } _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) { - return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret); + return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret); } _public_ int sd_network_link_get_wildcard_domain(int ifindex) { diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 18a82fdeb9..4a807bacc3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2875,6 +2875,20 @@ int link_save(Link *link) { fprintf(f, "DNSSEC=%s\n", dnssec_mode_to_string(link->network->dnssec_mode)); + if (!set_isempty(link->network->dnssec_negative_trust_anchors)) { + const char *n; + + fputs("DNSSEC_NTA=", f); + space = false; + SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) { + if (space) + fputc(' ', f); + fputs(n, f); + space = true; + } + fputc('\n', f); + } + fputs("ADDRESSES=", f); space = false; SET_FOREACH(a, link->addresses, i) { @@ -2887,7 +2901,6 @@ int link_save(Link *link) { fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); space = true; } - fputc('\n', f); fputs("ROUTES=", f); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 75a2620804..2f2a36ccca 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -48,6 +48,7 @@ Network.DNS, config_parse_strv, 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.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, offsetof(Network, dnssec_negative_trust_anchors) 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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c91531ca69..c11cb3dcb3 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -32,6 +32,7 @@ #include "networkd-network.h" #include "networkd.h" #include "parse-util.h" +#include "set.h" #include "stat-util.h" #include "string-table.h" #include "string-util.h" @@ -277,6 +278,8 @@ void network_free(Network *network) { free(network->dhcp_server_dns); free(network->dhcp_server_ntp); + set_free_free(network->dnssec_negative_trust_anchors); + free(network); } @@ -910,3 +913,55 @@ int config_parse_dhcp_server_ntp( n->dhcp_server_ntp = m; } } + +int config_parse_dnssec_negative_trust_anchors( + 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 *p = rvalue; + Network *n = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors); + return 0; + } + + for (;;) { + _cleanup_free_ char *w = NULL; + + r = extract_first_word(&p, &w, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + r = dns_name_is_valid(w); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w); + continue; + } + + r = set_put(n->dnssec_negative_trust_anchors, w); + if (r < 0) + return log_oom(); + if (r > 0) + w = NULL; + } + + return 0; +} diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 7817b13cc4..b07fa41abc 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -147,6 +147,7 @@ struct Network { ResolveSupport llmnr; ResolveSupport mdns; DnssecMode dnssec_mode; + Set *dnssec_negative_trust_anchors; LIST_FIELDS(Network, networks); }; @@ -173,6 +174,7 @@ int config_parse_hostname(const char *unit, const char *filename, unsigned line, int config_parse_timezone(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_dhcp_server_dns(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_dhcp_server_ntp(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_negative_trust_anchors(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); /* Legacy IPv4LL support */ int config_parse_ipv4ll(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); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 8631afadb2..f5171a940f 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -1406,6 +1406,25 @@ static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags return false; } +static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) { + int r; + + assert(t); + + /* Check whether the specified name is in the the NTA + * database, either in the global one, or the link-local + * one. */ + + r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name); + if (r != 0) + return r; + + if (!t->scope->link) + return 0; + + return set_contains(t->scope->link->dnssec_negative_trust_anchors, name); +} + static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) { int r; @@ -1422,7 +1441,7 @@ static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) { /* Is this key explicitly listed as a negative trust anchor? * If so, it's nothing we need to care about */ - r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key)); + r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key)); if (r < 0) return r; if (r > 0) @@ -1513,7 +1532,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) { continue; /* If this RR is in the negative trust anchor, we don't need to validate it. */ - r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key)); + r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) @@ -1863,7 +1882,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * if (dns_type_is_pseudo(rr->key->type)) return -EINVAL; - r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key)); + r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) @@ -2066,7 +2085,7 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) { if (dns_type_is_pseudo(t->key->type)) return -EINVAL; - r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(t->key)); + r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(t->key)); if (r < 0) return r; if (r > 0) @@ -2135,7 +2154,7 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe * the specified RRset is authenticated (i.e. has a matching * DS RR). */ - r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, DNS_RESOURCE_KEY_NAME(rr->key)); + r = dns_transaction_negative_trust_anchor_lookup(t, DNS_RESOURCE_KEY_NAME(rr->key)); if (r < 0) return r; if (r > 0) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 50d3f9096b..30838ef8cc 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -82,6 +82,8 @@ Link *link_free(Link *l) { dns_scope_free(l->mdns_ipv4_scope); dns_scope_free(l->mdns_ipv6_scope); + set_free_free(l->dnssec_negative_trust_anchors); + free(l); return NULL; } @@ -302,6 +304,43 @@ clear: return r; } +static int link_update_dnssec_negative_trust_anchors(Link *l) { + _cleanup_strv_free_ char **ntas = NULL; + _cleanup_set_free_free_ Set *ns = NULL; + char **i; + int r; + + assert(l); + + r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + ns = set_new(&dns_name_hash_ops); + if (!ns) + return -ENOMEM; + + STRV_FOREACH(i, ntas) { + r = set_put_strdup(ns, *i); + if (r < 0) + return r; + } + + set_free_free(l->dnssec_negative_trust_anchors); + l->dnssec_negative_trust_anchors = ns; + ns = NULL; + + return 0; + +clear: + l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors); + return r; +} + static int link_update_search_domains(Link *l) { _cleanup_strv_free_ char **domains = NULL; char **i; @@ -365,6 +404,10 @@ int link_update_monitor(Link *l) { if (r < 0) log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name); + r = link_update_dnssec_negative_trust_anchors(l); + if (r < 0) + log_warning_errno(r, "Failed to read DNSSEC negative trust anchors 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); diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index d17b57253b..db0e51da04 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -70,6 +70,7 @@ struct Link { ResolveSupport llmnr_support; ResolveSupport mdns_support; DnssecMode dnssec_mode; + Set *dnssec_negative_trust_anchors; DnsScope *unicast_scope; DnsScope *llmnr_ipv4_scope; diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 00aaa102ce..653c61a162 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -126,6 +126,12 @@ int sd_network_link_get_mdns(int ifindex, char **mdns); */ int sd_network_link_get_dnssec(int ifindex, char **dnssec); +/* Returns the list of per-interface DNSSEC negative trust anchors + * Possible return codes: + * -ENODATA: networkd is not aware of the link, or has no such data + */ +int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta); + int sd_network_link_get_lldp(int ifindex, char **lldp); /* Get the DNS domain names for a given link. */ -- cgit v1.2.3-54-g00ecf