This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ec2b74df77335d48818ea52454b1f8c07be61a07
Author: zhanghongyu <[email protected]>
AuthorDate: Wed Mar 15 19:52:22 2023 +0800

    icmpv6: add RDNSS field support for send route advertise
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 net/icmpv6/Kconfig             |  7 ++++
 net/icmpv6/icmpv6_radvertise.c | 88 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/net/icmpv6/Kconfig b/net/icmpv6/Kconfig
index f83918a5ab..37d78a2494 100644
--- a/net/icmpv6/Kconfig
+++ b/net/icmpv6/Kconfig
@@ -202,6 +202,13 @@ config NET_ICMPv6_PREFIX_8
                Advertisement message.  This is the last of the 8-values.  The
                default for all eight values is fc00::0.
 
+config NET_ICMPv6_ROUTER_RDNSS
+       bool "Fill the RDNSS into Router Advertisement"
+       default n
+       ---help---
+               Fill the RDNSS from the netdb DNS Server into the Router
+               Advertisement.
+
 endif # NET_ICMPv6_ROUTER_MANUAL
 endif # NET_ICMPv6_ROUTER
 
diff --git a/net/icmpv6/icmpv6_radvertise.c b/net/icmpv6/icmpv6_radvertise.c
index 9429b96465..c9a882a973 100644
--- a/net/icmpv6/icmpv6_radvertise.c
+++ b/net/icmpv6/icmpv6_radvertise.c
@@ -28,11 +28,13 @@
 #include <stdint.h>
 #include <string.h>
 #include <debug.h>
+#include <netinet/in.h>
 
 #include <nuttx/net/netconfig.h>
 #include <nuttx/net/netstats.h>
 #include <nuttx/net/netdev.h>
 #include <nuttx/net/icmpv6.h>
+#include <nuttx/net/dns.h>
 
 #include "netdev/netdev.h"
 #include "inet/inet.h"
@@ -41,6 +43,16 @@
 
 #ifdef CONFIG_NET_ICMPv6_ROUTER
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rdnss_add_dns_nameserver_s
+{
+  FAR struct icmpv6_rdnss_s *rdnss;
+  int nservers;
+};
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -92,6 +104,44 @@ static inline void ipv6addr_mask(FAR uint16_t *dest, FAR 
const uint16_t *src,
 }
 #endif /* !CONFIG_NET_ICMPv6_ROUTER_MANUAL */
 
+/****************************************************************************
+ * Name: icmpv6_radvertise_fill_rndss
+ *
+ * Description:
+ *   Copy an IPv6 DNS address into RDNSS field
+ *
+ * Input Parameters:
+ *   arg     - RDNSS context infomation
+ *   addr    - DNS server address
+ *   addrlen - length of DNS server address
+ *
+ * Returned Value:
+ *   0 is success
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_ICMPv6_ROUTER_RDNSS
+static int icmpv6_radvertise_fill_rndss(FAR void *arg,
+                                        FAR struct sockaddr *addr,
+                                        FAR socklen_t addrlen)
+{
+  FAR struct rdnss_add_dns_nameserver_s *rdnss_context = arg;
+  FAR struct sockaddr_in6 *addr6;
+
+  if (addr->sa_family == AF_INET6)
+    {
+      FAR uint8_t *server = rdnss_context->rdnss->servers;
+
+      addr6 = (FAR struct sockaddr_in6 *)addr;
+      net_ipv6addr_copy(server + 16 * rdnss_context->nservers,
+                        &addr6->sin6_addr);
+      rdnss_context->nservers++;
+    }
+
+  return 0;
+}
+#endif /* CONFIG_NET_ICMPv6_ROUTER_RDNSS */
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -120,6 +170,10 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
   FAR struct icmpv6_srclladdr_s *srcaddr;
   FAR struct icmpv6_mtu_s *mtu;
   FAR struct icmpv6_prefixinfo_s *prefix;
+#ifdef CONFIG_NET_ICMPv6_ROUTER_RDNSS
+  FAR struct icmpv6_rdnss_s *rdnss;
+  struct rdnss_add_dns_nameserver_s rndss_context;
+#endif
   net_ipv6addr_t srcv6addr;
   uint16_t lladdrsize;
   uint16_t l3size;
@@ -136,9 +190,6 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
 
   icmpv6_linkipaddr(dev, srcv6addr);
 
-  ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6,
-                    srcv6addr, g_ipv6_allnodes, 255, 0);
-
   /* Set up the ICMPv6 Router Advertise response */
 
   adv               = IPBUF(IPv6_HDRLEN);
@@ -198,6 +249,37 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
   ipv6addr_mask(prefix->prefix, dev->d_ipv6addr, dev->d_ipv6netmask);
 #endif /* CONFIG_NET_ICMPv6_ROUTER_MANUAL */
 
+#ifdef CONFIG_NET_ICMPv6_ROUTER_RDNSS
+  rdnss                  = (FAR struct icmpv6_rdnss_s *)
+                           ((FAR uint8_t *)prefix +
+                           sizeof(struct icmpv6_prefixinfo_s));
+  rndss_context.rdnss    = rdnss;
+  rndss_context.nservers = 0;
+
+  dns_foreach_nameserver(icmpv6_radvertise_fill_rndss, &rndss_context);
+
+  if (rndss_context.nservers > 0)
+    {
+      rdnss->opttype     = ICMPv6_OPT_RDNSS;
+      rdnss->optlen      = 1 + 2 * rndss_context.nservers;
+      rdnss->reserved    = 0;
+
+      /* RFC8106: The value of Lifetime SHOULD by default be at least
+       * 3 * MaxRtrAdvInterval and the MaxRtrAdvInterval default value
+       * is 600 seconds.
+       */
+
+      rdnss->lifetime[0] = 0;
+      rdnss->lifetime[1] = HTONS(1800);
+
+      l3size            += 8 * rdnss->optlen;
+    }
+
+#endif
+
+  ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6,
+                    srcv6addr, g_ipv6_allnodes, 255, 0);
+
   /* Update device buffer length */
 
   iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);

Reply via email to