Replace os_sockQueryInterfaces by os_getifaddrs
Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
parent
2fc4cac1a7
commit
458b1df3f7
23 changed files with 696 additions and 597 deletions
|
@ -17,10 +17,10 @@ IF(${platform} IN_LIST posix_platforms)
|
|||
set(platform posix)
|
||||
ENDIF()
|
||||
|
||||
PREPEND(srcs_platform ${platform} os_platform_errno.c os_platform_heap.c os_platform_init.c os_platform_process.c os_platform_socket.c os_platform_stdlib.c os_platform_sync.c os_platform_thread.c os_platform_time.c)
|
||||
PREPEND(srcs_platform ${platform} os_platform_errno.c os_platform_heap.c os_platform_init.c os_platform_process.c os_platform_ifaddrs.c os_platform_socket.c os_platform_stdlib.c os_platform_sync.c os_platform_thread.c os_platform_time.c)
|
||||
|
||||
include (GenerateExportHeader)
|
||||
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_report.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
|
||||
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_report.c os_ifaddrs.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
|
||||
add_library(OSAPI ${srcs_os})
|
||||
|
||||
configure_file(
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
#ifndef OS_SOCKET_HAS_IPV6
|
||||
#error "OS_SOCKET_HAS_IPV6 should have been defined by os_platform_socket.h"
|
||||
#endif
|
||||
#ifndef OS_IFNAMESIZE
|
||||
#error "OS_IFNAMESIZE should have been defined by os_platform_socket.h"
|
||||
#endif
|
||||
#ifndef OS_SOCKET_HAS_SA_LEN
|
||||
#error "OS_SOCKET_HAS_SA_LEN should have been defined by os_platform_socket.h"
|
||||
#endif
|
||||
#ifndef OS_NO_SIOCGIFINDEX
|
||||
#error "OS_NO_SIOCGIFINDEX should have been defined by os_platform_socket.h"
|
||||
#endif
|
||||
|
@ -94,11 +88,7 @@ extern "C" {
|
|||
typedef struct ipv6_mreq os_ipv6_mreq;
|
||||
typedef struct in6_addr os_in6_addr;
|
||||
|
||||
#if defined (OSPL_VXWORKS653)
|
||||
typedef struct sockaddr_in os_sockaddr_storage;
|
||||
#else
|
||||
typedef struct sockaddr_storage os_sockaddr_storage;
|
||||
#endif
|
||||
|
||||
typedef struct sockaddr_in6 os_sockaddr_in6;
|
||||
#endif
|
||||
|
@ -120,59 +110,50 @@ extern "C" {
|
|||
|
||||
#define SD_FLAG_IS_SET(flags, flag) ((((uint32_t)(flags) & (uint32_t)(flag))) != 0U)
|
||||
|
||||
/**
|
||||
* Structure to hold a network interface's attributes
|
||||
*/
|
||||
typedef struct os_ifAttributes_s {
|
||||
/**
|
||||
* The network interface name (or at least OS_IFNAMESIZE - 1 charcaters thereof)
|
||||
*/
|
||||
char name[OS_IFNAMESIZE];
|
||||
/**
|
||||
* Iff the interface is IPv4 holds the ioctl query result flags for this interface.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t af_inet : 1;
|
||||
uint8_t af_inet6 : 1;
|
||||
uint8_t af_packet : 1;
|
||||
} os_ifaddr_filter_t;
|
||||
|
||||
/** Network interface attributes */
|
||||
typedef struct os_ifaddrs_s {
|
||||
struct os_ifaddrs_s *next;
|
||||
char *name;
|
||||
uint32_t index;
|
||||
uint32_t flags;
|
||||
/**
|
||||
* The network interface address of this interface.
|
||||
*/
|
||||
os_sockaddr_storage address;
|
||||
/**
|
||||
* Iff this is an IPv4 interface, holds the broadcast address for the sub-network this
|
||||
* interface is connected to.
|
||||
*/
|
||||
os_sockaddr_storage broadcast_address;
|
||||
/**
|
||||
* Iff this is an IPv4 interface, holds the subnet mast for this interface
|
||||
*/
|
||||
os_sockaddr_storage network_mask;
|
||||
/**
|
||||
* Holds the interface index for this interface.
|
||||
*/
|
||||
unsigned interfaceIndexNo;
|
||||
} os_ifAttributes;
|
||||
|
||||
OSAPI_EXPORT os_result
|
||||
os_sockQueryInterfaces(
|
||||
os_ifAttributes *ifList,
|
||||
uint32_t listSize,
|
||||
uint32_t *validElements);
|
||||
os_sockaddr *addr;
|
||||
os_sockaddr *netmask;
|
||||
os_sockaddr *broadaddr;
|
||||
} os_ifaddrs_t;
|
||||
|
||||
/**
|
||||
* Fill-in a pre-allocated list of os_ifAttributes_s with details of
|
||||
* the available IPv6 network interfaces.
|
||||
* @param listSize Number of elements there is space for in the list.
|
||||
* @param ifList Pointer to head of list
|
||||
* @param validElements Out param to hold the number of interfaces found
|
||||
* whose detauils have been returned.
|
||||
* @return os_resultSuccess if 0 or more interfaces were found, os_resultFail if
|
||||
* an error occurred.
|
||||
* @see os_sockQueryInterfaces
|
||||
* @brief Get interface addresses
|
||||
*
|
||||
* Retrieve network interfaces available on the local system and store
|
||||
* them in a linked list of os_ifaddrs_t structures.
|
||||
*
|
||||
* The data returned by os_getifaddrs() is dynamically allocated and should
|
||||
* be freed using os_freeifaddrs when no longer needed.
|
||||
*
|
||||
* @param[in,out] ifap Address of first os_ifaddrs_t structure in the list.
|
||||
* @param[in] ifilt FIXME: comment
|
||||
*
|
||||
* @returns Returns zero on success or a valid errno value on error.
|
||||
*/
|
||||
OSAPI_EXPORT os_result
|
||||
os_sockQueryIPv6Interfaces(
|
||||
os_ifAttributes *ifList,
|
||||
uint32_t listSize,
|
||||
uint32_t *validElements);
|
||||
OSAPI_EXPORT _Success_(return == 0) int
|
||||
os_getifaddrs(
|
||||
_Inout_ os_ifaddrs_t **ifap,
|
||||
_In_ const os_ifaddr_filter_t *ifilt);
|
||||
|
||||
/**
|
||||
* @brief Free os_ifaddrs_t structure list allocated by os_getifaddrs()
|
||||
*
|
||||
* @param[in] Address of first os_ifaddrs_t structure in the list.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
os_freeifaddrs(
|
||||
_Pre_maybenull_ _Post_ptr_invalid_ os_ifaddrs_t *ifa);
|
||||
|
||||
OSAPI_EXPORT os_socket
|
||||
os_sockNew(
|
||||
|
|
|
@ -262,6 +262,9 @@ extern "C" {
|
|||
__attribute_returns_nonnull__
|
||||
__attribute_warn_unused_result__;
|
||||
|
||||
void *
|
||||
os_memdup(void *src, size_t n);
|
||||
|
||||
/** \brief os_strsep wrapper
|
||||
*
|
||||
* See strsep()
|
||||
|
@ -271,6 +274,14 @@ extern "C" {
|
|||
char **stringp,
|
||||
const char *delim);
|
||||
|
||||
/** \brief write a formatted string to a newly allocated buffer
|
||||
*/
|
||||
OSAPI_EXPORT int
|
||||
os_asprintf(
|
||||
char **strp,
|
||||
const char *fmt,
|
||||
...);
|
||||
|
||||
/** \brief os_vsnprintf wrapper
|
||||
*
|
||||
* Microsoft generates deprected warnings for vsnprintf,
|
||||
|
|
|
@ -39,7 +39,6 @@ extern "C" {
|
|||
|
||||
/* Keep defines before common header */
|
||||
#define OS_SOCKET_HAS_IPV6 1
|
||||
#define OS_IFNAMESIZE IF_NAMESIZE
|
||||
#define OS_SOCKET_HAS_SA_LEN 1
|
||||
#define OS_NO_SIOCGIFINDEX 1
|
||||
#define OS_NO_NETLINK 1
|
||||
|
|
|
@ -25,7 +25,6 @@ extern "C" {
|
|||
|
||||
/* Keep defines before common header */
|
||||
#define OS_SOCKET_HAS_IPV6 1
|
||||
#define OS_IFNAMESIZE 128
|
||||
#define OS_SOCKET_HAS_SA_LEN 0
|
||||
#define OS_NO_SIOCGIFINDEX 1
|
||||
#define OS_NO_NETLINK 1
|
||||
|
|
29
src/os/src/os_ifaddrs.c
Normal file
29
src/os/src/os_ifaddrs.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "os/os.h"
|
||||
|
||||
void
|
||||
os_freeifaddrs(os_ifaddrs_t *ifa)
|
||||
{
|
||||
os_ifaddrs_t *next;
|
||||
|
||||
while (ifa != NULL) {
|
||||
next = ifa->next;
|
||||
os_free(ifa->name);
|
||||
os_free(ifa->addr);
|
||||
os_free(ifa->netmask);
|
||||
os_free(ifa->broadaddr);
|
||||
os_free(ifa);
|
||||
ifa = next;
|
||||
}
|
||||
}
|
||||
|
128
src/os/src/posix/os_platform_ifaddrs.c
Normal file
128
src/os/src/posix/os_platform_ifaddrs.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__linux)
|
||||
#include <linux/if_packet.h> /* sockaddr_ll */
|
||||
#endif /* __linux */
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
static int
|
||||
copy_ifaddrs(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
|
||||
{
|
||||
int err = 0;
|
||||
os_ifaddrs_t *ifa;
|
||||
size_t size;
|
||||
|
||||
assert(ifap != NULL);
|
||||
assert(sys_ifa != NULL);
|
||||
assert(sys_ifa->ifa_addr->sa_family == AF_INET ||
|
||||
sys_ifa->ifa_addr->sa_family == AF_INET6 ||
|
||||
sys_ifa->ifa_addr->sa_family == AF_PACKET);
|
||||
|
||||
ifa = os_malloc(sizeof(*ifa));
|
||||
if (ifa == NULL) {
|
||||
err = errno;
|
||||
} else {
|
||||
(void)memset(ifa, 0, sizeof(*ifa));
|
||||
|
||||
ifa->index = if_nametoindex(sys_ifa->ifa_name);
|
||||
ifa->flags = sys_ifa->ifa_flags;
|
||||
if ((ifa->name = os_strdup(sys_ifa->ifa_name)) == NULL) {
|
||||
err = errno;
|
||||
} else if (sys_ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
size = sizeof(struct sockaddr_in6);
|
||||
if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, size))) {
|
||||
err = errno;
|
||||
}
|
||||
} else {
|
||||
if (sys_ifa->ifa_addr->sa_family == AF_INET) {
|
||||
size = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
assert(sys_ifa->ifa_addr->sa_family == AF_PACKET);
|
||||
size = sizeof(struct sockaddr_ll);
|
||||
}
|
||||
|
||||
if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, size)) ||
|
||||
(sys_ifa->ifa_netmask &&
|
||||
!(ifa->netmask = os_memdup(sys_ifa->ifa_netmask, size))) ||
|
||||
(sys_ifa->ifa_broadaddr &&
|
||||
!(ifa->broadaddr = os_memdup(sys_ifa->ifa_broadaddr, size))))
|
||||
{
|
||||
err = errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
os_freeifaddrs(ifa);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
_Success_(return == 0) int
|
||||
os_getifaddrs(
|
||||
_Inout_ os_ifaddrs_t **ifap,
|
||||
_In_opt_ const os_ifaddr_filter_t *ifltr)
|
||||
{
|
||||
int err = 0;
|
||||
os_ifaddrs_t *ifa, *ifa_root, *ifa_next;
|
||||
struct ifaddrs *sys_ifa, *sys_ifa_root;
|
||||
struct sockaddr *addr;
|
||||
|
||||
assert(ifap != NULL);
|
||||
assert(ifltr != NULL);
|
||||
|
||||
if (getifaddrs(&sys_ifa_root) == -1) {
|
||||
err = errno;
|
||||
} else {
|
||||
ifa = ifa_root = NULL;
|
||||
|
||||
for (sys_ifa = sys_ifa_root;
|
||||
sys_ifa != NULL && err == 0;
|
||||
sys_ifa = sys_ifa->ifa_next)
|
||||
{
|
||||
addr = sys_ifa->ifa_addr;
|
||||
if ((addr->sa_family == AF_PACKET && ifltr->af_packet)
|
||||
|| (addr->sa_family == AF_INET && ifltr->af_inet)
|
||||
|| (addr->sa_family == AF_INET6 && ifltr->af_inet6 &&
|
||||
!IN6_IS_ADDR_UNSPECIFIED(
|
||||
&((struct sockaddr_in6 *)addr)->sin6_addr)))
|
||||
{
|
||||
err = copy_ifaddrs(&ifa_next, sys_ifa);
|
||||
if (err == 0) {
|
||||
if (ifa == NULL) {
|
||||
ifa = ifa_root = ifa_next;
|
||||
} else {
|
||||
ifa->next = ifa_next;
|
||||
ifa = ifa_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(sys_ifa_root);
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa_root;
|
||||
} else {
|
||||
os_freeifaddrs(ifa_root);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
|
@ -230,98 +230,3 @@ os_sockSelect(
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
_Check_return_
|
||||
static os_result
|
||||
os_queryInterfaceAttributesIPv4 (_In_ const struct ifaddrs *ifa, _Inout_ os_ifAttributes *ifElement)
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
strncpy (ifElement->name, ifa->ifa_name, OS_IFNAMESIZE);
|
||||
ifElement->name[OS_IFNAMESIZE - 1] = '\0';
|
||||
memcpy (&ifElement->address, ifa->ifa_addr, sizeof (os_sockaddr_in));
|
||||
ifElement->flags = ifa->ifa_flags;
|
||||
if (ifElement->flags & IFF_BROADCAST)
|
||||
memcpy (&ifElement->broadcast_address, ifa->ifa_broadaddr, sizeof (os_sockaddr_in));
|
||||
else
|
||||
memset (&ifElement->broadcast_address, 0, sizeof (ifElement->broadcast_address));
|
||||
memcpy (&ifElement->network_mask, ifa->ifa_netmask, sizeof (os_sockaddr_in));
|
||||
ifElement->interfaceIndexNo = (unsigned) if_nametoindex (ifa->ifa_name);
|
||||
return result;
|
||||
}
|
||||
|
||||
_Check_return_
|
||||
static os_result
|
||||
os_queryInterfaceAttributesIPv6 (_In_ const struct ifaddrs *ifa, _Inout_ os_ifAttributes *ifElement)
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
strncpy (ifElement->name, ifa->ifa_name, OS_IFNAMESIZE);
|
||||
ifElement->name[OS_IFNAMESIZE - 1] = '\0';
|
||||
memcpy (&ifElement->address, ifa->ifa_addr, sizeof (os_sockaddr_in6));
|
||||
ifElement->flags = ifa->ifa_flags;
|
||||
memset (&ifElement->broadcast_address, 0, sizeof (ifElement->broadcast_address));
|
||||
memset (&ifElement->network_mask, 0, sizeof (ifElement->network_mask));
|
||||
ifElement->interfaceIndexNo = (unsigned) if_nametoindex (ifa->ifa_name);
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result os_sockQueryInterfaces (os_ifAttributes *ifList, uint32_t listSize, uint32_t *validElements)
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
unsigned int listIndex;
|
||||
struct ifaddrs *ifa_first, *ifa;
|
||||
if (getifaddrs (&ifa_first) != 0)
|
||||
{
|
||||
perror ("getifaddrs");
|
||||
return os_resultFail;
|
||||
}
|
||||
listIndex = 0;
|
||||
for (ifa = ifa_first; ifa && listIndex < listSize; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (ifa->ifa_addr && ((struct sockaddr_in *) ifa->ifa_addr)->sin_family == AF_INET)
|
||||
{
|
||||
/* Get other interface attributes */
|
||||
result = os_queryInterfaceAttributesIPv4 (ifa, &ifList[listIndex]);
|
||||
if (result == os_resultSuccess)
|
||||
listIndex++;
|
||||
}
|
||||
|
||||
if (result == os_resultSuccess)
|
||||
*validElements = listIndex;
|
||||
}
|
||||
freeifaddrs (ifa_first);
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result os_sockQueryIPv6Interfaces (os_ifAttributes *ifList, uint32_t listSize, uint32_t *validElements)
|
||||
{
|
||||
struct ifaddrs* interfaceList = NULL;
|
||||
struct ifaddrs* nextInterface = NULL;
|
||||
unsigned int listIndex = 0;
|
||||
|
||||
*validElements = 0;
|
||||
if (getifaddrs (&interfaceList) != 0)
|
||||
{
|
||||
return os_resultFail;
|
||||
}
|
||||
|
||||
nextInterface = interfaceList;
|
||||
while (nextInterface != NULL && listIndex < listSize)
|
||||
{
|
||||
if (nextInterface->ifa_addr && nextInterface->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
os_sockaddr_in6 *v6Address = (os_sockaddr_in6 *) nextInterface->ifa_addr;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&v6Address->sin6_addr))
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
result = os_queryInterfaceAttributesIPv6 (nextInterface, &ifList[listIndex]);
|
||||
if (result == os_resultSuccess)
|
||||
listIndex++;
|
||||
}
|
||||
}
|
||||
nextInterface = nextInterface->ifa_next;
|
||||
}
|
||||
*validElements = listIndex;
|
||||
freeifaddrs(interfaceList);
|
||||
return os_resultSuccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "os_stdlib_strsep.c"
|
||||
#include "os_stdlib_memdup.c"
|
||||
#include "os_stdlib_rindex.c"
|
||||
#include "os_stdlib_asprintf.c"
|
||||
#include "os_stdlib_strcasecmp.c"
|
||||
#include "os_stdlib_strncasecmp.c"
|
||||
#include "os_stdlib_strdup.c"
|
||||
|
|
48
src/os/src/snippets/code/os_stdlib_asprintf.c
Normal file
48
src/os/src/snippets/code/os_stdlib_asprintf.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "os/os.h"
|
||||
|
||||
int
|
||||
os_asprintf(
|
||||
char **strp,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
int ret;
|
||||
unsigned int len;
|
||||
char buf[1] = { '\0' };
|
||||
char *str = NULL;
|
||||
va_list args1, args2;
|
||||
|
||||
assert(strp != NULL);
|
||||
assert(fmt != NULL);
|
||||
|
||||
va_start(args1, fmt);
|
||||
va_copy(args2, args1); /* va_list cannot be reused */
|
||||
|
||||
if ((ret = os_vsnprintf(buf, sizeof(buf), fmt, args1)) >= 0) {
|
||||
len = (unsigned int)ret; /* +1 for null byte */
|
||||
if ((str = os_malloc(len + 1)) == NULL) {
|
||||
ret = -1;
|
||||
} else if ((ret = os_vsnprintf(str, len + 1, fmt, args2)) >= 0) {
|
||||
assert(((unsigned int)ret) == len);
|
||||
*strp = str;
|
||||
} else {
|
||||
os_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args1);
|
||||
va_end(args2);
|
||||
|
||||
return ret;
|
||||
}
|
24
src/os/src/snippets/code/os_stdlib_memdup.c
Normal file
24
src/os/src/snippets/code/os_stdlib_memdup.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "os/os.h"
|
||||
|
||||
void *
|
||||
os_memdup(void *src, size_t n)
|
||||
{
|
||||
void *dest;
|
||||
|
||||
if ((dest = os_malloc_s(n)) != NULL) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
260
src/os/src/windows/os_platform_ifaddrs.c
Normal file
260
src/os/src/windows/os_platform_ifaddrs.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
static int
|
||||
getifaces(PIP_ADAPTER_ADDRESSES *ptr)
|
||||
{
|
||||
int err = ERANGE;
|
||||
PIP_ADAPTER_ADDRESSES buf = NULL;
|
||||
ULONG bufsz = 0; /* Size is determined on first iteration. */
|
||||
ULONG ret;
|
||||
size_t i;
|
||||
|
||||
static const size_t max = 3;
|
||||
static const ULONG filter = GAA_FLAG_INCLUDE_PREFIX |
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
for (i = 0; err == ERANGE && i < max; i++) {
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, filter, NULL, buf, &bufsz);
|
||||
assert(ret != ERROR_INVALID_PARAMETER);
|
||||
switch (ret) {
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
err = ERANGE;
|
||||
os_free(buf);
|
||||
if ((buf = (IP_ADAPTER_ADDRESSES *)os_malloc(bufsz)) == NULL) {
|
||||
err = ENOMEM;
|
||||
}
|
||||
break;
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
err = ENOMEM;
|
||||
break;
|
||||
case ERROR_SUCCESS:
|
||||
case ERROR_ADDRESS_NOT_ASSOCIATED: /* No address associated yet. */
|
||||
case ERROR_NO_DATA: /* No adapters that match the filter. */
|
||||
default:
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ptr = buf;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
getaddrtable(PMIB_IPADDRTABLE *ptr)
|
||||
{
|
||||
int err = ERANGE;
|
||||
PMIB_IPADDRTABLE buf = NULL;
|
||||
ULONG bufsz = 0;
|
||||
DWORD ret;
|
||||
size_t i;
|
||||
|
||||
static const size_t max = 2;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
for (i = 0; err == ERANGE && i < max; i++) {
|
||||
ret = GetIpAddrTable(buf, &bufsz, 0);
|
||||
assert(ret != ERROR_INVALID_PARAMETER &&
|
||||
ret != ERROR_NOT_SUPPORTED);
|
||||
switch (ret) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
err = ERANGE;
|
||||
os_free(buf);
|
||||
if ((buf = (PMIB_IPADDRTABLE)os_malloc(bufsz)) == NULL) {
|
||||
err = ENOMEM;
|
||||
}
|
||||
break;
|
||||
case ERROR_SUCCESS:
|
||||
default:
|
||||
err = GetLastError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ptr = buf;
|
||||
} else {
|
||||
os_free(buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
getflags(const PIP_ADAPTER_ADDRESSES iface)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (iface->OperStatus == IfOperStatusUp) {
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
if (iface->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
|
||||
flags |= IFF_LOOPBACK;
|
||||
}
|
||||
if (!(iface->Flags & IP_ADAPTER_NO_MULTICAST)) {
|
||||
flags |= IFF_MULTICAST;
|
||||
}
|
||||
|
||||
/* FIXME: Shouldn't IFF_LOOPBACK be included here? */
|
||||
switch (iface->IfType) {
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
case IF_TYPE_IEEE80211:
|
||||
case IF_TYPE_IEEE1394:
|
||||
case IF_TYPE_ISO88025_TOKENRING:
|
||||
flags |= IFF_BROADCAST;
|
||||
break;
|
||||
default:
|
||||
flags |= IFF_POINTTOPOINT;
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int
|
||||
copyaddr(
|
||||
os_ifaddrs_t **ifap,
|
||||
const PIP_ADAPTER_ADDRESSES iface,
|
||||
const PMIB_IPADDRTABLE addrtable,
|
||||
const PIP_ADAPTER_UNICAST_ADDRESS addr)
|
||||
{
|
||||
int err = 0;
|
||||
int eq = 0;
|
||||
os_ifaddrs_t *ifa;
|
||||
DWORD i;
|
||||
struct sockaddr *sa = (struct sockaddr *)addr->Address.lpSockaddr;
|
||||
size_t size;
|
||||
|
||||
assert(iface != NULL);
|
||||
assert(addrtable != NULL);
|
||||
assert(addr != NULL);
|
||||
|
||||
if ((ifa = os_calloc_s(1, sizeof(*ifa))) == NULL) {
|
||||
err = ENOMEM;
|
||||
} else {
|
||||
ifa->flags = getflags(iface);
|
||||
(void)os_asprintf(&ifa->name, "%wS", iface->FriendlyName);
|
||||
|
||||
if (ifa->name == NULL) {
|
||||
err = ENOMEM;
|
||||
} else if (ifa->flags & IFF_UP) {
|
||||
ifa->addr = os_memdup(sa, addr->Address.iSockaddrLength);
|
||||
if (ifa->addr == NULL) {
|
||||
err = ENOMEM;
|
||||
} else if (ifa->addr->sa_family == AF_INET) {
|
||||
size = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in netmask, broadaddr;
|
||||
|
||||
memset(&netmask, 0, size);
|
||||
memset(&broadaddr, 0, size);
|
||||
netmask.sin_family = broadaddr.sin_family = AF_INET;
|
||||
|
||||
for (i = 0; !eq && i < addrtable->dwNumEntries; i++) {
|
||||
eq = (((struct sockaddr_in *)sa)->sin_addr.s_addr ==
|
||||
addrtable->table[i].dwAddr);
|
||||
if (eq) {
|
||||
ifa->index = addrtable->table[i].dwIndex;
|
||||
netmask.sin_addr.s_addr = addrtable->table[i].dwMask;
|
||||
broadaddr.sin_addr.s_addr =
|
||||
((struct sockaddr_in *)sa)->sin_addr.s_addr | ~(netmask.sin_addr.s_addr);
|
||||
}
|
||||
}
|
||||
|
||||
assert(eq != 0);
|
||||
|
||||
if ((ifa->netmask = os_memdup(&netmask, size)) == NULL ||
|
||||
(ifa->broadaddr = os_memdup(&broadaddr, size)) == NULL)
|
||||
{
|
||||
err = ENOMEM;
|
||||
}
|
||||
} else {
|
||||
ifa->index = iface->Ipv6IfIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
os_free(ifa);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
_Success_(return == 0) int
|
||||
os_getifaddrs(
|
||||
_Inout_ os_ifaddrs_t **ifap,
|
||||
_In_opt_ const os_ifaddr_filter_t *ifltr)
|
||||
{
|
||||
int err = 0;
|
||||
PIP_ADAPTER_ADDRESSES ifaces = NULL, iface;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS addr = NULL;
|
||||
PMIB_IPADDRTABLE addrtable = NULL;
|
||||
os_ifaddrs_t *ifa, *ifa_root, *ifa_next;
|
||||
struct sockaddr *sa;
|
||||
|
||||
assert(ifap != NULL);
|
||||
assert(ifltr != NULL);
|
||||
|
||||
ifa = ifa_root = ifa_next = NULL;
|
||||
|
||||
if ((err = getifaces(&ifaces)) == 0 &&
|
||||
(err = getaddrtable(&addrtable)) == 0)
|
||||
{
|
||||
for (iface = ifaces; !err && iface != NULL; iface = iface->Next) {
|
||||
for (addr = iface->FirstUnicastAddress;
|
||||
addr != NULL;
|
||||
addr = addr->Next)
|
||||
{
|
||||
sa = (struct sockaddr *)addr->Address.lpSockaddr;
|
||||
if ((sa->sa_family == AF_INET && ifltr->af_inet) ||
|
||||
(sa->sa_family == AF_INET6 && ifltr->af_inet6))
|
||||
{
|
||||
err = copyaddr(&ifa_next, iface, addrtable, addr);
|
||||
if (err == 0) {
|
||||
if (ifa == NULL) {
|
||||
ifa = ifa_root = ifa_next;
|
||||
} else {
|
||||
ifa->next = ifa_next;
|
||||
ifa = ifa_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os_free(ifaces);
|
||||
os_free(addrtable);
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa_root;
|
||||
} else {
|
||||
os_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
|
@ -558,341 +558,3 @@ os__sockSelect(
|
|||
return r;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
getInterfaceFlags(PIP_ADAPTER_ADDRESSES pAddr)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (pAddr->OperStatus == IfOperStatusUp) {
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
|
||||
if (pAddr->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
|
||||
flags |= IFF_LOOPBACK;
|
||||
}
|
||||
|
||||
if (!(pAddr->Flags & IP_ADAPTER_NO_MULTICAST)) {
|
||||
flags |= IFF_MULTICAST;
|
||||
}
|
||||
|
||||
switch (pAddr->IfType) {
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
case IF_TYPE_IEEE80211:
|
||||
case IF_TYPE_IEEE1394:
|
||||
case IF_TYPE_ISO88025_TOKENRING:
|
||||
flags |= IFF_BROADCAST;
|
||||
break;
|
||||
default:
|
||||
flags |= IFF_POINTTOPOINT;
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static os_result
|
||||
addressToIndexAndMask(struct sockaddr *addr, unsigned int *ifIndex, struct sockaddr *mask )
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
bool found = FALSE;
|
||||
PMIB_IPADDRTABLE pIPAddrTable = NULL;
|
||||
DWORD dwSize = 0;
|
||||
DWORD i;
|
||||
int errNo;
|
||||
|
||||
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
|
||||
pIPAddrTable = (MIB_IPADDRTABLE *) os_malloc(dwSize);
|
||||
if (pIPAddrTable != NULL) {
|
||||
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) != NO_ERROR) {
|
||||
errNo = os_getErrno();
|
||||
OS_ERROR("addressToIndexAndMask", 0, "GetIpAddrTable failed: %d", errNo);
|
||||
result = os_resultFail;
|
||||
}
|
||||
} else {
|
||||
OS_ERROR("addressToIndexAndMask", 0, "Failed to allocate %lu bytes for IP address table", dwSize);
|
||||
result = os_resultFail;
|
||||
}
|
||||
} else {
|
||||
errNo = os_getErrno();
|
||||
OS_ERROR("addressToIndexAndMask", 0, "GetIpAddrTable failed: %d", errNo);
|
||||
result = os_resultFail;
|
||||
}
|
||||
|
||||
if (result == os_resultSuccess) {
|
||||
for (i = 0; !found && i < pIPAddrTable->dwNumEntries; i++ ) {
|
||||
if (((struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr) {
|
||||
*ifIndex = pIPAddrTable->table[i].dwIndex;
|
||||
((struct sockaddr_in*) mask)->sin_addr.s_addr= pIPAddrTable->table[i].dwMask;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pIPAddrTable) {
|
||||
os_free(pIPAddrTable);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
result = os_resultFail;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define MAX_INTERFACES 64
|
||||
#define INTF_MAX_NAME_LEN 16
|
||||
|
||||
os_result
|
||||
os_sockQueryInterfaces(
|
||||
os_ifAttributes *ifList,
|
||||
unsigned int listSize,
|
||||
unsigned int *validElements)
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
DWORD filter;
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
PIP_ADAPTER_ADDRESSES pCurrAddress = NULL;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
|
||||
unsigned long outBufLen = WORKING_BUFFER_SIZE;
|
||||
int retVal;
|
||||
int iterations = 0;
|
||||
int listIndex = 0;
|
||||
|
||||
filter = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
do {
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen);
|
||||
if (!pAddresses) {
|
||||
OS_ERROR("os_sockQueryInterfaces", 0, "Failed to allocate %lu bytes for Adapter addresses", outBufLen);
|
||||
return os_resultFail;
|
||||
}
|
||||
retVal = GetAdaptersAddresses(AF_INET, filter, NULL, pAddresses, &outBufLen);
|
||||
if (retVal == ERROR_BUFFER_OVERFLOW) {
|
||||
os_free(pAddresses);
|
||||
pAddresses = NULL;
|
||||
outBufLen <<= 1; /* double the buffer just to be save.*/
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
iterations++;
|
||||
} while ((retVal == ERROR_BUFFER_OVERFLOW) && (iterations < MAX_TRIES));
|
||||
|
||||
if (retVal != ERROR_SUCCESS) {
|
||||
if (pAddresses) {
|
||||
os_free(pAddresses);
|
||||
pAddresses = NULL;
|
||||
}
|
||||
OS_ERROR("os_sockQueryInterfaces", 0, "Failed to GetAdaptersAddresses");
|
||||
return os_resultFail;
|
||||
}
|
||||
|
||||
for (pCurrAddress = pAddresses; pCurrAddress; pCurrAddress = pCurrAddress->Next) {
|
||||
IP_ADAPTER_PREFIX *firstPrefix = NULL;
|
||||
|
||||
if (pCurrAddress->Length >= sizeof(IP_ADAPTER_ADDRESSES)) {
|
||||
firstPrefix = pCurrAddress->FirstPrefix;
|
||||
}
|
||||
|
||||
if (pCurrAddress->OperStatus != IfOperStatusUp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (pUnicast = pCurrAddress->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
|
||||
unsigned int ipv4Index;
|
||||
struct sockaddr_in ipv4Netmask;
|
||||
|
||||
if (pUnicast->Address.lpSockaddr->sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ipv4Index = 0;
|
||||
memset(&ipv4Netmask, 0, sizeof(ipv4Netmask));
|
||||
if (addressToIndexAndMask((struct sockaddr *) pUnicast->Address.lpSockaddr,
|
||||
&ipv4Index, (struct sockaddr *) &ipv4Netmask) != os_resultSuccess) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddress->FriendlyName);
|
||||
|
||||
/* Get interface flags. */
|
||||
ifList[listIndex].flags = getInterfaceFlags(pCurrAddress);
|
||||
ifList[listIndex].interfaceIndexNo = ipv4Index;
|
||||
|
||||
memcpy(&ifList[listIndex].address, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
memcpy(&ifList[listIndex].broadcast_address, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
memcpy(&ifList[listIndex].network_mask, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
|
||||
((struct sockaddr_in *)(&(ifList[listIndex].broadcast_address)))->sin_addr.s_addr =
|
||||
((struct sockaddr_in *)(&(ifList[listIndex].address)))->sin_addr.s_addr | ~(ipv4Netmask.sin_addr.s_addr);
|
||||
((struct sockaddr_in *)&(ifList[listIndex].network_mask))->sin_addr.s_addr = ipv4Netmask.sin_addr.s_addr;
|
||||
|
||||
listIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
for (pCurrAddress = pAddresses; pCurrAddress; pCurrAddress = pCurrAddress->Next) {
|
||||
if (pCurrAddress->OperStatus != IfOperStatusUp) {
|
||||
(void)snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddress->FriendlyName);
|
||||
|
||||
/* Get interface flags. */
|
||||
ifList[listIndex].flags = getInterfaceFlags(pCurrAddress);
|
||||
ifList[listIndex].interfaceIndexNo = 0;
|
||||
memset (&ifList[listIndex].address, 0, sizeof(ifList[listIndex].address));
|
||||
memset (&ifList[listIndex].broadcast_address, 0, sizeof (ifList[listIndex].broadcast_address));
|
||||
memset (&ifList[listIndex].network_mask, 0, sizeof (ifList[listIndex].network_mask));
|
||||
|
||||
listIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAddresses) {
|
||||
os_free(pAddresses);
|
||||
}
|
||||
|
||||
*validElements = listIndex;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result
|
||||
os_sockQueryIPv6Interfaces (
|
||||
os_ifAttributes *ifList,
|
||||
unsigned int listSize,
|
||||
unsigned int *validElements)
|
||||
{
|
||||
os_result result = os_resultSuccess;
|
||||
ULONG filter;
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
PIP_ADAPTER_ADDRESSES pCurrAddress = NULL;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
|
||||
ULONG outBufLen = WORKING_BUFFER_SIZE;
|
||||
ULONG retVal;
|
||||
int iterations = 0;
|
||||
int listIndex = 0;
|
||||
|
||||
filter = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
do {
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen);
|
||||
if (!pAddresses) {
|
||||
OS_ERROR("os_sockQueryIPv6Interfaces", 0, "Failed to allocate %lu bytes for Adapter addresses", outBufLen);
|
||||
return os_resultFail;
|
||||
}
|
||||
retVal = GetAdaptersAddresses(AF_INET6, filter, NULL, pAddresses, &outBufLen);
|
||||
if (retVal == ERROR_BUFFER_OVERFLOW) {
|
||||
os_free(pAddresses);
|
||||
pAddresses = NULL;
|
||||
outBufLen <<= 1; /* double the buffer just to be save.*/
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
iterations++;
|
||||
} while ((retVal == ERROR_BUFFER_OVERFLOW) && (iterations < MAX_TRIES));
|
||||
|
||||
if (retVal != ERROR_SUCCESS) {
|
||||
if (pAddresses) {
|
||||
os_free(pAddresses);
|
||||
pAddresses = NULL;
|
||||
}
|
||||
OS_ERROR("os_sockQueryIPv6Interfaces", 0, "Failed to GetAdaptersAddresses");
|
||||
return os_resultFail;
|
||||
}
|
||||
|
||||
for (pCurrAddress = pAddresses; pCurrAddress; pCurrAddress = pCurrAddress->Next) {
|
||||
DWORD ipv6IfIndex = 0;
|
||||
IP_ADAPTER_PREFIX *firstPrefix = NULL;
|
||||
|
||||
if (pCurrAddress->Length >= sizeof(IP_ADAPTER_ADDRESSES)) {
|
||||
ipv6IfIndex = pCurrAddress->Ipv6IfIndex;
|
||||
firstPrefix = pCurrAddress->FirstPrefix;
|
||||
}
|
||||
|
||||
if (((ipv6IfIndex == 1) && (pCurrAddress->IfType != IF_TYPE_SOFTWARE_LOOPBACK)) || (pCurrAddress->IfType == IF_TYPE_TUNNEL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pCurrAddress->OperStatus != IfOperStatusUp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (pUnicast = pCurrAddress->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
|
||||
IP_ADAPTER_PREFIX *prefix;
|
||||
IN6_ADDR mask;
|
||||
struct sockaddr_in6 *sa6;
|
||||
struct sockaddr_in6 ipv6Netmask;
|
||||
|
||||
if (pUnicast->Address.lpSockaddr->sa_family != AF_INET6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddress->FriendlyName);
|
||||
|
||||
/* Get interface flags. */
|
||||
ifList[listIndex].flags = getInterfaceFlags(pCurrAddress);
|
||||
ifList[listIndex].interfaceIndexNo = (uint32_t) pCurrAddress->Ipv6IfIndex;
|
||||
|
||||
memcpy(&ifList[listIndex].address, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
memcpy(&ifList[listIndex].broadcast_address, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
memcpy(&ifList[listIndex].network_mask, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
|
||||
|
||||
sa6 = (struct sockaddr_in6 *)&ifList[listIndex].network_mask;
|
||||
memset(&sa6->sin6_addr.s6_addr, 0xFF, sizeof(sa6->sin6_addr.s6_addr));
|
||||
|
||||
for (prefix = firstPrefix; prefix; prefix = prefix->Next) {
|
||||
unsigned int l, i;
|
||||
if ((prefix->PrefixLength == 0) || (prefix->PrefixLength > 128) ||
|
||||
(pUnicast->Address.iSockaddrLength != prefix->Address.iSockaddrLength) ||
|
||||
(memcmp(pUnicast->Address.lpSockaddr, prefix->Address.lpSockaddr, pUnicast->Address.iSockaddrLength) == 0)){
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&ipv6Netmask, 0, sizeof(ipv6Netmask));
|
||||
ipv6Netmask.sin6_family = AF_INET6;
|
||||
|
||||
l = prefix->PrefixLength;
|
||||
for (i = 0; l > 0; l -= 8, i++) {
|
||||
ipv6Netmask.sin6_addr.s6_addr[i] = (l >= 8) ? 0xFF : ((0xFF << (8-l)) & 0xFF);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
mask.s6_addr[i] =
|
||||
((struct sockaddr_in6 *)pUnicast->Address.lpSockaddr)->sin6_addr.s6_addr[i] & ipv6Netmask.sin6_addr.s6_addr[i];
|
||||
}
|
||||
|
||||
if (memcmp(((struct sockaddr_in6 *)prefix->Address.lpSockaddr)->sin6_addr.s6_addr,
|
||||
mask.s6_addr, sizeof(ipv6Netmask.sin6_addr)) == 0) {
|
||||
memcpy(&sa6->sin6_addr.s6_addr, &ipv6Netmask.sin6_addr.s6_addr, sizeof(sa6->sin6_addr.s6_addr));
|
||||
}
|
||||
}
|
||||
listIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
for (pCurrAddress = pAddresses; pCurrAddress; pCurrAddress = pCurrAddress->Next) {
|
||||
if (pCurrAddress->OperStatus != IfOperStatusUp) {
|
||||
(void) snprintf(ifList[listIndex].name, OS_IFNAMESIZE, "%wS", pCurrAddress->FriendlyName);
|
||||
|
||||
/* Get interface flags. */
|
||||
ifList[listIndex].flags = getInterfaceFlags(pCurrAddress);
|
||||
ifList[listIndex].interfaceIndexNo = 0;
|
||||
memset (&ifList[listIndex].address, 0, sizeof(ifList[listIndex].address));
|
||||
memset (&ifList[listIndex].broadcast_address, 0, sizeof (ifList[listIndex].broadcast_address));
|
||||
memset (&ifList[listIndex].network_mask, 0, sizeof (ifList[listIndex].network_mask));
|
||||
|
||||
listIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAddresses) {
|
||||
os_free(pAddresses);
|
||||
}
|
||||
|
||||
*validElements = listIndex;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#undef MAX_INTERFACES
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "../snippets/code/os_stdlib_strtok_r.c"
|
||||
#include "../snippets/code/os_stdlib_strsep.c"
|
||||
#include "../snippets/code/os_stdlib_strdup.c"
|
||||
#include "../snippets/code/os_stdlib_memdup.c"
|
||||
#include "../snippets/code/os_stdlib_asprintf.c"
|
||||
#include "../snippets/code/os_stdlib_rindex.c"
|
||||
#include "../snippets/code/os_stdlib_strcasecmp.c"
|
||||
#include "../snippets/code/os_stdlib_strncasecmp.c"
|
||||
|
|
83
src/os/tests/ifaddrs.c
Normal file
83
src/os/tests/ifaddrs.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Runner.h"
|
||||
#include "os/os.h"
|
||||
|
||||
/* FIXME: It's not possible to predict what network interfaces are available
|
||||
on a given host. To properly test all combinations the abstracted
|
||||
operating system functions must be mocked. */
|
||||
|
||||
CUnit_Suite_Initialize(os_getifaddrs)
|
||||
{
|
||||
os_osInit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CUnit_Suite_Cleanup(os_getifaddrs)
|
||||
{
|
||||
os_osExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume every test machine has at least one non-loopback IPv4 address. This
|
||||
simple test verifies an interface can at least be found and that the
|
||||
IFF_LOOPBACK flags are properly set. */
|
||||
CUnit_Test(os_getifaddrs, ipv4)
|
||||
{
|
||||
int err;
|
||||
int seen = 0;
|
||||
os_ifaddrs_t *ifa_root, *ifa;
|
||||
os_ifaddr_filter_t ifltr = { .af_inet = 1 };
|
||||
|
||||
err = os_getifaddrs(&ifa_root, &ifltr);
|
||||
CU_ASSERT_EQUAL_FATAL(err, 0);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET);
|
||||
if (ifa->addr->sa_family == AF_INET) {
|
||||
if (ifa->flags & IFF_LOOPBACK) {
|
||||
CU_ASSERT(os_sockaddrIsLoopback(ifa->addr));
|
||||
} else {
|
||||
CU_ASSERT(!os_sockaddrIsLoopback(ifa->addr));
|
||||
}
|
||||
seen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(seen, 1);
|
||||
|
||||
os_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
#ifdef OS_SOCKET_HAS_IPV6
|
||||
CUnit_Test(os_getifaddrs, non_local_ipv6)
|
||||
{
|
||||
int err;
|
||||
os_ifaddrs_t *ifa_root, *ifa;
|
||||
os_ifaddr_filter_t ifltr = { .af_inet6 = 1 };
|
||||
|
||||
err = os_getifaddrs(&ifa_root, &ifltr);
|
||||
CU_ASSERT_EQUAL_FATAL(err, 0);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET6);
|
||||
if (ifa->addr->sa_family == AF_INET6) {
|
||||
if (ifa->flags & IFF_LOOPBACK) {
|
||||
CU_ASSERT(os_sockaddrIsLoopback(ifa->addr));
|
||||
} else {
|
||||
CU_ASSERT(!os_sockaddrIsLoopback(ifa->addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os_freeifaddrs(ifa_root);
|
||||
}
|
||||
#endif /* OS_SOCKET_HAS_IPV6 */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue