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 4702a095387f5c93428cf183a9f113556552ad9c
Author: meijian <[email protected]>
AuthorDate: Fri Apr 19 16:47:34 2024 +0800

    net/netlink: Add RTM preifx notify support
    
    Signed-off-by: meijian <[email protected]>
---
 include/netpacket/netlink.h |  30 +++++++++++++
 net/icmpv6/icmpv6_input.c   |   3 ++
 net/netlink/Kconfig         |   6 +++
 net/netlink/netlink.h       |  17 ++++++++
 net/netlink/netlink_route.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 160 insertions(+)

diff --git a/include/netpacket/netlink.h b/include/netpacket/netlink.h
index da4e13e165..31daae56a1 100644
--- a/include/netpacket/netlink.h
+++ b/include/netpacket/netlink.h
@@ -704,6 +704,36 @@ struct rtmsg
   uint32_t rtm_flags;
 };
 
+/* Structures used in prefix information. */
+
+struct prefixmsg
+{
+  uint8_t  prefix_family;
+  uint8_t  prefix_pad1;
+  uint16_t prefix_pad2;
+  int32_t  prefix_ifindex;
+  uint8_t  prefix_type;
+  uint8_t  prefix_len;
+  uint8_t  prefix_flags;
+  uint8_t  prefix_pad3;
+};
+
+enum
+{
+  PREFIX_UNSPEC,
+  PREFIX_ADDRESS,
+  PREFIX_CACHEINFO,
+  __PREFIX_MAX
+};
+
+#define PREFIX_MAX (__PREFIX_MAX - 1)
+
+struct prefix_cacheinfo
+{
+  uint32_t preferred_time;
+  uint32_t valid_time;
+};
+
 /* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
  * +---------------------+- - -+- - - - - - - - - -+- - -+
  * |        Header       | Pad |     Payload       | Pad |
diff --git a/net/icmpv6/icmpv6_input.c b/net/icmpv6/icmpv6_input.c
index 17d9137b54..e2be6241ac 100644
--- a/net/icmpv6/icmpv6_input.c
+++ b/net/icmpv6/icmpv6_input.c
@@ -36,6 +36,7 @@
 #include <nuttx/net/dns.h>
 
 #include "devif/devif.h"
+#include "netlink/netlink.h"
 #include "neighbor/neighbor.h"
 #include "utils/utils.h"
 #include "icmpv6/icmpv6.h"
@@ -450,6 +451,8 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned 
int iplen)
                       {
                          icmpv6_setaddresses(dev, ipv6->srcipaddr,
                                     prefixopt->prefix, prefixopt->preflen);
+                        netlink_ipv6_prefix_notify(dev, RTM_NEWPREFIX,
+                                                   prefixopt);
                       }
 
                       /* Notify any waiting threads */
diff --git a/net/netlink/Kconfig b/net/netlink/Kconfig
index 71d60885fd..dd788e6006 100644
--- a/net/netlink/Kconfig
+++ b/net/netlink/Kconfig
@@ -116,6 +116,12 @@ config NETLINK_VALIDATE_POLICY
                VALIDATE_POLICY is used to make sure the parameters
                you pass in are valid.
 
+config NETLINK_DISABLE_NEWPREFIX
+       bool "Disable RTM_NEWPREFIX support"
+       default n
+       ---help---
+               RTM_NEWPREFIX is used to set netdev prefix.
+
 endif # NETLINK_ROUTE
 
 config NETLINK_NETFILTER
diff --git a/net/netlink/netlink.h b/net/netlink/netlink.h
index fd1f81e4b3..9932a9635f 100644
--- a/net/netlink/netlink.h
+++ b/net/netlink/netlink.h
@@ -32,6 +32,7 @@
 
 #include <netpacket/netlink.h>
 #include <nuttx/queue.h>
+#include <nuttx/net/icmpv6.h>
 #include <nuttx/net/netlink.h>
 #include <nuttx/semaphore.h>
 #include <nuttx/wqueue.h>
@@ -48,6 +49,7 @@
 #  define netlink_device_notify_ipaddr(dev, type, domain, addr, preflen)
 #  define netlink_route_notify(route, type, domain)
 #  define netlink_neigh_notify(neigh, type, domain)
+#  define netlink_ipv6_prefix_notify(dev, type, pinfo)
 #endif
 
 #ifdef CONFIG_NET_NETLINK
@@ -552,6 +554,21 @@ void netlink_route_notify(FAR const void *route, int type, 
int domain);
 void netlink_neigh_notify(FAR const void *neigh, int type, int domain);
 #endif
 
+/****************************************************************************
+ * Name: netlink_ipv6_prefix_notify()
+ *
+ * Description:
+ *   Perform the RA prefix for the NETLINK_ROUTE protocol.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NETLINK_DISABLE_NEWPREFIX) || !defined(CONFIG_NET_IPV6)
+#  define netlink_ipv6_prefix_notify(dev, type, pinfo)
+#else
+void netlink_ipv6_prefix_notify(FAR struct net_driver_s *dev, int type,
+                                FAR const struct icmpv6_prefixinfo_s *pinfo);
+#endif
+
 /****************************************************************************
  * Name: nla_next
  *
diff --git a/net/netlink/netlink_route.c b/net/netlink/netlink_route.c
index 24ee4cddda..b4fecc769d 100644
--- a/net/netlink/netlink_route.c
+++ b/net/netlink/netlink_route.c
@@ -29,6 +29,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <debug.h>
+#include <arpa/inet.h>
 
 #include <net/route.h>
 #include <netpacket/netlink.h>
@@ -179,6 +180,32 @@ struct getaddr_recvfrom_rsplist_s
   struct getaddr_recvfrom_response_s payload;
 };
 
+struct getprefix_recvfrom_addr_s
+{
+  struct rtattr  attr;
+  net_ipv6addr_t addr;
+};
+
+struct getprefix_recvfrom_cache_s
+{
+  struct rtattr           attr;
+  struct prefix_cacheinfo pci;
+};
+
+struct getprefix_recvfrom_response_s
+{
+  struct nlmsghdr  hdr;
+  struct prefixmsg pmsg;
+  struct getprefix_recvfrom_addr_s  prefix;
+  struct getprefix_recvfrom_cache_s pci;
+};
+
+struct getprefix_recvfrom_rsplist_s
+{
+  sq_entry_t flink;
+  struct getprefix_recvfrom_response_s payload;
+};
+
 /* netdev_foreach() callback */
 
 struct nlroute_sendto_request_s
@@ -1249,6 +1276,58 @@ static int netlink_get_addr(NETLINK_HANDLE handle,
 }
 #endif
 
+#if !defined(CONFIG_NETLINK_DISABLE_NEWADDR) && defined(CONFIG_NET_IPV6)
+static FAR struct netlink_response_s *
+netlink_fill_ipv6prefix(FAR struct net_driver_s *dev, int type,
+                        FAR const struct icmpv6_prefixinfo_s *pinfo)
+{
+  FAR struct getprefix_recvfrom_rsplist_s *alloc;
+  FAR struct getprefix_recvfrom_response_s *resp;
+
+  DEBUGASSERT(dev != NULL && pinfo != NULL);
+
+  alloc = kmm_zalloc(sizeof(struct getprefix_recvfrom_rsplist_s));
+  if (alloc == NULL)
+    {
+      nerr("ERROR: Failed to allocate response buffer.\n");
+      return NULL;
+    }
+
+  /* Initialize the response buffer */
+
+  resp                  = &alloc->payload;
+
+  resp->hdr.nlmsg_len   = sizeof(struct getprefix_recvfrom_response_s);
+  resp->hdr.nlmsg_type  = type;
+  resp->hdr.nlmsg_flags = 0;
+  resp->hdr.nlmsg_seq   = 0;
+  resp->hdr.nlmsg_pid   = 0;
+
+  resp->pmsg.prefix_family = AF_INET6;
+#ifdef CONFIG_NETDEV_IFINDEX
+  resp->pmsg.prefix_ifindex = dev->d_ifindex;
+#endif
+  resp->pmsg.prefix_len  = pinfo->optlen;
+  resp->pmsg.prefix_type = pinfo->opttype;
+
+  resp->prefix.attr.rta_len  = RTA_LENGTH(sizeof(net_ipv6addr_t));
+  resp->prefix.attr.rta_type = PREFIX_ADDRESS;
+  net_ipv6addr_copy(resp->prefix.addr, pinfo->prefix);
+
+  resp->pci.attr.rta_len  = RTA_LENGTH(sizeof(struct prefix_cacheinfo));
+  resp->pci.attr.rta_type = PREFIX_CACHEINFO;
+
+  resp->pci.pci.preferred_time  = NTOHS(pinfo->plifetime[0]) << 16;
+  resp->pci.pci.preferred_time |= NTOHS(pinfo->plifetime[1]);
+  resp->pci.pci.valid_time      = NTOHS(pinfo->vlifetime[0]) << 16;
+  resp->pci.pci.valid_time     |= NTOHS(pinfo->vlifetime[1]);
+
+  /* Finally, return the response */
+
+  return (FAR struct netlink_response_s *)alloc;
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -1582,4 +1661,29 @@ void netlink_neigh_notify(FAR const void *neigh, int 
type, int domain)
 }
 #endif
 
+/****************************************************************************
+ * Name: netlink_ipv6_prefix_notify()
+ *
+ * Description:
+ *   Perform the RA prefix for the NETLINK_ROUTE protocol.
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NETLINK_DISABLE_NEWADDR) && defined(CONFIG_NET_IPV6)
+void netlink_ipv6_prefix_notify(FAR struct net_driver_s *dev, int type,
+                                FAR const struct icmpv6_prefixinfo_s *pinfo)
+{
+  FAR struct netlink_response_s *resp;
+
+  resp = netlink_fill_ipv6prefix(dev, type, pinfo);
+  if (resp == NULL)
+    {
+      return;
+    }
+
+  netlink_add_broadcast(RTNLGRP_IPV6_PREFIX, resp);
+  netlink_add_terminator(NULL, NULL, RTNLGRP_IPV6_PREFIX);
+}
+#endif
+
 #endif /* CONFIG_NETLINK_ROUTE */

Reply via email to