summaryrefslogtreecommitdiffstats
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2017-08-21 12:41:20 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2017-09-15 09:34:57 +0200
commite965d6aba3d6a23783173a19fe850e8b384ad4fb (patch)
treeec2c887e3e32e2924321c394652db290311659e3 /src/libsystemd-network
parentnetworkd: Parse DNS search domain information for Router Advertisement (diff)
downloadsystemd-e965d6aba3d6a23783173a19fe850e8b384ad4fb.tar.xz
systemd-e965d6aba3d6a23783173a19fe850e8b384ad4fb.zip
sd-radv: Add Router Advertisement DNS Search List option
Add Router Advertisement DNS Search List option as specified in RFC 8106. The search list option uses and identical option header as the RDNSS option and therefore the option header structure can be reused. If systemd is compiled with IDNA support, internationalization of the provided search domain is applied, after which the search list is written in wire format into the DNSSL option.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/radv-internal.h2
-rw-r--r--src/libsystemd-network/sd-radv.c60
2 files changed, 62 insertions, 0 deletions
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
index c3f847ec05..5601be844d 100644
--- a/src/libsystemd-network/radv-internal.h
+++ b/src/libsystemd-network/radv-internal.h
@@ -36,6 +36,7 @@ assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC)
#define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC)
#define SD_RADV_OPT_RDNSS 25
+#define SD_RADV_OPT_DNSSL 31
enum RAdvState {
SD_RADV_STATE_IDLE = 0,
@@ -75,6 +76,7 @@ struct sd_radv {
size_t n_rdnss;
struct sd_radv_opt_dns *rdnss;
+ struct sd_radv_opt_dns *dnssl;
};
struct sd_radv_prefix {
diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c
index 70772b4f15..f05c44032d 100644
--- a/src/libsystemd-network/sd-radv.c
+++ b/src/libsystemd-network/sd-radv.c
@@ -26,12 +26,14 @@
#include "macro.h"
#include "alloc-util.h"
+#include "dns-domain.h"
#include "fd-util.h"
#include "icmp6-util.h"
#include "in-addr-util.h"
#include "radv-internal.h"
#include "socket-util.h"
#include "string-util.h"
+#include "strv.h"
#include "util.h"
#include "random-util.h"
@@ -204,6 +206,12 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst,
msg.msg_iovlen++;
}
+ if (ra->dnssl) {
+ iov[msg.msg_iovlen].iov_base = ra->dnssl;
+ iov[msg.msg_iovlen].iov_len = ra->dnssl->length * 8;
+ msg.msg_iovlen++;
+ }
+
if (sendmsg(ra->fd, &msg, 0) < 0)
return -errno;
@@ -590,6 +598,58 @@ _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
return 0;
}
+_public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
+ char **search_list) {
+ _cleanup_free_ struct sd_radv_opt_dns *opt_dnssl = NULL;
+ size_t len = 0;
+ char **s;
+ uint8_t *p;
+
+ assert_return(ra, -EINVAL);
+
+ if (!search_list || *search_list == NULL) {
+ ra->dnssl = mfree(ra->dnssl);
+
+ return 0;
+ }
+
+ STRV_FOREACH(s, search_list)
+ len += strlen(*s) + 2;
+
+ len = (sizeof(struct sd_radv_opt_dns) + len + 7) & ~0x7;
+
+ opt_dnssl = malloc0(len);
+ if (!opt_dnssl)
+ return -ENOMEM;
+
+ opt_dnssl->type = SD_RADV_OPT_DNSSL;
+ opt_dnssl->length = len / 8;
+ opt_dnssl->lifetime = htobe32(lifetime);
+
+ p = (uint8_t *)(opt_dnssl + 1);
+ len -= sizeof(struct sd_radv_opt_dns);
+
+ STRV_FOREACH(s, search_list) {
+ int r;
+
+ r = dns_name_to_wire_format(*s, p, len, false);
+ if (r < 0)
+ return r;
+
+ if (len < (size_t)r)
+ return -ENOBUFS;
+
+ p += r;
+ len -= r;
+ }
+
+ free(ra->dnssl);
+ ra->dnssl = opt_dnssl;
+ opt_dnssl = NULL;
+
+ return 0;
+}
+
_public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;