]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-radv: Add Router Advertisement DNS Search List option
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 21 Aug 2017 10:41:20 +0000 (13:41 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Fri, 15 Sep 2017 07:34:57 +0000 (10:34 +0300)
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.

src/libsystemd-network/radv-internal.h
src/libsystemd-network/sd-radv.c
src/systemd/sd-radv.h

index c3f847ec059137f720c128a40a3dc11ed6b4a532..5601be844d35ed1aff57c799d0023b1b66a51a36 100644 (file)
@@ -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 {
index 70772b4f150285ca2bd94c7aea86151725f4f1b9..f05c44032d261d0acaa7a73b63b58bc69a16378b 100644 (file)
 
 #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;
 
index ce10ae0606303af4ca448cdf54b741158acb107c..0cc1d670b9a27ff21a777442e23535e347f88949 100644 (file)
@@ -59,6 +59,7 @@ int sd_radv_set_preference(sd_radv *ra, unsigned preference);
 int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p);
 int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
                       const struct in6_addr *dns, size_t n_dns);
+int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime, char **search_list);
 
 /* Advertised prefixes */
 int sd_radv_prefix_new(sd_radv_prefix **ret);