You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/11/07 16:20:26 UTC

(nuttx-apps) 01/02: netutils/netlib: Add support for add/del a single IPv6 address

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

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

commit 2f9d98cab221a93bd9939ffb6ac637ebb684adc3
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Thu Oct 19 15:35:32 2023 +0800

    netutils/netlib: Add support for add/del a single IPv6 address
    
    Note:
    The `SIOCSIFADDR` and `SIOCDIFADDR` uses different params for `AF_INET` and `AF_INET6` (`struct ifreq` vs `struct in6_ifreq`) as defined by https://man7.org/linux/man-pages/man7/netdevice.7.html
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 include/netutils/netlib.h                          | 14 ++++++++
 netutils/netlib/CMakeLists.txt                     |  1 +
 netutils/netlib/Makefile                           |  1 +
 .../{netlib_setipv4addr.c => netlib_addipv6addr.c} | 41 +++++++++++++---------
 .../{netlib_setipv4addr.c => netlib_delipv6addr.c} | 41 +++++++++++++---------
 netutils/netlib/netlib_setipv4addr.c               |  2 +-
 6 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/include/netutils/netlib.h b/include/netutils/netlib.h
index e99dafbde..8668a86a3 100644
--- a/include/netutils/netlib.h
+++ b/include/netutils/netlib.h
@@ -239,7 +239,21 @@ int netlib_get_ipv4netmask(FAR const char *ifname, FAR struct in_addr *addr);
 int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr);
 #endif
 
+/* We support multiple IPv6 addresses on a single interface.
+ * Recommend to use netlib_add/del_ipv6addr to manage them, by which you
+ * don't need to care about the slot it stored.
+ *
+ * Previous interfaces can still work, the ifname can be <eth>:<num>,
+ * e.g. eth0:0 stands for managing the secondary address on eth0
+ */
+
 #ifdef CONFIG_NET_IPv6
+#  ifdef CONFIG_NETDEV_MULTIPLE_IPv6
+int netlib_add_ipv6addr(FAR const char *ifname,
+                        FAR const struct in6_addr *addr, uint8_t preflen);
+int netlib_del_ipv6addr(FAR const char *ifname,
+                        FAR const struct in6_addr *addr, uint8_t preflen);
+#  endif
 int netlib_get_ipv6addr(FAR const char *ifname, FAR struct in6_addr *addr);
 int netlib_set_ipv6addr(FAR const char *ifname,
                         FAR const struct in6_addr *addr);
diff --git a/netutils/netlib/CMakeLists.txt b/netutils/netlib/CMakeLists.txt
index 5ae551d6f..fd039bc53 100644
--- a/netutils/netlib/CMakeLists.txt
+++ b/netutils/netlib/CMakeLists.txt
@@ -56,6 +56,7 @@ if(CONFIG_NETUTILS_NETLIB)
   endif()
 
   if(CONFIG_NET_IPv6)
+    list(APPEND SRCS netlib_addipv6addr.c netlib_delipv6addr.c)
     list(APPEND SRCS netlib_setipv6addr.c netlib_getipv6addr.c)
     list(APPEND SRCS netlib_setdripv6addr.c netlib_setipv6netmask.c)
     list(APPEND SRCS netlib_prefix2ipv6netmask.c netlib_ipv6netmask2prefix.c)
diff --git a/netutils/netlib/Makefile b/netutils/netlib/Makefile
index bd6673017..12aac379e 100644
--- a/netutils/netlib/Makefile
+++ b/netutils/netlib/Makefile
@@ -56,6 +56,7 @@ endif
 endif
 
 ifeq ($(CONFIG_NET_IPv6),y)
+CSRCS += netlib_addipv6addr.c netlib_delipv6addr.c
 CSRCS += netlib_setipv6addr.c netlib_getipv6addr.c
 CSRCS += netlib_setdripv6addr.c netlib_setipv6netmask.c
 CSRCS += netlib_prefix2ipv6netmask.c netlib_ipv6netmask2prefix.c
diff --git a/netutils/netlib/netlib_setipv4addr.c b/netutils/netlib/netlib_addipv6addr.c
similarity index 67%
copy from netutils/netlib/netlib_setipv4addr.c
copy to netutils/netlib/netlib_addipv6addr.c
index dca8f09fb..142e3e1e3 100644
--- a/netutils/netlib/netlib_setipv4addr.c
+++ b/netutils/netlib/netlib_addipv6addr.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * apps/netutils/netlib/netlib_setipv4addr.c
+ * apps/netutils/netlib/netlib_addipv6addr.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -23,7 +23,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NETDEV_MULTIPLE_IPv6
 
 #include <sys/socket.h>
 #include <sys/ioctl.h>
@@ -42,45 +42,54 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: netlib_set_ipv4addr
+ * Name: netlib_add_ipv6addr
  *
  * Description:
- *   Set the network driver IPv4 address
+ *   Add an IPv6 address to the network driver
  *
  * Parameters:
  *   ifname   The name of the interface to use
- *   ipaddr   The address to set
+ *   ipaddr   The address to add
+ *   preflen  The prefix length of the address
  *
  * Return:
  *   0 on success; -1 on failure
  *
  ****************************************************************************/
 
-int netlib_set_ipv4addr(FAR const char *ifname,
-                        FAR const struct in_addr *addr)
+int netlib_add_ipv6addr(FAR const char *ifname,
+                        FAR const struct in6_addr *addr, uint8_t preflen)
 {
   int ret = ERROR;
 
   if (ifname && addr)
     {
-      int sockfd = socket(NET_SOCK_FAMILY, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
+      int sockfd = socket(AF_INET6, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
       if (sockfd >= 0)
         {
-          FAR struct sockaddr_in *inaddr;
           struct ifreq req;
+          struct in6_ifreq ifr6;
 
           /* Add the device name to the request */
 
           strlcpy(req.ifr_name, ifname, IFNAMSIZ);
 
-          /* Add the INET address to the request */
+          /* Get interface index */
 
-          inaddr             = (FAR struct sockaddr_in *)&req.ifr_addr;
-          inaddr->sin_family = AF_INET;
-          inaddr->sin_port   = 0;
-          memcpy(&inaddr->sin_addr, addr, sizeof(struct in_addr));
+          ret = ioctl(sockfd, SIOCGIFINDEX,
+                     ((unsigned long)(uintptr_t)&req));
+          if (ret == OK)
+            {
+              /* Add address to the interface. */
+
+              ifr6.ifr6_ifindex = req.ifr_ifindex;
+              ifr6.ifr6_prefixlen = preflen;
+              memcpy(&ifr6.ifr6_addr, addr, sizeof(struct in6_addr));
+
+              ret = ioctl(sockfd, SIOCSIFADDR,
+                          ((unsigned long)(uintptr_t)&ifr6));
+            }
 
-          ret = ioctl(sockfd, SIOCSIFADDR, (unsigned long)&req);
           close(sockfd);
         }
     }
@@ -88,4 +97,4 @@ int netlib_set_ipv4addr(FAR const char *ifname,
   return ret;
 }
 
-#endif /* CONFIG_NET_IPv4 */
+#endif /* CONFIG_NETDEV_MULTIPLE_IPv6 */
diff --git a/netutils/netlib/netlib_setipv4addr.c b/netutils/netlib/netlib_delipv6addr.c
similarity index 66%
copy from netutils/netlib/netlib_setipv4addr.c
copy to netutils/netlib/netlib_delipv6addr.c
index dca8f09fb..d83ffa807 100644
--- a/netutils/netlib/netlib_setipv4addr.c
+++ b/netutils/netlib/netlib_delipv6addr.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * apps/netutils/netlib/netlib_setipv4addr.c
+ * apps/netutils/netlib/netlib_delipv6addr.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -23,7 +23,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NETDEV_MULTIPLE_IPv6
 
 #include <sys/socket.h>
 #include <sys/ioctl.h>
@@ -42,45 +42,54 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: netlib_set_ipv4addr
+ * Name: netlib_del_ipv6addr
  *
  * Description:
- *   Set the network driver IPv4 address
+ *   Remove an IPv6 address from the network driver
  *
  * Parameters:
  *   ifname   The name of the interface to use
- *   ipaddr   The address to set
+ *   ipaddr   The address to delete
+ *   preflen  The prefix length of the address
  *
  * Return:
  *   0 on success; -1 on failure
  *
  ****************************************************************************/
 
-int netlib_set_ipv4addr(FAR const char *ifname,
-                        FAR const struct in_addr *addr)
+int netlib_del_ipv6addr(FAR const char *ifname,
+                        FAR const struct in6_addr *addr, uint8_t preflen)
 {
   int ret = ERROR;
 
   if (ifname && addr)
     {
-      int sockfd = socket(NET_SOCK_FAMILY, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
+      int sockfd = socket(AF_INET6, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
       if (sockfd >= 0)
         {
-          FAR struct sockaddr_in *inaddr;
           struct ifreq req;
+          struct in6_ifreq ifr6;
 
           /* Add the device name to the request */
 
           strlcpy(req.ifr_name, ifname, IFNAMSIZ);
 
-          /* Add the INET address to the request */
+          /* Get interface index */
 
-          inaddr             = (FAR struct sockaddr_in *)&req.ifr_addr;
-          inaddr->sin_family = AF_INET;
-          inaddr->sin_port   = 0;
-          memcpy(&inaddr->sin_addr, addr, sizeof(struct in_addr));
+          ret = ioctl(sockfd, SIOCGIFINDEX,
+                     ((unsigned long)(uintptr_t)&req));
+          if (ret == OK)
+            {
+              /* Delete address from the interface. */
+
+              ifr6.ifr6_ifindex = req.ifr_ifindex;
+              ifr6.ifr6_prefixlen = preflen;
+              memcpy(&ifr6.ifr6_addr, addr, sizeof(struct in6_addr));
+
+              ret = ioctl(sockfd, SIOCDIFADDR,
+                          ((unsigned long)(uintptr_t)&ifr6));
+            }
 
-          ret = ioctl(sockfd, SIOCSIFADDR, (unsigned long)&req);
           close(sockfd);
         }
     }
@@ -88,4 +97,4 @@ int netlib_set_ipv4addr(FAR const char *ifname,
   return ret;
 }
 
-#endif /* CONFIG_NET_IPv4 */
+#endif /* CONFIG_NETDEV_MULTIPLE_IPv6 */
diff --git a/netutils/netlib/netlib_setipv4addr.c b/netutils/netlib/netlib_setipv4addr.c
index dca8f09fb..8ada0e48a 100644
--- a/netutils/netlib/netlib_setipv4addr.c
+++ b/netutils/netlib/netlib_setipv4addr.c
@@ -63,7 +63,7 @@ int netlib_set_ipv4addr(FAR const char *ifname,
 
   if (ifname && addr)
     {
-      int sockfd = socket(NET_SOCK_FAMILY, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
+      int sockfd = socket(AF_INET, NET_SOCK_TYPE, NET_SOCK_PROTOCOL);
       if (sockfd >= 0)
         {
           FAR struct sockaddr_in *inaddr;