summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd-network/radv-internal.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
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 <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;