From 9e25315caa2359077565308e646cd8ef72acb6e6 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 29 Sep 2017 11:10:19 +0300 Subject: [PATCH 1/3] networkd: Add EmitDNS and EmitDomains configuration options Add EmitDNS= and EmitDomains= options to the IPv6PrefixDelegation network configuration file section so that sending DNS servers and DNS search domains can be configured independent of each other. The default values for both are set to true. --- src/network/networkd-network-gperf.gperf | 2 ++ src/network/networkd-network.c | 3 +++ src/network/networkd-network.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index af39d77ce9..ca0d67e3d2 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -152,7 +152,9 @@ IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed) IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0 +IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns) IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0 +IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) IPv6Prefix.Prefix, config_parse_prefix, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 3a7eb2c2a8..bf54a57f3b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -233,6 +233,9 @@ static int network_load_one(Manager *manager, const char *filename) { network->dhcp_server_emit_router = true; network->dhcp_server_emit_timezone = true; + network->router_emit_dns = true; + network->router_emit_domains = true; + network->use_bpdu = true; network->allow_port_to_be_root = true; network->unicast_flood = true; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 9fb0eae380..500325fbd0 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -167,6 +167,8 @@ struct Network { uint8_t router_preference; bool router_managed; bool router_other_information; + bool router_emit_dns; + bool router_emit_domains; usec_t router_dns_lifetime_usec; struct in6_addr *router_dns; unsigned n_router_dns; From c555a358ce6018044c91958df0afdae23271ad9f Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 29 Sep 2017 14:23:38 +0300 Subject: [PATCH 2/3] networkd: Automatically set DNS and search domain information When EmitDNS or EmitDomains is set, automatically look up values for Router Advertisement DNS and DNS search domain options starting with the values in the IPv6PrefixDelegationsection, if any. If none are found, use the values set for the network, and as a last resort try with the preferred upstream network. The default DNS lifetime and therefore Router Advertisement interval is added to the public sd_radv.h header as the DNS lifetime depends on the maximum advertisement interval. --- src/libsystemd-network/radv-internal.h | 2 - src/network/networkd-radv.c | 152 +++++++++++++++++++++---- src/network/networkd-radv.h | 1 + src/systemd/sd-radv.h | 5 + 4 files changed, 138 insertions(+), 22 deletions(-) diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index 5601be844d..b4d0becdd1 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -25,8 +25,6 @@ #include "list.h" #include "sparse-endian.h" -#define SD_RADV_DEFAULT_MIN_TIMEOUT_USEC (200*USEC_PER_SEC) -#define SD_RADV_DEFAULT_MAX_TIMEOUT_USEC (600*USEC_PER_SEC) assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC) #define SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC (16*USEC_PER_SEC) diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 6768208cfa..5c807b887a 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -21,9 +21,140 @@ #include #include "networkd-address.h" +#include "networkd-manager.h" #include "networkd-radv.h" #include "sd-radv.h" +static int radv_get_ip6dns(Network *network, struct in6_addr **dns, + size_t *n_dns) { + _cleanup_free_ struct in6_addr *addresses = NULL; + size_t i, n_addresses = 0, n_allocated = 0; + + assert(network); + assert(dns); + assert(n_dns); + + for (i = 0; i < network->n_dns; i++) { + union in_addr_union *addr; + + if (network->dns[i].family != AF_INET6) + continue; + + addr = &network->dns[i].address; + + if (in_addr_is_null(AF_INET6, addr) || + in_addr_is_link_local(AF_INET6, addr) || + in_addr_is_localhost(AF_INET6, addr)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return -ENOMEM; + + addresses[n_addresses++] = addr->in6; + } + + if (addresses) { + *dns = addresses; + addresses = NULL; + + *n_dns = n_addresses; + } + + return n_addresses; +} + +static int radv_set_dns(Link *link, Link *uplink) { + _cleanup_free_ struct in6_addr *dns = NULL; + size_t n_dns; + usec_t lifetime_usec; + int r; + + if (!link->network->router_emit_dns) + return 0; + + if (link->network->router_dns) { + dns = newdup(struct in6_addr, link->network->router_dns, + link->network->n_router_dns); + if (dns == NULL) + return -ENOMEM; + + n_dns = link->network->n_router_dns; + lifetime_usec = link->network->router_dns_lifetime_usec; + + goto set_dns; + } + + lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; + + r = radv_get_ip6dns(link->network, &dns, &n_dns); + if (r > 0) + goto set_dns; + + if (uplink) { + r = radv_get_ip6dns(uplink->network, &dns, &n_dns); + if (r > 0) + goto set_dns; + } + + return 0; + + set_dns: + return sd_radv_set_rdnss(link->radv, + DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + dns, n_dns); +} + +static int radv_set_domains(Link *link, Link *uplink) { + char **search_domains; + usec_t lifetime_usec; + + if (!link->network->router_emit_domains) + return 0; + + search_domains = link->network->router_search_domains; + lifetime_usec = link->network->router_dns_lifetime_usec; + + if (search_domains) + goto set_domains; + + lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; + + search_domains = link->network->search_domains; + if (search_domains) + goto set_domains; + + if (uplink) { + search_domains = uplink->network->search_domains; + if (search_domains) + goto set_domains; + } + + return 0; + + set_domains: + return sd_radv_set_dnssl(link->radv, + DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + search_domains); + +} + +int radv_emit_dns(Link *link) { + Link *uplink; + int r; + + uplink = manager_find_uplink(link->manager, link); + + r = radv_set_dns(link, uplink); + if (r < 0) + log_link_warning_errno(link, r, "Could not set RA DNS: %m"); + + r = radv_set_domains(link, uplink); + if (r < 0) + log_link_warning_errno(link, r, "Could not set RA Domains: %m"); + + return 0; +} + int radv_configure(Link *link) { int r; Prefix *p; @@ -75,24 +206,5 @@ int radv_configure(Link *link) { return r; } - if (link->network->router_dns) { - r = sd_radv_set_rdnss(link->radv, - DIV_ROUND_UP(link->network->router_dns_lifetime_usec, - USEC_PER_SEC), - link->network->router_dns, - link->network->n_router_dns); - if (r < 0) - return r; - } - - if (link->network->router_search_domains) { - r = sd_radv_set_dnssl(link->radv, - DIV_ROUND_UP(link->network->router_dns_lifetime_usec, - USEC_PER_SEC), - link->network->router_search_domains); - if (r < 0) - return r; - } - - return 0; + return radv_emit_dns(link); } diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index a186b111a1..d59373df9f 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -21,4 +21,5 @@ #include "networkd-link.h" +int radv_emit_dns(Link *link); int radv_configure(Link *link); diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 0cc1d670b9..9805e3f24d 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -33,6 +33,11 @@ _SD_BEGIN_DECLARATIONS; +#define SD_RADV_DEFAULT_MIN_TIMEOUT_USEC (200*USEC_PER_SEC) +#define SD_RADV_DEFAULT_MAX_TIMEOUT_USEC (600*USEC_PER_SEC) + +#define SD_RADV_DEFAULT_DNS_LIFETIME_USEC (3*SD_RADV_DEFAULT_MAX_TIMEOUT_USEC) + typedef struct sd_radv sd_radv; typedef struct sd_radv_prefix sd_radv_prefix; From 4cb8478c409de99ff6cdfcd839a9bb2a86b4d0dd Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 29 Sep 2017 20:48:07 +0300 Subject: [PATCH 3/3] man: Add EmitDNS= and EmitDomains= to the IPv6PrefixDelegation section --- man/systemd.network.xml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index b1759677f9..2fb5886b79 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1452,19 +1452,36 @@ + EmitDNS= DNS= - A list of recursive DNS server IPv6 addresses - distributed via Router Advertisement messages. + DNS= specifies a list of recursive + DNS server IPv6 addresses that distributed via Router Advertisement + messages when EmitDNS= is true. If DNS= + is empty, DNS servers are read from the + [Network] section. If the + [Network] section does not contain any DNS servers + either, DNS servers from the uplink with the highest priority default + route are used. When EmitDNS= is false, no DNS server + information is sent in Router Advertisement messages. + EmitDNS= defaults to true. + EmitDomains= Domains= - A list of DNS search domains distributed via - Router Advertisement messages. Defaults to empty, i.e. no search - domains are sent. + A list of DNS search domains distributed via Router + Advertisement messages when EmitDomains= is true. If + Domains= is empty, DNS search domains are read from the + [Network] section. If the [Network] + section does not contain any DNS search domains either, DNS search + domains from the uplink with the highest priority default route are + used. When EmitDomains= is false, no DNS search domain + information is sent in Router Advertisement messages. + EmitDomains= defaults to true. +