From 0ef62b9690ee09b559e09a5235c5c7bbf0ecea5c Mon Sep 17 00:00:00 2001
From: Martine Lenders <m.lenders@fu-berlin.de>
Date: Mon, 26 Feb 2018 17:34:43 +0100
Subject: [PATCH] gnrc_ndp: add support for building RDNSS option

---
 Makefile.dep                              |  7 +++++++
 makefiles/pseudomodules.inc.mk            |  1 +
 sys/include/net/gnrc/ipv6/nib/conf.h      | 13 +++++++++++++
 sys/include/net/gnrc/ndp.h                | 23 +++++++++++++++++++++++
 sys/net/gnrc/network_layer/ndp/gnrc_ndp.c | 21 +++++++++++++++++++++
 5 files changed, 65 insertions(+)

diff --git a/Makefile.dep b/Makefile.dep
index 0d1751434a..9237561036 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -305,6 +305,10 @@ ifneq (,$(filter gnrc_ipv6_nib_6ln,$(USEMODULE)))
   USEMODULE += gnrc_sixlowpan_nd
 endif
 
+ifneq (,$(filter gnrc_ipv6_nib_dns,$(USEMODULE)))
+  USEMODULE += gnrc_ipv6_nib
+endif
+
 ifneq (,$(filter gnrc_ipv6_nib_router,$(USEMODULE)))
   USEMODULE += gnrc_ipv6_nib
 endif
@@ -315,6 +319,9 @@ ifneq (,$(filter gnrc_ipv6_nib,$(USEMODULE)))
   USEMODULE += gnrc_netif
   USEMODULE += ipv6_addr
   USEMODULE += random
+  ifneq (,$(filter sock_dns,$(USEMODULE)))
+    USEMODULE += gnrc_ipv6_nib_dns
+  endif
 endif
 
 ifneq (,$(filter gnrc_udp,$(USEMODULE)))
diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk
index 1b4ca0337e..dca9b530d0 100644
--- a/makefiles/pseudomodules.inc.mk
+++ b/makefiles/pseudomodules.inc.mk
@@ -17,6 +17,7 @@ PSEUDOMODULES += gnrc_ipv6_router_default
 PSEUDOMODULES += gnrc_ipv6_nib_6lbr
 PSEUDOMODULES += gnrc_ipv6_nib_6ln
 PSEUDOMODULES += gnrc_ipv6_nib_6lr
+PSEUDOMODULES += gnrc_ipv6_nib_dns
 PSEUDOMODULES += gnrc_ipv6_nib_router
 PSEUDOMODULES += gnrc_netdev_default
 PSEUDOMODULES += gnrc_neterr
diff --git a/sys/include/net/gnrc/ipv6/nib/conf.h b/sys/include/net/gnrc/ipv6/nib/conf.h
index a62c4b47d0..d859428782 100644
--- a/sys/include/net/gnrc/ipv6/nib/conf.h
+++ b/sys/include/net/gnrc/ipv6/nib/conf.h
@@ -68,6 +68,10 @@ extern "C" {
 #define GNRC_IPV6_NIB_CONF_ROUTER       (1)
 #endif
 
+#ifdef MODULE_GNRC_IPV6_NIB_DNS
+#define GNRC_IPV6_NIB_CONF_DNS          (1)
+#endif
+
 /**
  * @name    Compile flags
  * @brief   Compile flags to (de-)activate certain features for NIB
@@ -171,6 +175,15 @@ extern "C" {
 #endif
 #endif
 
+/**
+ * @brief   Support for DNS configuration options
+ *
+ * @see [RFC 8106](https://tools.ietf.org/html/rfc8106)
+ */
+#ifndef GNRC_IPV6_NIB_CONF_DNS
+#define GNRC_IPV6_NIB_CONF_DNS          (0)
+#endif
+
 /**
  * @brief   Multihop prefix and 6LoWPAN context distribution
  *
diff --git a/sys/include/net/gnrc/ndp.h b/sys/include/net/gnrc/ndp.h
index 660f47646f..94aff38982 100644
--- a/sys/include/net/gnrc/ndp.h
+++ b/sys/include/net/gnrc/ndp.h
@@ -250,6 +250,29 @@ gnrc_pktsnip_t *gnrc_ndp_opt_pi_build(const ipv6_addr_t *prefix,
  */
 gnrc_pktsnip_t *gnrc_ndp_opt_mtu_build(uint32_t mtu, gnrc_pktsnip_t *next);
 
+/**
+ * @brief   Builts the recursive DNS server option
+ *
+ * @see [RFC 8106, section 5.1](https://tools.ietf.org/html/rfc8106#section-5.1)
+ * @pre `addrs != NULL`
+ * @pre `addrs_num > 0`
+ *
+ * @note    Should only be used with router advertisemnents. This is not checked
+ *          however, since nodes should silently ignore it in other NDP messages.
+ *
+ * @param[in] lifetime      The lifetime of the recursive DNS servers
+ * @param[in] addrs         The addresses of the recursive DNS servers
+ * @param[in] addrs_num     The number of addresses in @p addrs
+ * @param[in] next          More options in the packet. NULL, if there are none.
+ *
+ * @return  The packet snip list of options, on success
+ * @return  @p next, if RDNSS is not supported
+ * @return  NULL, if packet buffer is full
+ */
+gnrc_pktsnip_t *gnrc_ndp_opt_rdnss_build(uint32_t lifetime, ipv6_addr_t *addrs,
+                                         unsigned addrs_num,
+                                         gnrc_pktsnip_t *next);
+
 /**
  * @brief   Send pre-compiled neighbor solicitation depending on a given network
  *          interface.
diff --git a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
index afce23dac9..e467ea9506 100644
--- a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
+++ b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c
@@ -222,6 +222,27 @@ gnrc_pktsnip_t *gnrc_ndp_opt_mtu_build(uint32_t mtu, gnrc_pktsnip_t *next)
     return pkt;
 }
 
+gnrc_pktsnip_t *gnrc_ndp_opt_rdnss_build(uint32_t ltime, ipv6_addr_t *addrs,
+                                         unsigned addrs_num,
+                                         gnrc_pktsnip_t *next)
+{
+    assert(addrs != NULL);
+    assert(addrs_num > 0);
+    size_t opt_size = sizeof(ndp_opt_t) + (sizeof(ipv6_addr_t) * addrs_num);
+    gnrc_pktsnip_t *pkt = gnrc_ndp_opt_build(NDP_OPT_RDNSS, opt_size, next);
+
+    if (pkt != NULL) {
+        ndp_opt_rdnss_t *rdnss_opt = pkt->data;
+        rdnss_opt->resv.u16 = 0;
+        rdnss_opt->ltime = byteorder_htonl(ltime);
+        for (unsigned i = 0; i < addrs_num; i++) {
+            memcpy(&rdnss_opt->addrs[i], &addrs[i],
+                   sizeof(rdnss_opt->addrs[i]));
+        }
+    }
+    return pkt;
+}
+
 static gnrc_pktsnip_t *_build_headers(gnrc_netif_t *netif,
                                       const ipv6_addr_t *src,
                                       const ipv6_addr_t *dst,
-- 
GitLab