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 d9e009cb46315c0467e73d3b4a79410fde079b40
Author: zhanghongyu <[email protected]>
AuthorDate: Wed Mar 15 13:52:18 2023 +0800

    icmpv6: add route advertise RDNSS field handle when icmpv6_input
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 include/nuttx/net/icmpv6.h | 20 ++++++++++++++-----
 net/icmpv6/Kconfig         |  7 +++++++
 net/icmpv6/icmpv6_input.c  | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/include/nuttx/net/icmpv6.h b/include/nuttx/net/icmpv6.h
index cae937a3ab..d9872a3fbd 100644
--- a/include/nuttx/net/icmpv6.h
+++ b/include/nuttx/net/icmpv6.h
@@ -102,11 +102,12 @@
 
 /* Option types */
 
-#define ICMPv6_OPT_SRCLLADDR  1 /* Source Link-Layer Address */
-#define ICMPv6_OPT_TGTLLADDR  2 /* Target Link-Layer Address */
-#define ICMPv6_OPT_PREFIX     3 /* Prefix Information */
-#define ICMPv6_OPT_REDIRECT   4 /* Redirected Header */
-#define ICMPv6_OPT_MTU        5 /* MTU */
+#define ICMPv6_OPT_SRCLLADDR  1  /* Source Link-Layer Address */
+#define ICMPv6_OPT_TGTLLADDR  2  /* Target Link-Layer Address */
+#define ICMPv6_OPT_PREFIX     3  /* Prefix Information */
+#define ICMPv6_OPT_REDIRECT   4  /* Redirected Header */
+#define ICMPv6_OPT_MTU        5  /* MTU */
+#define ICMPv6_OPT_RDNSS      25 /* DNS */
 
 /* ICMPv6 Neighbor Advertisement message flags */
 
@@ -351,6 +352,15 @@ struct icmpv6_mtu_s
   uint16_t mtu[2];           /* "   " ": MTU */
 };
 
+struct icmpv6_rdnss_s
+{
+  uint8_t  opttype;          /* Octet 1: Option Type: ICMPv6_OPT_RNDSS */
+  uint8_t  optlen;           /* "   " ": Option length: 1 octet */
+  uint16_t reserved;         /* "   " ": Reserved */
+  uint16_t lifetime[2];      /* "   " ": lifetime */
+  uint8_t  servers[1];       /* Octets 2-: Beginning of the DNS Servers */
+};
+
 /* The structure holding the ICMP statistics that are gathered if
  * CONFIG_NET_STATISTICS is defined.
  */
diff --git a/net/icmpv6/Kconfig b/net/icmpv6/Kconfig
index d7090e35b0..f83918a5ab 100644
--- a/net/icmpv6/Kconfig
+++ b/net/icmpv6/Kconfig
@@ -88,6 +88,13 @@ config ICMPv6_AUTOCONF_DELAYMSEC
                when an Router Solicitation is sent until the Router
                Advertisement is received.
 
+config ICMPv6_AUTOCONF_RDNSS
+       bool "ICMPv6 handle RDNSS field in router advertise"
+       default n
+       ---help---
+               Handle the RDNSS field in the Router Advertisement and add it to
+               netdb DNS Server.
+
 endif # NET_ICMPv6_AUTOCONF
 
 config NET_ICMPv6_ROUTER
diff --git a/net/icmpv6/icmpv6_input.c b/net/icmpv6/icmpv6_input.c
index 2a1ed92d4e..9216f5ac27 100644
--- a/net/icmpv6/icmpv6_input.c
+++ b/net/icmpv6/icmpv6_input.c
@@ -33,6 +33,7 @@
 #include <nuttx/net/netdev.h>
 #include <nuttx/net/netstats.h>
 #include <nuttx/net/icmpv6.h>
+#include <nuttx/net/dns.h>
 
 #include "devif/devif.h"
 #include "neighbor/neighbor.h"
@@ -357,6 +358,53 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned 
int iplen)
                   }
                   break;
 
+#ifdef CONFIG_ICMPv6_AUTOCONF_RDNSS
+                case ICMPv6_OPT_RDNSS:
+                  {
+                    FAR struct icmpv6_rdnss_s *rdnss =
+                                          (FAR struct icmpv6_rdnss_s *)opt;
+                    FAR struct in6_addr *servers;
+                    struct sockaddr_in6 addr;
+                    int nservers;
+                    int ret;
+                    int i;
+
+                    if (rdnss->optlen < 3)
+                      {
+                        nerr("rdnss error length %d\n", rdnss->optlen);
+                        break;
+                      }
+
+                    /* optlen is in units of 8 bytes. The header is 1 unit
+                     * (8 bytes) and each address is another 2 units
+                     * (16 bytes). So the number of addresses is equal to
+                     * (optlen - 1) / 2.
+                     */
+
+                    servers  = (FAR struct in6_addr *)rdnss->servers;
+                    nservers = (rdnss->optlen - 1) / 2;
+
+                    /* Set the IPv6 DNS server address */
+
+                    memset(&addr, 0, sizeof(addr));
+                    addr.sin6_family = AF_INET6;
+
+                    for (i = 0; i < CONFIG_NETDB_DNSSERVER_NAMESERVERS &&
+                         i < nservers; i++)
+                      {
+                        net_ipv6addr_copy(&addr.sin6_addr, servers + i);
+                        ret = dns_add_nameserver(
+                                          (FAR const struct sockaddr *)&addr,
+                                          sizeof(struct sockaddr_in6));
+                        if (ret < 0 && ret != -EEXIST)
+                          {
+                            nerr("dns add nameserver failed %d", ret);
+                          }
+                      }
+                  }
+                  break;
+#endif
+
                 default:
                   break;
               }

Reply via email to