summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-10-23 18:39:07 +0200
committerGitHub <noreply@github.com>2017-10-23 18:39:07 +0200
commitd3aa0a1c4265aa48c6565c34eb7aa2b7bb255be7 (patch)
tree092e78cc5d74f7986cdf65b5a58109cd55a75a74
parenthwdb: invert the USB touchpad integration assumption (#7161) (diff)
parentman: Add EmitDNS= and EmitDomains= to the IPv6PrefixDelegation section (diff)
downloadsystemd-d3aa0a1c4265aa48c6565c34eb7aa2b7bb255be7.tar.xz
systemd-d3aa0a1c4265aa48c6565c34eb7aa2b7bb255be7.zip
Merge pull request #6948 from pfl/radv_emit_dns
Add EmitDNS= and EmitDomains= network file configuration options
-rw-r--r--man/systemd.network.xml27
-rw-r--r--src/libsystemd-network/radv-internal.h2
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c3
-rw-r--r--src/network/networkd-network.h2
-rw-r--r--src/network/networkd-radv.c152
-rw-r--r--src/network/networkd-radv.h1
-rw-r--r--src/systemd/sd-radv.h5
8 files changed, 167 insertions, 27 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 @@
</varlistentry>
<varlistentry>
+ <term><varname>EmitDNS=</varname></term>
<term><varname>DNS=</varname></term>
- <listitem><para>A list of recursive DNS server IPv6 addresses
- distributed via Router Advertisement messages.
+ <listitem><para><varname>DNS=</varname> specifies a list of recursive
+ DNS server IPv6 addresses that distributed via Router Advertisement
+ messages when <varname>EmitDNS=</varname> is true. If <varname>DNS=
+ </varname> is empty, DNS servers are read from the
+ <literal>[Network]</literal> section. If the
+ <literal>[Network]</literal> section does not contain any DNS servers
+ either, DNS servers from the uplink with the highest priority default
+ route are used. When <varname>EmitDNS=</varname> is false, no DNS server
+ information is sent in Router Advertisement messages.
+ <varname>EmitDNS=</varname> defaults to true.
</para></listitem>
</varlistentry>
<varlistentry>
+ <term><varname>EmitDomains=</varname></term>
<term><varname>Domains=</varname></term>
- <listitem><para>A list of DNS search domains distributed via
- Router Advertisement messages. Defaults to empty, i.e. no search
- domains are sent.</para></listitem>
+ <listitem><para>A list of DNS search domains distributed via Router
+ Advertisement messages when <varname>EmitDomains=</varname> is true. If
+ <varname>Domains=</varname> is empty, DNS search domains are read from the
+ <literal>[Network]</literal> section. If the <literal>[Network]</literal>
+ section does not contain any DNS search domains either, DNS search
+ domains from the uplink with the highest priority default route are
+ used. When <varname>EmitDomains=</varname> is false, no DNS search domain
+ information is sent in Router Advertisement messages.
+ <varname>EmitDomains=</varname> defaults to true.
+ </para></listitem>
</varlistentry>
<varlistentry>
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-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;
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 <arpa/inet.h>
#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;