From 2f9d98cab221a93bd9939ffb6ac637ebb684adc3 Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Thu, 19 Oct 2023 15:35:32 +0800 Subject: [PATCH] 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 --- include/netutils/netlib.h | 14 ++++ netutils/netlib/CMakeLists.txt | 1 + netutils/netlib/Makefile | 1 + netutils/netlib/netlib_addipv6addr.c | 100 +++++++++++++++++++++++++++ netutils/netlib/netlib_delipv6addr.c | 100 +++++++++++++++++++++++++++ netutils/netlib/netlib_setipv4addr.c | 2 +- 6 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 netutils/netlib/netlib_addipv6addr.c create mode 100644 netutils/netlib/netlib_delipv6addr.c 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 :, + * 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_addipv6addr.c b/netutils/netlib/netlib_addipv6addr.c new file mode 100644 index 000000000..142e3e1e3 --- /dev/null +++ b/netutils/netlib/netlib_addipv6addr.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * 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 + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NETDEV_MULTIPLE_IPv6 + +#include +#include + +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_add_ipv6addr + * + * Description: + * Add an IPv6 address to the network driver + * + * Parameters: + * ifname The name of the interface to use + * ipaddr The address to add + * preflen The prefix length of the address + * + * Return: + * 0 on success; -1 on failure + * + ****************************************************************************/ + +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(AF_INET6, NET_SOCK_TYPE, NET_SOCK_PROTOCOL); + if (sockfd >= 0) + { + struct ifreq req; + struct in6_ifreq ifr6; + + /* Add the device name to the request */ + + strlcpy(req.ifr_name, ifname, IFNAMSIZ); + + /* Get interface index */ + + 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)); + } + + close(sockfd); + } + } + + return ret; +} + +#endif /* CONFIG_NETDEV_MULTIPLE_IPv6 */ diff --git a/netutils/netlib/netlib_delipv6addr.c b/netutils/netlib/netlib_delipv6addr.c new file mode 100644 index 000000000..d83ffa807 --- /dev/null +++ b/netutils/netlib/netlib_delipv6addr.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * 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 + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NETDEV_MULTIPLE_IPv6 + +#include +#include + +#include +#include +#include + +#include +#include + +#include "netutils/netlib.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netlib_del_ipv6addr + * + * Description: + * Remove an IPv6 address from the network driver + * + * Parameters: + * ifname The name of the interface to use + * ipaddr The address to delete + * preflen The prefix length of the address + * + * Return: + * 0 on success; -1 on failure + * + ****************************************************************************/ + +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(AF_INET6, NET_SOCK_TYPE, NET_SOCK_PROTOCOL); + if (sockfd >= 0) + { + struct ifreq req; + struct in6_ifreq ifr6; + + /* Add the device name to the request */ + + strlcpy(req.ifr_name, ifname, IFNAMSIZ); + + /* Get interface index */ + + 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)); + } + + close(sockfd); + } + } + + return ret; +} + +#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;