From 2fc4cac1a7f70438b21905a4bd4be86f4d9bfe45 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 19 Sep 2018 18:40:19 +0200 Subject: [PATCH 01/15] Consolidate some duplicate functions Signed-off-by: Jeroen Koekkoek --- src/os/src/snippets/code/os_stdlib.c | 79 +-------------- src/os/src/snippets/code/os_stdlib_rindex.c | 28 ++++++ .../src/snippets/code/os_stdlib_strcasecmp.c | 32 ++++++ src/os/src/snippets/code/os_stdlib_strdup.c | 28 ++++++ .../src/snippets/code/os_stdlib_strncasecmp.c | 35 +++++++ src/os/src/windows/os_platform_stdlib.c | 98 +------------------ 6 files changed, 132 insertions(+), 168 deletions(-) create mode 100644 src/os/src/snippets/code/os_stdlib_rindex.c create mode 100644 src/os/src/snippets/code/os_stdlib_strcasecmp.c create mode 100644 src/os/src/snippets/code/os_stdlib_strdup.c create mode 100644 src/os/src/snippets/code/os_stdlib_strncasecmp.c diff --git a/src/os/src/snippets/code/os_stdlib.c b/src/os/src/snippets/code/os_stdlib.c index f8a89e2..a79b40e 100644 --- a/src/os/src/snippets/code/os_stdlib.c +++ b/src/os/src/snippets/code/os_stdlib.c @@ -21,8 +21,11 @@ #include #include - #include "os_stdlib_strsep.c" +#include "os_stdlib_rindex.c" +#include "os_stdlib_strcasecmp.c" +#include "os_stdlib_strncasecmp.c" +#include "os_stdlib_strdup.c" _Ret_opt_z_ const char * os_getenv( @@ -79,38 +82,6 @@ os_access( return result; } -char * -os_rindex( - const char *s, - int c) -{ - char *last = NULL; - - while (*s) { - if (*s == c) { - last = (char *)s; - } - s++; - } - return last; -} - -_Ret_z_ -_Check_return_ -char * -os_strdup( - _In_z_ const char *s1) -{ - size_t len; - char *dup; - - len = strlen(s1) + 1; - dup = os_malloc(len); - memcpy(dup, s1, len); - - return dup; -} - int os_vsnprintf( char *str, @@ -157,48 +128,6 @@ os_vfprintfnosigpipe( return result; } -int -os_strcasecmp( - const char *s1, - const char *s2) -{ - int cr; - - while (*s1 && *s2) { - cr = tolower(*s1) - tolower(*s2); - if (cr) { - return cr; - } - s1++; - s2++; - } - cr = tolower(*s1) - tolower(*s2); - return cr; -} - -int -os_strncasecmp( - const char *s1, - const char *s2, - size_t n) -{ - int cr = 0; - - while (*s1 && *s2 && n) { - cr = tolower(*s1) - tolower(*s2); - if (cr) { - return cr; - } - s1++; - s2++; - n--; - } - if (n) { - cr = tolower(*s1) - tolower(*s2); - } - return cr; -} - os_result os_stat( const char *path, diff --git a/src/os/src/snippets/code/os_stdlib_rindex.c b/src/os/src/snippets/code/os_stdlib_rindex.c new file mode 100644 index 0000000..a1a8f1a --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_rindex.c @@ -0,0 +1,28 @@ +/* + * 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 + +char * +os_rindex( + const char *s, + int c) +{ + char *last = NULL; + + while (*s) { + if (*s == c) { + last = (char *)s; + } + s++; + } + return last; +} diff --git a/src/os/src/snippets/code/os_stdlib_strcasecmp.c b/src/os/src/snippets/code/os_stdlib_strcasecmp.c new file mode 100644 index 0000000..ae1e250 --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_strcasecmp.c @@ -0,0 +1,32 @@ +/* + * 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" + +#pragma warning( default : 4996 ) +int +os_strcasecmp( + const char *s1, + const char *s2) +{ + int cr; + + while (*s1 && *s2) { + cr = tolower(*s1) - tolower(*s2); + if (cr) { + return cr; + } + s1++; + s2++; + } + cr = tolower(*s1) - tolower(*s2); + return cr; +} diff --git a/src/os/src/snippets/code/os_stdlib_strdup.c b/src/os/src/snippets/code/os_stdlib_strdup.c new file mode 100644 index 0000000..3acc6d8 --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_strdup.c @@ -0,0 +1,28 @@ +/* + * 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" + +_Ret_z_ +_Check_return_ +char * +os_strdup( + _In_z_ const char *s1) +{ + size_t len; + char *dup; + + len = strlen(s1) + 1; + dup = os_malloc(len); + memcpy(dup, s1, len); + + return dup; +} diff --git a/src/os/src/snippets/code/os_stdlib_strncasecmp.c b/src/os/src/snippets/code/os_stdlib_strncasecmp.c new file mode 100644 index 0000000..753042d --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_strncasecmp.c @@ -0,0 +1,35 @@ +/* + * 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_strncasecmp( + const char *s1, + const char *s2, + size_t n) +{ + int cr = 0; + + while (*s1 && *s2 && n) { + cr = tolower(*s1) - tolower(*s2); + if (cr) { + return cr; + } + s1++; + s2++; + n--; + } + if (n) { + cr = tolower(*s1) - tolower(*s2); + } + return cr; +} diff --git a/src/os/src/windows/os_platform_stdlib.c b/src/os/src/windows/os_platform_stdlib.c index 6b05cab..27f2acb 100644 --- a/src/os/src/windows/os_platform_stdlib.c +++ b/src/os/src/windows/os_platform_stdlib.c @@ -18,7 +18,11 @@ #include "../snippets/code/os_stdlib_strtod.c" #include "../snippets/code/os_stdlib_strtol.c" #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_rindex.c" +#include "../snippets/code/os_stdlib_strcasecmp.c" +#include "../snippets/code/os_stdlib_strncasecmp.c" static int32_t os__ensurePathExists( @@ -140,55 +144,6 @@ os_access( return result; } -char * -os_rindex( - const char *s, - int c) -{ - char *last = NULL; - - while (*s) { - if (*s == c) { - last = (char *)s; - } - s++; - } - return last; -} - -_Ret_z_ -_Check_return_ -char * -os_strdup( - _In_z_ const char *s1) -{ - size_t len; - char *dup; - - len = strlen(s1) + 1; - dup = os_malloc(len); - memcpy(dup, s1, len); - - return dup; -} - -char * -os_strsep(char **str, const char *sep) -{ - char *ret; - if (**str == '\0') - return 0; - ret = *str; - while (**str && strchr(sep, **str) == 0) - (*str)++; - if (**str != '\0') - { - **str = '\0'; - (*str)++; - } - return ret; -} - #pragma warning( disable : 4996 ) int os_vfprintfnosigpipe( @@ -199,49 +154,6 @@ os_vfprintfnosigpipe( return vfprintf(file, format, args); } -#pragma warning( default : 4996 ) -int -os_strcasecmp( - const char *s1, - const char *s2) -{ - int cr; - - while (*s1 && *s2) { - cr = tolower(*s1) - tolower(*s2); - if (cr) { - return cr; - } - s1++; - s2++; - } - cr = tolower(*s1) - tolower(*s2); - return cr; -} - -int -os_strncasecmp( - const char *s1, - const char *s2, - size_t n) -{ - int cr = 0; - - while (*s1 && *s2 && n) { - cr = tolower(*s1) - tolower(*s2); - if (cr) { - return cr; - } - s1++; - s2++; - n--; - } - if (n) { - cr = tolower(*s1) - tolower(*s2); - } - return cr; -} - os_result os_stat( const char *path, From 458b1df3f780a48bf07f3a84ca87ea637834ac4b Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 19 Sep 2018 19:25:58 +0200 Subject: [PATCH 02/15] Replace os_sockQueryInterfaces by os_getifaddrs Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/include/ddsi/ddsi_ipaddr.h | 2 +- src/core/ddsi/include/ddsi/ddsi_tran.h | 4 +- src/core/ddsi/src/ddsi_ipaddr.c | 8 +- src/core/ddsi/src/ddsi_raweth.c | 45 +-- src/core/ddsi/src/ddsi_tcp.c | 8 +- src/core/ddsi/src/ddsi_tran.c | 4 +- src/core/ddsi/src/ddsi_udp.c | 4 +- src/core/ddsi/src/q_nwif.c | 93 ++--- src/os/CMakeLists.txt | 4 +- src/os/include/os/os_socket.h | 99 +++-- src/os/include/os/os_stdlib.h | 11 + src/os/include/os/posix/os_platform_socket.h | 1 - .../include/os/windows/os_platform_socket.h | 1 - src/os/src/os_ifaddrs.c | 29 ++ src/os/src/posix/os_platform_ifaddrs.c | 128 +++++++ src/os/src/posix/os_platform_socket.c | 95 ----- src/os/src/snippets/code/os_stdlib.c | 2 + src/os/src/snippets/code/os_stdlib_asprintf.c | 48 +++ src/os/src/snippets/code/os_stdlib_memdup.c | 24 ++ src/os/src/windows/os_platform_ifaddrs.c | 260 ++++++++++++++ src/os/src/windows/os_platform_socket.c | 338 ------------------ src/os/src/windows/os_platform_stdlib.c | 2 + src/os/tests/ifaddrs.c | 83 +++++ 23 files changed, 696 insertions(+), 597 deletions(-) create mode 100644 src/os/src/os_ifaddrs.c create mode 100644 src/os/src/posix/os_platform_ifaddrs.c create mode 100644 src/os/src/snippets/code/os_stdlib_asprintf.c create mode 100644 src/os/src/snippets/code/os_stdlib_memdup.c create mode 100644 src/os/src/windows/os_platform_ifaddrs.c create mode 100644 src/os/tests/ifaddrs.c diff --git a/src/core/ddsi/include/ddsi/ddsi_ipaddr.h b/src/core/ddsi/include/ddsi/ddsi_ipaddr.h index 9a86d85..0fa1b44 100644 --- a/src/core/ddsi/include/ddsi/ddsi_ipaddr.h +++ b/src/core/ddsi/include/ddsi/ddsi_ipaddr.h @@ -17,7 +17,7 @@ enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str, int32_t kind); char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); -void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind); +void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr *src, int32_t kind); void ddsi_ipaddr_from_loc (os_sockaddr_storage *dst, const nn_locator_t *src); #endif diff --git a/src/core/ddsi/include/ddsi/ddsi_tran.h b/src/core/ddsi/include/ddsi/ddsi_tran.h index 27af518..4a1f428 100644 --- a/src/core/ddsi/include/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/ddsi/ddsi_tran.h @@ -75,7 +75,7 @@ typedef enum ddsi_locator_from_string_result (*ddsi_locator_from_string_fn_t) (d typedef char * (*ddsi_locator_to_string_fn_t) (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); -typedef int (*ddsi_enumerate_interfaces_fn_t) (ddsi_tran_factory_t tran, int max, struct os_ifAttributes_s *interfs); +typedef int (*ddsi_enumerate_interfaces_fn_t) (ddsi_tran_factory_t tran, os_ifaddrs_t **interfs); /* Data types */ @@ -237,7 +237,7 @@ enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc char *ddsi_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc); char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_locator_t *loc); -int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs); +int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs); #define ddsi_listener_locator(s,l) (ddsi_tran_locator (&(s)->m_base,(l))) ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener); diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index 3e2a970..bc6c371 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -49,7 +49,7 @@ enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_ return AFSR_INVALID; if ((ipv4 && tmpaddr.ss_family != AF_INET) || (!ipv4 && tmpaddr.ss_family != AF_INET6)) return AFSR_MISMATCH; - ddsi_ipaddr_to_loc (loc, &tmpaddr, kind); + ddsi_ipaddr_to_loc (loc, (os_sockaddr *)&tmpaddr, kind); /* This is just an address, so there is no valid value for port, other than INVALID. Without a guarantee that tmpaddr has port 0, best is to set it explicitly here */ loc->port = NN_LOCATOR_PORT_INVALID; @@ -94,10 +94,10 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ return dst; } -void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind) +void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr *src, int32_t kind) { dst->kind = kind; - switch (src->ss_family) + switch (src->sa_family) { case AF_INET: { @@ -137,7 +137,7 @@ void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int3 } #endif default: - NN_FATAL ("nn_address_to_loc: family %d unsupported\n", (int) src->ss_family); + NN_FATAL ("nn_address_to_loc: family %d unsupported\n", (int) src->sa_family); } } diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index 801023c..1534740 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -347,42 +347,23 @@ static void ddsi_raweth_deinit(void) } } -static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs) +static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { - struct ifaddrs *ifaddr, *ifa; + int err = 0; int cnt = 0; + os_ifaddrs_t *ifa; + os_ifaddr_filter_t filt = { .af_packet = 1 }; + (void)factory; - if (getifaddrs (&ifaddr) == -1) - return -errno; - for (ifa = ifaddr; ifa && cnt < max; ifa = ifa->ifa_next) - { - struct os_ifAttributes_s *f = &interfs[cnt]; - struct sockaddr_ll *x; - if (ifa->ifa_addr == NULL) - continue; - if (ifa->ifa_addr->sa_family != AF_PACKET) - continue; - if ((ifa->ifa_flags & (IFF_UP | IFF_BROADCAST)) != (IFF_UP | IFF_BROADCAST)) - continue; - strncpy(f->name, ifa->ifa_name, sizeof(f->name)); - f->name[sizeof(f->name)-1] = 0; - f->flags = ifa->ifa_flags; - f->interfaceIndexNo = if_nametoindex(f->name); - x = (struct sockaddr_ll *)&f->address; - memcpy(x, ifa->ifa_addr, sizeof (*x)); - x = (struct sockaddr_ll *)&f->network_mask; - if (ifa->ifa_netmask) - memcpy(x, ifa->ifa_netmask, sizeof (*x)); - else - memset(x, 0, sizeof(*x)); - x = (struct sockaddr_ll *)&f->broadcast_address; - if (ifa->ifa_broadaddr) - memcpy(x, ifa->ifa_broadaddr, sizeof (*x)); - else - memset(x, 0, sizeof(*x)); - cnt++; + + if ((err = os_getifaddrs(interfs, &filt)) == 0) { + for (ifa = *interfs; ifa != NULL; ifa = ifa->next, cnt++) { + /* do nothing */ + } + } else { + return -err; } - freeifaddrs (ifaddr); + return cnt; } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 5b88969..5885404 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -145,7 +145,7 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket, bool, os_sockaddr_storage * static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const os_sockaddr_storage *src) { nn_locator_t loc; - ddsi_ipaddr_to_loc(&loc, src, src->ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(&loc, (const os_sockaddr *)src, src->ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); ddsi_locator_to_string(dst, sizeof_dst, &loc); return dst; } @@ -452,7 +452,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s { if (srcloc) { - ddsi_ipaddr_to_loc(srcloc, &tcp->m_peer_addr, tcp->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(srcloc, (os_sockaddr *)&tcp->m_peer_addr, tcp->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); } return (ssize_t) pos; } @@ -869,7 +869,7 @@ static void ddsi_tcp_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * lo char buff[DDSI_LOCSTRLEN]; ddsi_tcp_conn_t tc = (ddsi_tcp_conn_t) conn; assert (tc->m_sock != Q_INVALID_SOCKET); - ddsi_ipaddr_to_loc (loc, &tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc (loc, (os_sockaddr *)&tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); ddsi_locator_to_string(buff, sizeof(buff), loc); TRACE (("(%s EP:%s)", ddsi_name, buff)); } @@ -976,7 +976,7 @@ static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc) sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr); nn_log (LC_INFO, "%s close %s connnection on socket %"PRIsock" to %s\n", ddsi_name, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); (void) shutdown (conn->m_sock, 2); - ddsi_ipaddr_to_loc(&loc, &conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(&loc, (os_sockaddr *)&conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); loc.port = conn->m_peer_port; purge_proxy_participants (&loc, conn->m_base.m_server); } diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index eea914b..363eb66 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -332,10 +332,10 @@ char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_loc return dst; } -int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs) +int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { /* FIXME: HACK */ if (factory->m_enumerate_interfaces_fn == 0) return 0; - return factory->m_enumerate_interfaces_fn (factory, max, interfs); + return factory->m_enumerate_interfaces_fn (factory, interfs); } diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 3a5f507..f547e31 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -79,7 +79,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s if (ret > 0) { if (srcloc) - ddsi_ipaddr_to_loc(srcloc, &src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); + ddsi_ipaddr_to_loc(srcloc, (os_sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); /* Check for udp packet truncation */ if ((((size_t) ret) > len) @@ -90,7 +90,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s { char addrbuf[DDSI_LOCSTRLEN]; nn_locator_t tmp; - ddsi_ipaddr_to_loc(&tmp, &src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); + ddsi_ipaddr_to_loc(&tmp, (os_sockaddr *)&src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6); ddsi_locator_to_string(addrbuf, sizeof(addrbuf), &tmp); NN_WARNING ("%s => %d truncated to %d\n", addrbuf, (int)ret, (int)len); } diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index c1964a9..fabddba 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -455,63 +455,51 @@ int find_own_ip (const char *requested_address) const char *sep = " "; char last_if_name[80] = ""; int quality = -1; - os_result res; int i; - unsigned int nif; - os_ifAttributes *ifs; + os_ifaddrs_t *ifa, *ifa_root = NULL; int maxq_list[MAX_INTERFACES]; int maxq_count = 0; size_t maxq_strlen = 0; int selected_idx = -1; char addrbuf[DDSI_LOCSTRLEN]; - ifs = os_malloc (MAX_INTERFACES * sizeof (*ifs)); - nn_log (LC_CONFIG, "interfaces:"); { int retcode; - nif = 0; - retcode = ddsi_enumerate_interfaces(gv.m_factory, (int)(MAX_INTERFACES - nif), ifs); - if (retcode > 0) - { - nif = (unsigned)retcode; - res = os_resultSuccess; - } - else if (retcode < 0) - { - NN_ERROR ("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, retcode); - res = os_resultFail; - } - else - { - if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6) - res = os_sockQueryIPv6Interfaces (ifs, MAX_INTERFACES, &nif); - else if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP) - res = os_sockQueryInterfaces (ifs, MAX_INTERFACES, &nif); - else - { - NN_ERROR ("ddsi_enumerate_interfaces(%s): no go but neither UDP[46] nor TCP[46]\n", gv.m_factory->m_typename); - res = os_resultFail; + retcode = ddsi_enumerate_interfaces(gv.m_factory, &ifa_root); + if (retcode < 0) { + NN_ERROR("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, retcode); + } else if (retcode == 0) { + int err; + const os_ifaddr_filter_t fltr = { + .af_inet = (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP), + .af_inet6 = (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6) + }; + + if ((err = os_getifaddrs(&ifa_root, &fltr)) != 0) { + NN_ERROR("os_getifaddrs: %s\n", os_strerror(err)); + retcode = -1; + } else if (ifa_root == NULL) { + NN_ERROR("ddsi_enumerate_interfaces(%s): no go but neither UDP[46] nor TCP[46]\n", gv.m_factory->m_typename); + retcode = -1; } } - if (res != os_resultSuccess) - { - NN_ERROR ("os_sockQueryInterfaces: %d\n", (int) res); - os_free (ifs); + + if (retcode < 0) { + os_freeifaddrs(ifa_root); return 0; } } gv.n_interfaces = 0; last_if_name[0] = 0; - for (i = 0; i < (int) nif; i++, sep = ", ") + for (ifa = ifa_root; ifa != NULL; ifa = ifa->next) { - os_sockaddr_storage tmpip, tmpmask; char if_name[sizeof (last_if_name)]; int q = 0; - strncpy (if_name, ifs[i].name, sizeof (if_name) - 1); + strncpy (if_name, ifa->name, sizeof (if_name) - 1); if_name[sizeof (if_name) - 1] = 0; if (strcmp (if_name, last_if_name)) @@ -519,46 +507,44 @@ int find_own_ip (const char *requested_address) strcpy (last_if_name, if_name); /* interface must be up */ - if ((ifs[i].flags & IFF_UP) == 0) + if ((ifa->flags & IFF_UP) == 0) { nn_log (LC_CONFIG, " (interface down)"); continue; } - tmpip = ifs[i].address; - tmpmask = ifs[i].network_mask; #ifdef __linux - if (tmpip.ss_family == AF_PACKET) + if (ifa->addr->sa_family == AF_PACKET) { /* FIXME: weirdo warning warranted */ nn_locator_t *l = &gv.interfaces[gv.n_interfaces].loc; l->kind = NN_LOCATOR_KIND_RAWETH; l->port = NN_LOCATOR_PORT_INVALID; memset(l->address, 0, 10); - memcpy(l->address + 10, ((struct sockaddr_ll *)&tmpip)->sll_addr, 6); + memcpy(l->address + 10, ((struct sockaddr_ll *)ifa->addr)->sll_addr, 6); } else #endif { - ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, &tmpip, gv.m_factory->m_kind); + ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, ifa->addr, gv.m_factory->m_kind); } ddsi_locator_to_string_no_port(addrbuf, sizeof(addrbuf), &gv.interfaces[gv.n_interfaces].loc); nn_log (LC_CONFIG, " %s(", addrbuf); - if (!(ifs[i].flags & IFF_MULTICAST) && multicast_override (if_name)) + if (!(ifa->flags & IFF_MULTICAST) && multicast_override (if_name)) { nn_log (LC_CONFIG, "assume-mc:"); - ifs[i].flags |= IFF_MULTICAST; + ifa->flags |= IFF_MULTICAST; } - if (ifs[i].flags & IFF_LOOPBACK) + if (ifa->flags & IFF_LOOPBACK) { /* Loopback device has the lowest priority of every interface available, because the other interfaces at least in principle allow communicating with other machines. */ q += 0; #if OS_SOCKET_HAS_IPV6 - if (!(tmpip.ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &tmpip)->sin6_addr))) + if (!(ifa->addr->sa_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *)ifa->addr)->sin6_addr))) q += 1; #endif } @@ -575,16 +561,16 @@ int find_own_ip (const char *requested_address) which it was received. But that means proper multi-homing support and has quite an impact in various places, not least of which is the abstraction layer. */ - if (!(tmpip.ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &tmpip)->sin6_addr))) + if (!(ifa->addr->sa_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *)ifa->addr)->sin6_addr))) q += 5; #endif /* We strongly prefer a multicast capable interface, if that's not available anything that's not point-to-point, or else we hope IP routing will take care of the issues. */ - if (ifs[i].flags & IFF_MULTICAST) + if (ifa->flags & IFF_MULTICAST) q += 4; - else if (!(ifs[i].flags & IFF_POINTOPOINT)) + else if (!(ifa->flags & IFF_POINTOPOINT)) q += 3; else q += 2; @@ -604,10 +590,9 @@ int find_own_ip (const char *requested_address) /* FIXME: HACK HACK */ //ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, &tmpip, gv.m_factory->m_kind); - if (tmpip.ss_family == AF_INET || tmpip.ss_family == AF_INET6) + if (ifa->addr->sa_family == AF_INET || ifa->addr->sa_family == AF_INET6) { - tmpmask.ss_family = tmpip.ss_family; - ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].netmask, &tmpmask, gv.m_factory->m_kind); + ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].netmask, ifa->netmask, gv.m_factory->m_kind); } else { @@ -615,14 +600,14 @@ int find_own_ip (const char *requested_address) gv.interfaces[gv.n_interfaces].netmask.port = NN_LOCATOR_PORT_INVALID; memset(&gv.interfaces[gv.n_interfaces].netmask.address, 0, sizeof(gv.interfaces[gv.n_interfaces].netmask.address)); } - gv.interfaces[gv.n_interfaces].mc_capable = ((ifs[i].flags & IFF_MULTICAST) != 0); - gv.interfaces[gv.n_interfaces].point_to_point = ((ifs[i].flags & IFF_POINTOPOINT) != 0); - gv.interfaces[gv.n_interfaces].if_index = ifs[i].interfaceIndexNo; + gv.interfaces[gv.n_interfaces].mc_capable = ((ifa->flags & IFF_MULTICAST) != 0); + gv.interfaces[gv.n_interfaces].point_to_point = ((ifa->flags & IFF_POINTOPOINT) != 0); + gv.interfaces[gv.n_interfaces].if_index = ifa->index; gv.interfaces[gv.n_interfaces].name = os_strdup (if_name); gv.n_interfaces++; } nn_log (LC_CONFIG, "\n"); - os_free (ifs); + os_freeifaddrs (ifa_root); if (requested_address == NULL) { diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt index 3f70059..2fce835 100644 --- a/src/os/CMakeLists.txt +++ b/src/os/CMakeLists.txt @@ -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( diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index a5c4945..39652d9 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -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( diff --git a/src/os/include/os/os_stdlib.h b/src/os/include/os/os_stdlib.h index adff4e3..26ce492 100644 --- a/src/os/include/os/os_stdlib.h +++ b/src/os/include/os/os_stdlib.h @@ -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, diff --git a/src/os/include/os/posix/os_platform_socket.h b/src/os/include/os/posix/os_platform_socket.h index 372d8f0..38bed46 100644 --- a/src/os/include/os/posix/os_platform_socket.h +++ b/src/os/include/os/posix/os_platform_socket.h @@ -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 diff --git a/src/os/include/os/windows/os_platform_socket.h b/src/os/include/os/windows/os_platform_socket.h index 592996c..30ff75a 100644 --- a/src/os/include/os/windows/os_platform_socket.h +++ b/src/os/include/os/windows/os_platform_socket.h @@ -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 diff --git a/src/os/src/os_ifaddrs.c b/src/os/src/os_ifaddrs.c new file mode 100644 index 0000000..77e92e9 --- /dev/null +++ b/src/os/src/os_ifaddrs.c @@ -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; + } +} + diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c new file mode 100644 index 0000000..9954ac0 --- /dev/null +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -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 +#include + +#if defined(__linux) +#include /* 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; +} diff --git a/src/os/src/posix/os_platform_socket.c b/src/os/src/posix/os_platform_socket.c index 75d6d85..92af40f 100644 --- a/src/os/src/posix/os_platform_socket.c +++ b/src/os/src/posix/os_platform_socket.c @@ -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; -} - diff --git a/src/os/src/snippets/code/os_stdlib.c b/src/os/src/snippets/code/os_stdlib.c index a79b40e..af9f0d4 100644 --- a/src/os/src/snippets/code/os_stdlib.c +++ b/src/os/src/snippets/code/os_stdlib.c @@ -22,7 +22,9 @@ #include #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" diff --git a/src/os/src/snippets/code/os_stdlib_asprintf.c b/src/os/src/snippets/code/os_stdlib_asprintf.c new file mode 100644 index 0000000..9432375 --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_asprintf.c @@ -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; +} diff --git a/src/os/src/snippets/code/os_stdlib_memdup.c b/src/os/src/snippets/code/os_stdlib_memdup.c new file mode 100644 index 0000000..37638da --- /dev/null +++ b/src/os/src/snippets/code/os_stdlib_memdup.c @@ -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; +} diff --git a/src/os/src/windows/os_platform_ifaddrs.c b/src/os/src/windows/os_platform_ifaddrs.c new file mode 100644 index 0000000..28c7127 --- /dev/null +++ b/src/os/src/windows/os_platform_ifaddrs.c @@ -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 +#include + +#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; +} diff --git a/src/os/src/windows/os_platform_socket.c b/src/os/src/windows/os_platform_socket.c index 3e32bc5..1faa048 100644 --- a/src/os/src/windows/os_platform_socket.c +++ b/src/os/src/windows/os_platform_socket.c @@ -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 diff --git a/src/os/src/windows/os_platform_stdlib.c b/src/os/src/windows/os_platform_stdlib.c index 27f2acb..9b9ff3c 100644 --- a/src/os/src/windows/os_platform_stdlib.c +++ b/src/os/src/windows/os_platform_stdlib.c @@ -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" diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c new file mode 100644 index 0000000..c7a8d1a --- /dev/null +++ b/src/os/tests/ifaddrs.c @@ -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 */ + From ea3f5e7ff41d83874c7a9012751c008749f025ec Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 20 Sep 2018 11:20:13 +0200 Subject: [PATCH 03/15] Disable AF_PACKET interfaces for all platforms but Linux Signed-off-by: Jeroen Koekkoek --- src/os/src/posix/os_platform_ifaddrs.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index 9954ac0..ba820e0 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -27,9 +27,11 @@ copy_ifaddrs(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) 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); + assert(sys_ifa->ifa_addr->sa_family == AF_INET +#ifdef __linux + || sys_ifa->ifa_addr->sa_family == AF_PACKET +#endif /* __linux */ + || sys_ifa->ifa_addr->sa_family == AF_INET6); ifa = os_malloc(sizeof(*ifa)); if (ifa == NULL) { @@ -49,9 +51,11 @@ copy_ifaddrs(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) } else { if (sys_ifa->ifa_addr->sa_family == AF_INET) { size = sizeof(struct sockaddr_in); +#ifdef __linux } else { assert(sys_ifa->ifa_addr->sa_family == AF_PACKET); size = sizeof(struct sockaddr_ll); +#endif /* __linux */ } if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, size)) || @@ -97,8 +101,10 @@ os_getifaddrs( 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) + if ((addr->sa_family == AF_INET && ifltr->af_inet) +#ifdef __linux + || (addr->sa_family == AF_PACKET && ifltr->af_packet) +#endif /* __linux */ || (addr->sa_family == AF_INET6 && ifltr->af_inet6 && !IN6_IS_ADDR_UNSPECIFIED( &((struct sockaddr_in6 *)addr)->sin6_addr))) From 7ba3bca087351efe930ce2be7127b60adc820fd4 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 18 Oct 2018 11:41:08 +0200 Subject: [PATCH 04/15] Change socket function signatures to use os_sockaddr * Consolidated and cleaned up some (duplicate) functions. * Removed some unused functions that did not make sense to keep around. Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/CMakeLists.txt | 1 + src/core/ddsi/src/ddsi_eth.c | 30 ++ src/core/ddsi/src/ddsi_eth.h | 20 ++ src/core/ddsi/src/ddsi_ipaddr.c | 2 +- src/core/ddsi/src/ddsi_raweth.c | 14 +- src/core/ddsi/src/ddsi_tcp.c | 83 ++--- src/core/ddsi/src/ddsi_tran.c | 3 - src/core/ddsi/src/ddsi_udp.c | 17 +- src/core/ddsi/src/q_nwif.c | 32 +- src/os/include/os/os_socket.h | 105 +++--- src/os/include/os/os_stdlib.h | 2 +- src/os/src/os_socket.c | 359 +++++--------------- src/os/src/posix/os_platform_ifaddrs.c | 70 ++-- src/os/src/snippets/code/os_stdlib_memdup.c | 6 +- src/os/src/snippets/code/os_stdlib_strdup.c | 11 +- src/os/src/windows/os_platform_ifaddrs.c | 15 +- src/os/src/windows/os_platform_socket.c | 3 - src/os/tests/ifaddrs.c | 8 +- src/os/tests/iter.c | 0 src/os/tests/stdlib.c | 0 20 files changed, 275 insertions(+), 506 deletions(-) create mode 100644 src/core/ddsi/src/ddsi_eth.c create mode 100644 src/core/ddsi/src/ddsi_eth.h mode change 100755 => 100644 src/os/tests/iter.c mode change 100755 => 100644 src/os/tests/stdlib.c diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 95f0776..e7129df 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -10,6 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" + ddsi_eth.c ddsi_ser.c ddsi_ssl.c ddsi_tcp.c diff --git a/src/core/ddsi/src/ddsi_eth.c b/src/core/ddsi/src/ddsi_eth.c new file mode 100644 index 0000000..f821832 --- /dev/null +++ b/src/core/ddsi/src/ddsi_eth.c @@ -0,0 +1,30 @@ +/* + * 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 "ddsi_eth.h" + +int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, os_ifaddrs_t **ifs) +{ + int err; + int afs[] = { AF_INET, 0 }; + + (void)fact; + +#if OS_SOCKET_HAVE_IPV6 + if (config.transport_selector == TRANS_TCP6 || + config.transport_selector == TRANS_UDP6) + { + afs[0] = AF_INET6; + } +#endif /* OS_SOCKET_HAVE_IPV6 */ + + return -os_getifaddrs(ifs, afs); +} diff --git a/src/core/ddsi/src/ddsi_eth.h b/src/core/ddsi/src/ddsi_eth.h new file mode 100644 index 0000000..0954755 --- /dev/null +++ b/src/core/ddsi/src/ddsi_eth.h @@ -0,0 +1,20 @@ +/* + * 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 + */ +#ifndef DDSI_ETH_H +#define DDSI_ETH_H + +#include "ddsi/ddsi_tran.h" +#include "os/os.h" + +int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, os_ifaddrs_t **ifs); + +#endif /* DDSI_ETH_H */ diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index bc6c371..96766da 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -29,7 +29,7 @@ enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory ddsi_ipaddr_from_loc(&ownip, &gv.ownloc); if (os_sockaddrSameSubnet ((os_sockaddr *) &tmp, (os_sockaddr *) &iftmp, (os_sockaddr *) &nmtmp)) { - if (os_sockaddrIPAddressEqual ((os_sockaddr*) &iftmp, (os_sockaddr*) &ownip)) + if (os_sockaddr_compare((os_sockaddr *)&iftmp, (os_sockaddr *)&ownip) == 0) return DNAR_SAME; else return DNAR_LOCAL; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index 1534740..ddf6c90 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -350,21 +350,11 @@ static void ddsi_raweth_deinit(void) static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { int err = 0; - int cnt = 0; - os_ifaddrs_t *ifa; - os_ifaddr_filter_t filt = { .af_packet = 1 }; + int afs[] = { AF_PACKET, 0 }; (void)factory; - if ((err = os_getifaddrs(interfs, &filt)) == 0) { - for (ifa = *interfs; ifa != NULL; ifa = ifa->next, cnt++) { - /* do nothing */ - } - } else { - return -err; - } - - return cnt; + return -os_getifaddrs(interfs, afs); } int ddsi_raweth_init (void) diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 5885404..6a57fb1 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -13,6 +13,7 @@ #include #include +#include "ddsi_eth.h" #include "ddsi/ddsi_tran.h" #include "ddsi/ddsi_tcp.h" #include "ddsi/ddsi_ipaddr.h" @@ -82,43 +83,16 @@ static void nn_trace_tcp (const char *fmt, ...) #define TRACE_TCP(args) ((config.enabled_logcats & LC_TCP) ? (nn_trace_tcp args) : (void) 0) -static unsigned short sockaddr_get_port (const os_sockaddr_storage *addr) -{ - if (addr->ss_family == AF_INET) - return ntohs (((os_sockaddr_in *) addr)->sin_port); -#if OS_SOCKET_HAS_IPV6 - else - return ntohs (((os_sockaddr_in6 *) addr)->sin6_port); -#endif -} - static int ddsi_tcp_cmp_conn (const ddsi_tcp_conn_t c1, const ddsi_tcp_conn_t c2) { - const os_sockaddr_storage *a1s = &c1->m_peer_addr; - const os_sockaddr_storage *a2s = &c2->m_peer_addr; - if (a1s->ss_family != a2s->ss_family) - return (a1s->ss_family < a2s->ss_family) ? -1 : 1; + const os_sockaddr *a1s = (os_sockaddr *)&c1->m_peer_addr; + const os_sockaddr *a2s = (os_sockaddr *)&c2->m_peer_addr; + if (a1s->sa_family != a2s->sa_family) + return (a1s->sa_family < a2s->sa_family) ? -1 : 1; else if (c1->m_peer_port != c2->m_peer_port) return (c1->m_peer_port < c2->m_peer_port) ? -1 : 1; - else if (a1s->ss_family == AF_INET) - { - const os_sockaddr_in *a1 = (const os_sockaddr_in *) a1s; - const os_sockaddr_in *a2 = (const os_sockaddr_in *) a2s; - return (a1->sin_addr.s_addr == a2->sin_addr.s_addr) ? 0 : (a1->sin_addr.s_addr < a2->sin_addr.s_addr) ? -1 : 1; - } -#if OS_SOCKET_HAS_IPV6 - else if (a1s->ss_family == AF_INET6) - { - const os_sockaddr_in6 *a1 = (const os_sockaddr_in6 *) a1s; - const os_sockaddr_in6 *a2 = (const os_sockaddr_in6 *) a2s; - return memcmp (&a1->sin6_addr, &a2->sin6_addr, 16); - } -#endif - else - { - assert (0); - return 0; - } + + return os_sockaddr_compare(a1s, a2s); } typedef struct ddsi_tcp_node @@ -140,12 +114,12 @@ static os_mutex ddsi_tcp_cache_lock_g; static ut_avlTree_t ddsi_tcp_cache_g; static struct ddsi_tran_factory ddsi_tcp_factory_g; -static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket, bool, os_sockaddr_storage *); +static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket, bool, os_sockaddr *); -static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const os_sockaddr_storage *src) +static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const os_sockaddr *src) { nn_locator_t loc; - ddsi_ipaddr_to_loc(&loc, (const os_sockaddr *)src, src->ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); + ddsi_ipaddr_to_loc(&loc, src, src->sa_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); ddsi_locator_to_string(dst, sizeof_dst, &loc); return dst; } @@ -185,7 +159,7 @@ static unsigned short get_socket_port (os_socket socket) NN_ERROR ("ddsi_tcp_get_socket_port: getsockname errno %d\n", err); return 0; } - return sockaddr_get_port(&addr); + return os_sockaddr_get_port((os_sockaddr *)&addr); } static void ddsi_tcp_conn_set_socket (ddsi_tcp_conn_t conn, os_socket sock) @@ -257,7 +231,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const struct msghdr * m } #endif - sockaddr_to_string_with_port(buff, sizeof(buff), (const os_sockaddr_storage *) msg->msg_name); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *) msg->msg_name); nn_log (LC_INFO, "%s connect socket %"PRIsock" port %u to %s\n", ddsi_name, sock, get_socket_port (sock), buff); /* Also may need to receive on connection so add to waitset */ @@ -305,7 +279,7 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) } } - sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&conn->m_peer_addr); nn_log (LC_INFO, "%s cache %s %s socket %"PRIsock" to %s\n", ddsi_name, action, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); } @@ -319,7 +293,7 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) node = ut_avlLookupDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path); if (node) { - sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&conn->m_peer_addr); nn_log (LC_INFO, "%s cache removed socket %"PRIsock" to %s\n", ddsi_name, conn->m_sock, buff); ut_avlDeleteDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path); ddsi_tcp_node_free (node); @@ -340,7 +314,7 @@ static ddsi_tcp_conn_t ddsi_tcp_cache_find (const struct msghdr * msg) ddsi_tcp_conn_t ret = NULL; memset (&key, 0, sizeof (key)); - key.m_peer_port = sockaddr_get_port (msg->msg_name); + key.m_peer_port = os_sockaddr_get_port (msg->msg_name); memcpy (&key.m_peer_addr, msg->msg_name, msg->msg_namelen); /* Check cache for existing connection to target */ @@ -361,7 +335,7 @@ static ddsi_tcp_conn_t ddsi_tcp_cache_find (const struct msghdr * msg) } if (ret == NULL) { - ret = ddsi_tcp_new_conn (Q_INVALID_SOCKET, false, &key.m_peer_addr); + ret = ddsi_tcp_new_conn (Q_INVALID_SOCKET, false, (os_sockaddr *)&key.m_peer_addr); ddsi_tcp_cache_add (ret, &path); } os_mutexUnlock (&ddsi_tcp_cache_lock_g); @@ -586,7 +560,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d memset(&msg, 0, sizeof(msg)); set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov); msg.msg_name = &dstaddr; - msg.msg_namelen = (socklen_t) os_sockaddrSizeof((os_sockaddr *) &dstaddr); + msg.msg_namelen = (socklen_t) os_sockaddr_size((os_sockaddr *) &dstaddr); #if SYSDEPS_MSGHDR_FLAGS msg.msg_flags = (int) flags; #endif @@ -822,7 +796,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) if (sock == Q_INVALID_SOCKET) { getsockname (tl->m_sock, (struct sockaddr *) &addr, &addrlen); - sockaddr_to_string_with_port(buff, sizeof(buff), &addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&addr); nn_log ((err == 0) ? LC_ERROR : LC_FATAL, "%s accept failed on socket %"PRIsock" at %s errno %d\n", ddsi_name, tl->m_sock, buff, err); } else if (getpeername (sock, (struct sockaddr *) &addr, &addrlen) == -1) @@ -832,11 +806,11 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) } else { - sockaddr_to_string_with_port(buff, sizeof(buff), &addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&addr); nn_log (LC_INFO, "%s accept new socket %"PRIsock" on socket %"PRIsock" from %s\n", ddsi_name, sock, tl->m_sock, buff); os_sockSetNonBlocking (sock, true); - tcp = ddsi_tcp_new_conn (sock, true, &addr); + tcp = ddsi_tcp_new_conn (sock, true, (os_sockaddr *)&addr); #ifdef DDSI_INCLUDE_SSL tcp->m_ssl = ssl; #endif @@ -885,7 +859,7 @@ static void ddsi_tcp_base_init (struct ddsi_tran_conn * base) base->m_peer_locator_fn = ddsi_tcp_conn_peer_locator; } -static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket sock, bool server, os_sockaddr_storage * peer) +static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket sock, bool server, os_sockaddr * peer) { ddsi_tcp_conn_t conn = (ddsi_tcp_conn_t) os_malloc (sizeof (*conn)); @@ -893,8 +867,8 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket sock, bool server, os_sockad ddsi_tcp_base_init (&conn->m_base); os_mutexInit (&conn->m_mutex); conn->m_sock = Q_INVALID_SOCKET; - conn->m_peer_addr = *peer; - conn->m_peer_port = sockaddr_get_port (peer); + (void)memcpy(&conn->m_peer_addr, peer, os_sockaddr_size(peer)); + conn->m_peer_port = os_sockaddr_get_port (peer); conn->m_base.m_server = server; conn->m_base.m_base.m_port = INVALID_PORT; ddsi_tcp_conn_set_socket (conn, sock); @@ -939,7 +913,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t return NULL; } - sockaddr_to_string_with_port(buff, sizeof(buff), &addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&addr); nn_log (LC_INFO, "%s create listener socket %"PRIsock" on %s\n", ddsi_name, sock, buff); } @@ -949,7 +923,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t static void ddsi_tcp_conn_delete (ddsi_tcp_conn_t conn) { char buff[DDSI_LOCSTRLEN]; - sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&conn->m_peer_addr); nn_log (LC_INFO, "%s free %s connnection on socket %"PRIsock" to %s\n", ddsi_name, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); #ifdef DDSI_INCLUDE_SSL @@ -973,7 +947,7 @@ static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc) char buff[DDSI_LOCSTRLEN]; nn_locator_t loc; ddsi_tcp_conn_t conn = (ddsi_tcp_conn_t) tc; - sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&conn->m_peer_addr); nn_log (LC_INFO, "%s close %s connnection on socket %"PRIsock" to %s\n", ddsi_name, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff); (void) shutdown (conn->m_sock, 2); ddsi_ipaddr_to_loc(&loc, (os_sockaddr *)&conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6); @@ -1035,13 +1009,13 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) } do { - ret = connect (sock, (struct sockaddr *) &addr, (unsigned) os_sockaddrSizeof((os_sockaddr *)&addr)); + ret = connect (sock, (struct sockaddr *) &addr, (unsigned) os_sockaddr_size((os_sockaddr *)&addr)); } while ((ret == -1) && (os_getErrno() == os_sockEINTR)); if (ret == -1) { char buff[DDSI_LOCSTRLEN]; - sockaddr_to_string_with_port(buff, sizeof(buff), &addr); + sockaddr_to_string_with_port(buff, sizeof(buff), (os_sockaddr *)&addr); nn_log (LC_WARNING, "%s failed to connect to own listener (%s) error %d\n", ddsi_name, buff, os_getErrno()); } } @@ -1093,6 +1067,7 @@ int ddsi_tcp_init (void) ddsi_tcp_factory_g.m_free_fn = ddsi_tcp_release_factory; ddsi_tcp_factory_g.m_locator_from_string_fn = ddsi_tcp_address_from_string; ddsi_tcp_factory_g.m_locator_to_string_fn = ddsi_ipaddr_to_string; + ddsi_tcp_factory_g.m_enumerate_interfaces_fn = ddsi_eth_enumerate_interfaces; ddsi_factory_add (&ddsi_tcp_factory_g); #if OS_SOCKET_HAS_IPV6 diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 363eb66..5b5576b 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -334,8 +334,5 @@ char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_loc int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { - /* FIXME: HACK */ - if (factory->m_enumerate_interfaces_fn == 0) - return 0; return factory->m_enumerate_interfaces_fn (factory, interfs); } diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index f547e31..62d8441 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -13,6 +13,7 @@ #include #include "os/os.h" #include "os/os_atomics.h" +#include "ddsi_eth.h" #include "ddsi/ddsi_tran.h" #include "ddsi/ddsi_udp.h" #include "ddsi/ddsi_ipaddr.h" @@ -120,7 +121,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d ddsi_ipaddr_from_loc(&dstaddr, dst); set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov); msg.msg_name = &dstaddr; - msg.msg_namelen = (socklen_t) os_sockaddrSizeof((os_sockaddr *) &dstaddr); + msg.msg_namelen = (socklen_t) os_sockaddr_size((os_sockaddr *) &dstaddr); #if !defined(__sun) || defined(_XPG4_2) msg.msg_control = NULL; msg.msg_controllen = 0; @@ -200,16 +201,6 @@ static int ddsi_udp_conn_locator (ddsi_tran_base_t base, nn_locator_t *loc) return ret; } -static unsigned short sockaddr_get_port (const os_sockaddr_storage *addr) -{ - if (addr->ss_family == AF_INET) - return ntohs (((os_sockaddr_in *) addr)->sin_port); -#if OS_SOCKET_HAS_IPV6 - else - return ntohs (((os_sockaddr_in6 *) addr)->sin6_port); -#endif -} - static unsigned short get_socket_port (os_socket socket) { os_sockaddr_storage addr; @@ -220,7 +211,8 @@ static unsigned short get_socket_port (os_socket socket) NN_ERROR ("ddsi_udp_get_socket_port: getsockname errno %d\n", err); return 0; } - return sockaddr_get_port(&addr); + + return os_sockaddr_get_port((os_sockaddr *)&addr); } static ddsi_tran_conn_t ddsi_udp_create_conn @@ -531,6 +523,7 @@ int ddsi_udp_init (void) ddsi_udp_factory_g.m_is_nearby_address_fn = ddsi_ipaddr_is_nearby_address; ddsi_udp_factory_g.m_locator_from_string_fn = ddsi_udp_address_from_string; ddsi_udp_factory_g.m_locator_to_string_fn = ddsi_udp_locator_to_string; + ddsi_udp_factory_g.m_enumerate_interfaces_fn = ddsi_eth_enumerate_interfaces; #if OS_SOCKET_HAS_IPV6 if (config.transport_selector == TRANS_UDP6) { diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index fabddba..876e34c 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -466,28 +466,10 @@ int find_own_ip (const char *requested_address) nn_log (LC_CONFIG, "interfaces:"); { - int retcode; - retcode = ddsi_enumerate_interfaces(gv.m_factory, &ifa_root); - if (retcode < 0) { - NN_ERROR("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, retcode); - } else if (retcode == 0) { - int err; - const os_ifaddr_filter_t fltr = { - .af_inet = (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP), - .af_inet6 = (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6) - }; - - if ((err = os_getifaddrs(&ifa_root, &fltr)) != 0) { - NN_ERROR("os_getifaddrs: %s\n", os_strerror(err)); - retcode = -1; - } else if (ifa_root == NULL) { - NN_ERROR("ddsi_enumerate_interfaces(%s): no go but neither UDP[46] nor TCP[46]\n", gv.m_factory->m_typename); - retcode = -1; - } - } - - if (retcode < 0) { - os_freeifaddrs(ifa_root); + int ret; + ret = ddsi_enumerate_interfaces(gv.m_factory, &ifa_root); + if (ret < 0) { + NN_ERROR("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, ret); return 0; } } @@ -507,10 +489,12 @@ int find_own_ip (const char *requested_address) strcpy (last_if_name, if_name); /* interface must be up */ - if ((ifa->flags & IFF_UP) == 0) - { + if ((ifa->flags & IFF_UP) == 0) { nn_log (LC_CONFIG, " (interface down)"); continue; + } else if (os_sockaddr_is_unspecified(ifa->addr)) { + nn_log (LC_CONFIG, " (address unspecified)"); + continue; } #ifdef __linux diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index 39652d9..b378530 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -110,12 +110,6 @@ extern "C" { #define SD_FLAG_IS_SET(flags, flag) ((((uint32_t)(flags) & (uint32_t)(flag))) != 0U) - 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; @@ -137,14 +131,17 @@ extern "C" { * 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 + * @param[in] afs NULL-terminated array of address families (AF_xyz) to + * restrict resulting set of network interfaces too. NULL to + * return all network interfaces for all supported address + * families. * * @returns Returns zero on success or a valid errno value on error. */ OSAPI_EXPORT _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_ const os_ifaddr_filter_t *ifilt); + _In_opt_ const int *const afs); /** * @brief Free os_ifaddrs_t structure list allocated by os_getifaddrs() @@ -252,20 +249,46 @@ extern "C" { os_time *timeout); #endif /* WIN32 */ - /* docced in implementation file */ - OSAPI_EXPORT os_result - os_sockaddrInit(os_sockaddr* sa, - bool isIPv4); /* IPvX is poorly abstracted; this is temporary */ + /** + * Returns sizeof(sa) based on the family of the actual content. + * @param sa the sockaddr to get the actual size for + * @return The actual size sa based on the family. If the family is + * unknown 0 will be returned. + * @pre sa is a valid sockaddr pointer + */ + OSAPI_EXPORT size_t + os_sockaddr_size( + const os_sockaddr *const sa) __nonnull_all__; - /* docced in implementation file */ - OSAPI_EXPORT bool - os_sockaddrIPAddressEqual(const os_sockaddr* this_sock, - const os_sockaddr* that_sock); + /** + * Retrieves the port number from the supplied sockaddr. + * @param sa the sockaddr to retrieve the port from + * @return The port number stored in the supplied sockaddr convert to host order + * @pre sa is a valid sockaddr pointer + */ + OSAPI_EXPORT uint16_t + os_sockaddr_get_port(const os_sockaddr *const sa) __nonnull_all__; + /** + * Compare two socket IP host addresses for equality - does not consider the port number. + * This is a 'straight' equal i.e. family must match and address bytes + * must correspond. So it will not consider the possibility of IPv6 mapped + * IPv4 addresses or anything arcane like that. + * @param thisSock First address + * @param thatSock Second address. + * @return true if equal, false otherwise. + */ OSAPI_EXPORT int - os_sockaddrIpAddressCompare(const os_sockaddr* addr1, - const os_sockaddr* addr2) __nonnull_all__ - __attribute_pure__; + os_sockaddr_compare( + const os_sockaddr *sa1, + const os_sockaddr *sa2) __nonnull_all__ __attribute_pure__; + + /** + * FIXME: comment + */ + OSAPI_EXPORT int + os_sockaddr_is_unspecified( + const os_sockaddr *const sa) __nonnull_all__; /* docced in implementation file */ OSAPI_EXPORT bool @@ -284,20 +307,6 @@ extern "C" { os_sockaddrAddressToString(const os_sockaddr* sa, char* buffer, size_t buflen); - /** - * Convert a socket address to a string format representation including the - * portnumber. - * @param sa The socket address struct. - * @param buffer A character buffer to hold the string rep of the address. - * @param buflen The (max) size of the buffer - * @return Pointer to start of string - */ - OSAPI_EXPORT char* - os_sockaddrAddressPortToString( - const os_sockaddr* sa, - char* buffer, - size_t buflen); - /** * Convert the provided addressString into a os_sockaddr. * @@ -323,16 +332,6 @@ extern "C" { OSAPI_EXPORT bool os_sockaddrIsLoopback(const os_sockaddr* thisSock); - /** - * Returns sizeof(sa) based on the family of the actual content. - * @param sa the sockaddr to get the actual size for - * @return The actual size sa based on the family. If the family is - * unknown 0 will be returned. - * @pre sa is a valid sockaddr pointer - */ - OSAPI_EXPORT size_t - os_sockaddrSizeof(const os_sockaddr* sa); - /** * Sets the address of the sockaddr to the special IN_ADDR_ANY value. * @param sa the sockaddr to set the address for @@ -342,26 +341,6 @@ extern "C" { OSAPI_EXPORT void os_sockaddrSetInAddrAny(os_sockaddr* sa); - /** - * Sets the port number in the supplied sockaddr. - * @param sa the sockaddr to set the port in - * @param port the port number to be set in network byte order - * @pre sa is a valid sockaddr pointer - * @post Port number of sa is set to port - */ - OSAPI_EXPORT void - os_sockaddrSetPort(os_sockaddr* sa, uint16_t port); - - /** - * Retrieves the port number from the supplied sockaddr. - * @param sa the sockaddr to retrieve the port from - * @return The port number stored in the supplied sockaddr (hence in network byte order) - * @pre sa is a valid sockaddr pointer - */ - OSAPI_EXPORT uint16_t - os_sockaddrGetPort(const os_sockaddr* const sa); - - /** * @} */ diff --git a/src/os/include/os/os_stdlib.h b/src/os/include/os/os_stdlib.h index 26ce492..c8a665b 100644 --- a/src/os/include/os/os_stdlib.h +++ b/src/os/include/os/os_stdlib.h @@ -263,7 +263,7 @@ extern "C" { __attribute_warn_unused_result__; void * - os_memdup(void *src, size_t n); + os_memdup(const void *src, size_t n); /** \brief os_strsep wrapper * diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 16c955f..23f7de5 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -20,6 +20,11 @@ #include #include + +#ifdef __linux +#include /* sockaddr_ll */ +#endif /* __linux */ + #include "os/os.h" #if (OS_SOCKET_HAS_IPV6 == 1) @@ -40,180 +45,113 @@ const os_in6_addr os_in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } #define OS_INET_PTON inet_pton #endif -static -void os__sockaddrInit4(os_sockaddr* sa) +size_t +os_sockaddr_size(const os_sockaddr *sa) { - assert(sa); - /* 0 is a valid value for all members besides sa_family */ - memset(sa, 0, sizeof(os_sockaddr_in)); - sa->sa_family = AF_INET; -} + size_t sz; + assert(sa != NULL); + switch(sa->sa_family) { #if (OS_SOCKET_HAS_IPV6 == 1) -static -void os__sockaddrInit6(os_sockaddr* sa) -{ - assert(sa); - /* 0 is a valid value for all members besides sa_family */ - memset(sa, 0, sizeof(os_sockaddr_in6)); - sa->sa_family = AF_INET6; -} -#endif - - -/** - * Initialises the memory pointed to by sa. The address family - * will be set correctly according to isIPv4. - * @param sa Pointer to the os_sockaddr to be initialised - * @param isIPv4 Flag indicating whether *sa will be IPv4 or IPv6. If - * IPv6 is not supported but this flag is FALSE, sa will be initialised - * as IPv4 and an API-warning is logged. - * @pre sa != NULL - * @return os_resultSuccess on successful initialisation, os_resultInvalid - * if isIPv4 was FALSE but IPv6 is not supported. - * @post sa is initialised - * @note Please be aware that the memory will be memset; make sure that - * enough memory for the requested address kind is available. Allocating - * os_sockaddr_storage always suffices. - */ -os_result -os_sockaddrInit(os_sockaddr* sa, - bool isIPv4) -{ - os_result result = os_resultSuccess; - - assert(sa); - if (!isIPv4) - { -#if (OS_SOCKET_HAS_IPV6 == 1) - os__sockaddrInit6(sa); -#else - OS_ERROR("os_sockaddrInit", 0, - "Unsupported parameter value: IPV6 address requested but not supported by this platform"); - os__sockaddrInit4(sa); - result = os_resultInvalid; -#endif - } - else - { - os__sockaddrInit4(sa); + case AF_INET6: + sz = sizeof(os_sockaddr_in6); + break; +#endif /* OS_SOCKET_HAS_IPV6 */ +#ifdef __linux + case AF_PACKET: + sz = sizeof(struct sockaddr_ll); + break; +#endif /* __linux */ + default: + assert(sa->sa_family == AF_INET); + sz = sizeof(os_sockaddr_in); + break; } - return result; + return sz; } - -/** -* Compare two socket IP host addresses for equality - does not consider the port number. -* This is a 'straight' equal i.e. family must match and address bytes -* must correspond. So it will not consider the possibility of IPv6 mapped -* IPv4 addresses or anything arcane like that. -* @param thisSock First address -* @param thatSock Second address. -* @return true if equal, false otherwise. -*/ -bool -os_sockaddrIPAddressEqual(const os_sockaddr* thisSock, - const os_sockaddr* thatSock) +uint16_t os_sockaddr_get_port(const os_sockaddr *sa) { - bool result = false; -#if (OS_SOCKET_HAS_IPV6 == 1) - os_sockaddr_in6 * thisV6, * thatV6; -#endif + unsigned short port = 0; - if (thisSock->sa_family == thatSock->sa_family) - { - if (thisSock->sa_family == AF_INET) - { - /* IPv4 */ - result = (((os_sockaddr_in*)thisSock)->sin_addr.s_addr == - ((os_sockaddr_in*)thatSock)->sin_addr.s_addr ? - true: false); - } -#if (OS_SOCKET_HAS_IPV6 == 1) - else - { - /* IPv6 */ - thisV6 = (os_sockaddr_in6*) thisSock; - thatV6 = (os_sockaddr_in6*) thatSock; - result = (memcmp(&thisV6->sin6_addr.s6_addr, &thatV6->sin6_addr.s6_addr, sizeof(unsigned char) * 16) ? - false : true); - } -#endif + switch(sa->sa_family) { +#if OS_SOCKET_HAS_IPV6 + case AF_INET6: + port = ntohs(((os_sockaddr_in6 *)sa)->sin6_port); + break; +#endif /* OS_SOCKET_HAS_IPV6 */ + default: + assert(sa->sa_family == AF_INET); + port = ntohs(((os_sockaddr_in *)sa)->sin_port); + break; } - return result; + + return port; } -int -os_sockaddrIpAddressCompare(const os_sockaddr* addr1, - const os_sockaddr* addr2) +int os_sockaddr_compare(const os_sockaddr *sa1, const os_sockaddr *sa2) { - int result = -1; - uint16_t port1, port2; - int r; + int eq; + size_t sz; + assert(sa1 != 0); + assert(sa2 != 0); + + if ((eq = sa1->sa_family - sa2->sa_family) == 0) { + switch(sa1->sa_family) { #if (OS_SOCKET_HAS_IPV6 == 1) - os_sockaddr_in6 * thisV6, * thatV6; -#endif - - if (addr1->sa_family == addr2->sa_family) - { - if (addr1->sa_family == AF_INET) - { - /* IPv4 */ - if (((os_sockaddr_in*)addr1)->sin_addr.s_addr == - ((os_sockaddr_in*)addr2)->sin_addr.s_addr) { - port1 = os_sockaddrGetPort(addr1); - port2 = os_sockaddrGetPort(addr2); - if (port1 == port2) { - result = 0; - } else { - if (port1 > port2) { - result = 1; - } else { - result = -1; - } - } - } else { - if (((os_sockaddr_in*)addr1)->sin_addr.s_addr > - ((os_sockaddr_in*)addr2)->sin_addr.s_addr) { - result = 1; - } else { - result = -1; - } + case AF_INET6: + { + os_sockaddr_in6 *sin61, *sin62; + sin61 = (os_sockaddr_in6 *)sa1; + sin62 = (os_sockaddr_in6 *)sa2; + sz = sizeof(sin61->sin6_addr); + eq = memcmp(&sin61->sin6_addr, &sin62->sin6_addr, sz); } - } -#if (OS_SOCKET_HAS_IPV6 == 1) - else - { - /* IPv6 */ - thisV6 = (os_sockaddr_in6*) addr1; - thatV6 = (os_sockaddr_in6*) addr2; - r = memcmp(&thisV6->sin6_addr.s6_addr, &thatV6->sin6_addr.s6_addr, sizeof(unsigned char) * 16); - if (r == 0) { - port1 = os_sockaddrGetPort(addr1); - port2 = os_sockaddrGetPort(addr2); - if (port1 == port2) { - result = 0; - } else { - if (port1 > port2) { - result = 1; - } else { - result = -1; - } - } - } else { - if (r > 0) { - result = 1; - } else { - result = -1; - } + break; +#endif /* OS_SOCKET_HAS_IPV6 */ +#ifdef __linux + case AF_PACKET: + { + struct sockaddr_ll *sll1, *sll2; + sll1 = (struct sockaddr_ll *)sa1; + sll2 = (struct sockaddr_ll *)sa2; + sz = sizeof(sll1->sll_addr); + eq = memcmp(sll1->sll_addr, sll2->sll_addr, sz); } + break; +#endif /* __linux */ + default: + { + assert(sa1->sa_family == AF_INET); + os_sockaddr_in *sin1, *sin2; + sin1 = (os_sockaddr_in *)sa1; + sin2 = (os_sockaddr_in *)sa2; + sz = sizeof(sin1->sin_addr); + eq = memcmp(sin1, sin2, sizeof(*sin1)); + } + break; } -#endif } - return result; + + return eq; +} + +int os_sockaddr_is_unspecified(const os_sockaddr *const sa) +{ + int unspec = 0; + + assert(sa != NULL); + + if (sa->sa_family == AF_INET6) { + unspec = IN6_IS_ADDR_UNSPECIFIED(&((os_sockaddr_in6 *)sa)->sin6_addr); + } else if (sa->sa_family == AF_INET) { + unspec = (((os_sockaddr_in *)sa)->sin_addr.s_addr == 0); + } + + return unspec; } /** @@ -342,7 +280,7 @@ os_sockaddrIsLoopback(const os_sockaddr* thisSock) if (thisSock->sa_family == AF_INET6) { result = IN6_IS_ADDR_LOOPBACK(&((os_sockaddr_in6*)thisSock)->sin6_addr) || - os_sockaddrIPAddressEqual(thisSock, linkLocalLoopbackPtr) ? true : false; + os_sockaddr_compare(thisSock, linkLocalLoopbackPtr) == 0 ? true : false; } else #endif @@ -354,38 +292,6 @@ os_sockaddrIsLoopback(const os_sockaddr* thisSock) return result; } -size_t -os_sockaddrSizeof( - const os_sockaddr* sa) -{ - size_t result; - assert(sa); - switch(sa->sa_family){ -#if (OS_SOCKET_HAS_IPV6 == 1) - case AF_INET6: - result = sizeof(os_sockaddr_in6); - break; -#endif - case AF_INET: - result = sizeof(os_sockaddr_in); - break; - default: -#if (OS_SOCKET_HAS_IPV6 == 1) - OS_ERROR("os_sockaddrSizeof", 0, - "Unkown address family specified: %d. Should be AF_INET (%d) or AF_INET6 (%d)", - (int)sa->sa_family, AF_INET, AF_INET6); -#else - OS_ERROR("os_sockaddrSizeof", 0, - "Unkown address family specified: %d. Should be AF_INET (%d)", - (int)sa->sa_family, AF_INET); -#endif - result = 0; - break; - } - return result; -} - - void os_sockaddrSetInAddrAny( os_sockaddr* sa) @@ -406,54 +312,6 @@ os_sockaddrSetInAddrAny( } } - -void -os_sockaddrSetPort( - os_sockaddr* sa, - uint16_t port /* network byte order */) -{ - assert(sa); -#if (OS_SOCKET_HAS_IPV6 == 1) - assert(sa->sa_family == AF_INET6 || sa->sa_family == AF_INET); - if (sa->sa_family == AF_INET6) - { - ((os_sockaddr_in6*)sa)->sin6_port = port; - } - else -#else - assert(sa->sa_family == AF_INET); -#endif - if (sa->sa_family == AF_INET) - { - ((os_sockaddr_in*)sa)->sin_port = port; - } -} - -uint16_t /* network byte order */ -os_sockaddrGetPort( - const os_sockaddr* const sa) -{ - uint16_t port = 0; - assert(sa); -#if (OS_SOCKET_HAS_IPV6 == 1) - assert(sa->sa_family == AF_INET6 || sa->sa_family == AF_INET); - if (sa->sa_family == AF_INET6) - { - port = (uint16_t)((os_sockaddr_in6*)sa)->sin6_port; - } - else -#else - assert(sa->sa_family == AF_INET); -#endif - if (sa->sa_family == AF_INET) - { - port = (uint16_t)((os_sockaddr_in*)sa)->sin_port; - } - - return port; -} - - char* os_sockaddrAddressToString(const os_sockaddr* sa, char* buffer, size_t buflen) @@ -478,34 +336,3 @@ os_sockaddrAddressToString(const os_sockaddr* sa, return buffer; } - -char* -os_sockaddrAddressPortToString( - const os_sockaddr* sa, - char* buffer, - size_t buflen) -{ - size_t pos; - switch (sa->sa_family) - { - case AF_INET: - os_sockaddrAddressToString (sa, buffer, buflen); - pos = strlen (buffer); - (void) snprintf (buffer + pos, buflen - pos, ":%hu", ntohs (((os_sockaddr_in *) sa)->sin_port)); - break; -#if OS_SOCKET_HAS_IPV6 - case AF_INET6: - if(buflen){ - buffer[0] = '['; - os_sockaddrAddressToString (sa, buffer + 1, buflen - 1); - pos = strlen (buffer); - (void) snprintf (buffer + pos, buflen - pos, "]:%hu", ntohs (((os_sockaddr_in6 *) sa)->sin6_port)); - } - break; -#endif - default: - (void) snprintf(buffer, buflen, "Unknown address family"); - break; - } - return buffer; -} diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index ba820e0..2146b5d 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -12,57 +12,37 @@ #include #include -#if defined(__linux) -#include /* sockaddr_ll */ -#endif /* __linux */ - #include "os/os.h" static int -copy_ifaddrs(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) +copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) { int err = 0; os_ifaddrs_t *ifa; - size_t size; + ssize_t sz; assert(ifap != NULL); assert(sys_ifa != NULL); - assert(sys_ifa->ifa_addr->sa_family == AF_INET -#ifdef __linux - || sys_ifa->ifa_addr->sa_family == AF_PACKET -#endif /* __linux */ - || sys_ifa->ifa_addr->sa_family == AF_INET6); - ifa = os_malloc(sizeof(*ifa)); + sz = os_sockaddr_size(sys_ifa->ifa_addr); + ifa = os_calloc_s(1, 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); -#ifdef __linux - } else { - assert(sys_ifa->ifa_addr->sa_family == AF_PACKET); - size = sizeof(struct sockaddr_ll); -#endif /* __linux */ + if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, sz))) { + err = errno; } - - 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)))) + } else { + assert(sys_ifa->ifa_netmask != NULL); + if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, sz)) || + !(ifa->netmask = os_memdup(sys_ifa->ifa_netmask, sz)) || + ((sys_ifa->ifa_flags & IFF_BROADCAST) && + !(ifa->broadaddr = os_memdup(sys_ifa->ifa_broadaddr, sz)))) { err = errno; } @@ -81,15 +61,15 @@ copy_ifaddrs(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_opt_ const os_ifaddr_filter_t *ifltr) + _In_opt_ const int *const afs) { int err = 0; + int use; os_ifaddrs_t *ifa, *ifa_root, *ifa_next; struct ifaddrs *sys_ifa, *sys_ifa_root; - struct sockaddr *addr; + struct sockaddr *sa; assert(ifap != NULL); - assert(ifltr != NULL); if (getifaddrs(&sys_ifa_root) == -1) { err = errno; @@ -97,19 +77,17 @@ os_getifaddrs( ifa = ifa_root = NULL; for (sys_ifa = sys_ifa_root; - sys_ifa != NULL && err == 0; + sys_ifa != NULL && sys_ifa->ifa_addr != NULL && err == 0; sys_ifa = sys_ifa->ifa_next) { - addr = sys_ifa->ifa_addr; - if ((addr->sa_family == AF_INET && ifltr->af_inet) -#ifdef __linux - || (addr->sa_family == AF_PACKET && ifltr->af_packet) -#endif /* __linux */ - || (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); + sa = sys_ifa->ifa_addr; + use = (afs == NULL); + for (int i = 0; !use && afs[i] != 0; i++) { + use = (sa->sa_family == afs[i]); + } + + if (use) { + err = copyaddr(&ifa_next, sys_ifa); if (err == 0) { if (ifa == NULL) { ifa = ifa_root = ifa_next; diff --git a/src/os/src/snippets/code/os_stdlib_memdup.c b/src/os/src/snippets/code/os_stdlib_memdup.c index 37638da..e2abb47 100644 --- a/src/os/src/snippets/code/os_stdlib_memdup.c +++ b/src/os/src/snippets/code/os_stdlib_memdup.c @@ -12,11 +12,11 @@ #include "os/os.h" void * -os_memdup(void *src, size_t n) +os_memdup(const void *src, size_t n) { - void *dest; + void *dest = NULL; - if ((dest = os_malloc_s(n)) != NULL) { + if (n != 0 && (dest = os_malloc_s(n)) != NULL) { memcpy(dest, src, n); } diff --git a/src/os/src/snippets/code/os_stdlib_strdup.c b/src/os/src/snippets/code/os_stdlib_strdup.c index 3acc6d8..3145f2e 100644 --- a/src/os/src/snippets/code/os_stdlib_strdup.c +++ b/src/os/src/snippets/code/os_stdlib_strdup.c @@ -15,14 +15,9 @@ _Ret_z_ _Check_return_ char * os_strdup( - _In_z_ const char *s1) + _In_z_ const char *str) { - size_t len; - char *dup; + assert(str != NULL); - len = strlen(s1) + 1; - dup = os_malloc(len); - memcpy(dup, s1, len); - - return dup; + return os_memdup(str, strlen(str) + 1); } diff --git a/src/os/src/windows/os_platform_ifaddrs.c b/src/os/src/windows/os_platform_ifaddrs.c index 28c7127..44ec688 100644 --- a/src/os/src/windows/os_platform_ifaddrs.c +++ b/src/os/src/windows/os_platform_ifaddrs.c @@ -23,7 +23,7 @@ getifaces(PIP_ADAPTER_ADDRESSES *ptr) ULONG ret; size_t i; - static const size_t max = 3; + static const size_t max = 2; static const ULONG filter = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | @@ -207,9 +207,10 @@ copyaddr( _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_opt_ const os_ifaddr_filter_t *ifltr) + _In_opt_ const int *const afs) { int err = 0; + int use; PIP_ADAPTER_ADDRESSES ifaces = NULL, iface; PIP_ADAPTER_UNICAST_ADDRESS addr = NULL; PMIB_IPADDRTABLE addrtable = NULL; @@ -217,7 +218,6 @@ os_getifaddrs( struct sockaddr *sa; assert(ifap != NULL); - assert(ifltr != NULL); ifa = ifa_root = ifa_next = NULL; @@ -230,9 +230,12 @@ os_getifaddrs( 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)) - { + use = (afs == NULL); + for (int i = 0; !use && afs[i] != 0; i++) { + use = (afs[i] == sa->sa_family); + } + + if (use) { err = copyaddr(&ifa_next, iface, addrtable, addr); if (err == 0) { if (ifa == NULL) { diff --git a/src/os/src/windows/os_platform_socket.c b/src/os/src/windows/os_platform_socket.c index 1faa048..4d0f720 100644 --- a/src/os/src/windows/os_platform_socket.c +++ b/src/os/src/windows/os_platform_socket.c @@ -19,9 +19,6 @@ #include -#define WORKING_BUFFER_SIZE 15000 -#define MAX_TRIES 3 - typedef BOOL (WINAPI *qwaveQOSCreateHandleFuncT) (_In_ PQOS_VERSION Version, _Out_ PHANDLE QOSHandle); typedef BOOL (WINAPI *qwaveQOSCloseHandleFuncT) (_In_ HANDLE QOSHandle); typedef BOOL (WINAPI *qwaveQOSAddSocketToFlowFuncT) ( diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index c7a8d1a..3cddf83 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -36,9 +36,9 @@ CUnit_Test(os_getifaddrs, ipv4) int err; int seen = 0; os_ifaddrs_t *ifa_root, *ifa; - os_ifaddr_filter_t ifltr = { .af_inet = 1 }; + const int afs[] = { AF_INET, 0 }; - err = os_getifaddrs(&ifa_root, &ifltr); + err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET); @@ -62,9 +62,9 @@ CUnit_Test(os_getifaddrs, non_local_ipv6) { int err; os_ifaddrs_t *ifa_root, *ifa; - os_ifaddr_filter_t ifltr = { .af_inet6 = 1 }; + const int afs[] = { AF_INET6, 0 }; - err = os_getifaddrs(&ifa_root, &ifltr); + err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET6); diff --git a/src/os/tests/iter.c b/src/os/tests/iter.c old mode 100755 new mode 100644 diff --git a/src/os/tests/stdlib.c b/src/os/tests/stdlib.c old mode 100755 new mode 100644 From 03c081fa1898c3085aec00a2b7d8d0ded0df0820 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 19 Oct 2018 10:11:46 +0200 Subject: [PATCH 05/15] Simplify os_getifaddrs operation for POSIX platforms Signed-off-by: Jeroen Koekkoek --- src/os/src/posix/os_platform_ifaddrs.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index 2146b5d..63aeec8 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -19,7 +19,7 @@ copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) { int err = 0; os_ifaddrs_t *ifa; - ssize_t sz; + size_t sz; assert(ifap != NULL); assert(sys_ifa != NULL); @@ -31,21 +31,15 @@ copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) } else { ifa->index = if_nametoindex(sys_ifa->ifa_name); ifa->flags = sys_ifa->ifa_flags; - if ((ifa->name = os_strdup(sys_ifa->ifa_name)) == NULL) { + if ((ifa->name = os_strdup(sys_ifa->ifa_name)) == NULL || + (ifa->addr = os_memdup(sys_ifa->ifa_addr, sz)) == NULL || + (sys_ifa->ifa_netmask != NULL && + (ifa->netmask = os_memdup(sys_ifa->ifa_netmask, sz)) == NULL) || + (sys_ifa->ifa_broadaddr != NULL && + (sys_ifa->ifa_flags & IFF_BROADCAST) && + (ifa->broadaddr = os_memdup(sys_ifa->ifa_broadaddr, sz)) == NULL)) + { err = errno; - } else if (sys_ifa->ifa_addr->sa_family == AF_INET6) { - if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, sz))) { - err = errno; - } - } else { - assert(sys_ifa->ifa_netmask != NULL); - if (!(ifa->addr = os_memdup(sys_ifa->ifa_addr, sz)) || - !(ifa->netmask = os_memdup(sys_ifa->ifa_netmask, sz)) || - ((sys_ifa->ifa_flags & IFF_BROADCAST) && - !(ifa->broadaddr = os_memdup(sys_ifa->ifa_broadaddr, sz)))) - { - err = errno; - } } } From 6867f949cd781f4955eb2c32fb13b908237f1e76 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 19 Oct 2018 13:45:19 +0200 Subject: [PATCH 06/15] Add extra os_getifaddrs test cases Signed-off-by: Jeroen Koekkoek --- src/os/tests/ifaddrs.c | 62 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index 3cddf83..2282a5e 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -57,8 +57,38 @@ CUnit_Test(os_getifaddrs, ipv4) os_freeifaddrs(ifa_root); } +CUnit_Test(os_getifaddrs, null_filter) +{ + int err; + int cnt = 0; + os_ifaddrs_t *ifa_root, *ifa; + + err = os_getifaddrs(&ifa_root, NULL); + CU_ASSERT_EQUAL_FATAL(err, 0); + for (ifa = ifa_root; ifa; ifa = ifa->next) { + cnt++; + } + + CU_ASSERT(cnt > 0); + + os_freeifaddrs(ifa_root); +} + +CUnit_Test(os_getifaddrs, empty_filter) +{ + int err; + os_ifaddrs_t *ifa_root; + const int afs[] = { 0 }; + + err = os_getifaddrs(&ifa_root, afs); + CU_ASSERT_EQUAL_FATAL(err, 0); + CU_ASSERT_PTR_EQUAL(ifa_root, NULL); + + os_freeifaddrs(ifa_root); +} + #ifdef OS_SOCKET_HAS_IPV6 -CUnit_Test(os_getifaddrs, non_local_ipv6) +CUnit_Test(os_getifaddrs, ipv6) { int err; os_ifaddrs_t *ifa_root, *ifa; @@ -79,5 +109,33 @@ CUnit_Test(os_getifaddrs, non_local_ipv6) os_freeifaddrs(ifa_root); } -#endif /* OS_SOCKET_HAS_IPV6 */ +/* Assume at least one IPv4 and one IPv6 interface are available when IPv6 is + available on the platform. */ +CUnit_Test(os_getifaddrs, ipv4_n_ipv6) +{ + int err; + int have_ipv4 = 0; + int have_ipv6 = 0; + os_ifaddrs_t *ifa_root, *ifa; + const int afs[] = { AF_INET, AF_INET6, 0 }; + + err = os_getifaddrs(&ifa_root, afs); + CU_ASSERT_EQUAL_FATAL(err, 0); + for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT(ifa->addr->sa_family == AF_INET || + ifa->addr->sa_family == AF_INET6); + if (ifa->addr->sa_family == AF_INET) { + have_ipv4 = 1; + } else if (ifa->addr->sa_family == AF_INET6) { + have_ipv6 = 1; + } + } + + CU_ASSERT_EQUAL(have_ipv4, 1); + CU_ASSERT_EQUAL(have_ipv6, 1); + + os_freeifaddrs(ifa_root); +} + +#endif /* OS_SOCKET_HAS_IPV6 */ From 6b41dada9d15cd10f848af336d1df370ef10b364 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 19 Oct 2018 13:42:44 +0200 Subject: [PATCH 07/15] Fix compiler warnings Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/src/ddsi_eth.c | 1 - src/core/ddsi/src/ddsi_raweth.c | 1 - src/os/include/os/os_socket.h | 4 ++-- src/os/src/os_socket.c | 8 +++++--- src/os/src/snippets/code/os_stdlib_strcasecmp.c | 2 ++ src/os/tests/ifaddrs.c | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/ddsi_eth.c b/src/core/ddsi/src/ddsi_eth.c index f821832..af3eff1 100644 --- a/src/core/ddsi/src/ddsi_eth.c +++ b/src/core/ddsi/src/ddsi_eth.c @@ -13,7 +13,6 @@ int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, os_ifaddrs_t **ifs) { - int err; int afs[] = { AF_INET, 0 }; (void)fact; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index ddf6c90..87e9352 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -349,7 +349,6 @@ static void ddsi_raweth_deinit(void) static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { - int err = 0; int afs[] = { AF_PACKET, 0 }; (void)factory; diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index b378530..230279b 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -280,8 +280,8 @@ extern "C" { */ OSAPI_EXPORT int os_sockaddr_compare( - const os_sockaddr *sa1, - const os_sockaddr *sa2) __nonnull_all__ __attribute_pure__; + const os_sockaddr *const sa1, + const os_sockaddr *const sa2) __nonnull_all__ __attribute_pure__; /** * FIXME: comment diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 23f7de5..82b8988 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -46,7 +46,7 @@ const os_in6_addr os_in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } #endif size_t -os_sockaddr_size(const os_sockaddr *sa) +os_sockaddr_size(const os_sockaddr *const sa) { size_t sz; @@ -72,7 +72,7 @@ os_sockaddr_size(const os_sockaddr *sa) return sz; } -uint16_t os_sockaddr_get_port(const os_sockaddr *sa) +uint16_t os_sockaddr_get_port(const os_sockaddr *const sa) { unsigned short port = 0; @@ -91,7 +91,9 @@ uint16_t os_sockaddr_get_port(const os_sockaddr *sa) return port; } -int os_sockaddr_compare(const os_sockaddr *sa1, const os_sockaddr *sa2) +int os_sockaddr_compare( + const os_sockaddr *const sa1, + const os_sockaddr *const sa2) { int eq; size_t sz; diff --git a/src/os/src/snippets/code/os_stdlib_strcasecmp.c b/src/os/src/snippets/code/os_stdlib_strcasecmp.c index ae1e250..a784b8e 100644 --- a/src/os/src/snippets/code/os_stdlib_strcasecmp.c +++ b/src/os/src/snippets/code/os_stdlib_strcasecmp.c @@ -11,7 +11,9 @@ */ #include "os/os.h" +#ifdef _MSC_VER #pragma warning( default : 4996 ) +#endif /* _MSC_VER */ int os_strcasecmp( const char *s1, diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index 2282a5e..cff5188 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -28,7 +28,7 @@ CUnit_Suite_Cleanup(os_getifaddrs) return 0; } -/* Assume every test machine has at least one non-loopback IPv4 address. This +/* Assume every test machine has at least one IPv4 enabled interface. 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) From a9e160ec07dbbe317b7fc6804fe082e3089f8833 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 19 Oct 2018 17:17:51 +0200 Subject: [PATCH 08/15] Update API documentation for modified socket address functions Signed-off-by: Jeroen Koekkoek --- src/os/include/os/os_socket.h | 37 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index 230279b..5231798 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -250,33 +250,37 @@ extern "C" { #endif /* WIN32 */ /** - * Returns sizeof(sa) based on the family of the actual content. - * @param sa the sockaddr to get the actual size for - * @return The actual size sa based on the family. If the family is - * unknown 0 will be returned. - * @pre sa is a valid sockaddr pointer + * Returns size of socket address. + * @param sa Socket address to return the size for. + * @return Size of the socket address based on the address family, or 0 if + * the address family is unknown. + * @pre sa is a valid os_sockaddr pointer. */ OSAPI_EXPORT size_t os_sockaddr_size( const os_sockaddr *const sa) __nonnull_all__; /** - * Retrieves the port number from the supplied sockaddr. - * @param sa the sockaddr to retrieve the port from - * @return The port number stored in the supplied sockaddr convert to host order - * @pre sa is a valid sockaddr pointer + * Retrieve port number from the given socket address. + * @param sa Socket address to retrieve the port from. + * @return Port number in host order. + * @pre sa is a valid os_sockaddr pointer. */ OSAPI_EXPORT uint16_t os_sockaddr_get_port(const os_sockaddr *const sa) __nonnull_all__; /** - * Compare two socket IP host addresses for equality - does not consider the port number. - * This is a 'straight' equal i.e. family must match and address bytes - * must correspond. So it will not consider the possibility of IPv6 mapped + * Compare two IP addresses for equality - does not consider port number. + * This is a 'straight' compare i.e. family must match and address bytes + * must correspond. It does not consider the possibility of IPv6 mapped * IPv4 addresses or anything arcane like that. - * @param thisSock First address - * @param thatSock Second address. + * @param sa1 First socket address + * @param sa2 Second socket address. * @return true if equal, false otherwise. + * @return Integer less than, equal to, or greater than zero if sa1 is + * found, respectively, to be less than, to match, or be greater + * than sa2. + * @pre both sa1 and sa2 are valid os_sockaddr pointers. */ OSAPI_EXPORT int os_sockaddr_compare( @@ -284,7 +288,10 @@ extern "C" { const os_sockaddr *const sa2) __nonnull_all__ __attribute_pure__; /** - * FIXME: comment + * Check if IP address of given socket address is unspecified. + * @param sa Socket address + * @return true if unspecified, false otherwise. + * @pre sa is a valid os_sockaddr pointer. */ OSAPI_EXPORT int os_sockaddr_is_unspecified( From fbde1ba5b8dd77e526c8147ea14bc65ae2e26326 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 19 Oct 2018 17:50:13 +0200 Subject: [PATCH 09/15] Do not stop interface iteration if address is NULL Signed-off-by: Jeroen Koekkoek --- src/os/src/posix/os_platform_ifaddrs.c | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index 63aeec8..c31f69c 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -71,23 +71,25 @@ os_getifaddrs( ifa = ifa_root = NULL; for (sys_ifa = sys_ifa_root; - sys_ifa != NULL && sys_ifa->ifa_addr != NULL && err == 0; + sys_ifa != NULL && err == 0; sys_ifa = sys_ifa->ifa_next) { sa = sys_ifa->ifa_addr; - use = (afs == NULL); - for (int i = 0; !use && afs[i] != 0; i++) { - use = (sa->sa_family == afs[i]); - } + if (sa != NULL) { + use = (afs == NULL); + for (int i = 0; !use && afs[i] != 0; i++) { + use = (sa->sa_family == afs[i]); + } - if (use) { - err = copyaddr(&ifa_next, sys_ifa); - if (err == 0) { - if (ifa == NULL) { - ifa = ifa_root = ifa_next; - } else { - ifa->next = ifa_next; - ifa = ifa_next; + if (use) { + err = copyaddr(&ifa_next, sys_ifa); + if (err == 0) { + if (ifa == NULL) { + ifa = ifa_root = ifa_next; + } else { + ifa->next = ifa_next; + ifa = ifa_next; + } } } } From 0324f36dd253d84668370128460e4f229f062fb5 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 00:13:16 +0200 Subject: [PATCH 10/15] Disable IPv6 interface tests if IPv6 is not available at runtime Signed-off-by: Jeroen Koekkoek --- src/os/tests/ifaddrs.c | 113 ++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index cff5188..0e72065 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -16,9 +16,38 @@ on a given host. To properly test all combinations the abstracted operating system functions must be mocked. */ +/* FIXME: It's possible that IPv6 is available in the network stack, but + disabled in the kernel. Travis CI for example has build environments + that do not have IPv6 enabled. */ + +#ifdef OS_SOCKET_HAS_IPV6 +static int ipv6_enabled = 1; +#endif + CUnit_Suite_Initialize(os_getifaddrs) { os_osInit(); + +#ifdef OS_SOCKET_HAS_IPV6 +#ifdef __linux + FILE *fh; + const char *const *path; + static const char *const paths[] = { + "/proc/sys/net/ipv6/conf/all/disable_ipv6", + "/proc/sys/net/ipv6/conf/default/disable_ipv6", + NULL + }; + + for (path = paths; ipv6_enabled == 1 && *path != NULL; path++) { + if ((fh = fopen(*path, "r")) != NULL) { + ipv6_enabled = (fgetc(fh) == '0'); + fclose(fh); + fh = NULL; + } + } +#endif /* __linux */ +#endif /* OS_SOCKET_HAS_IPV6 */ + return 0; } @@ -90,52 +119,68 @@ CUnit_Test(os_getifaddrs, empty_filter) #ifdef OS_SOCKET_HAS_IPV6 CUnit_Test(os_getifaddrs, ipv6) { - int err; - os_ifaddrs_t *ifa_root, *ifa; - const int afs[] = { AF_INET6, 0 }; + if (ipv6_enabled == 1) { + int err; + int have_ipv6 = 0; + os_ifaddrs_t *ifa_root, *ifa; + const int afs[] = { AF_INET6, 0 }; - err = os_getifaddrs(&ifa_root, afs); - 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)); + err = os_getifaddrs(&ifa_root, afs); + 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) { + have_ipv6 = 1; + if (ifa->flags & IFF_LOOPBACK) { + CU_ASSERT(os_sockaddrIsLoopback(ifa->addr)); + } else { + CU_ASSERT(!os_sockaddrIsLoopback(ifa->addr)); + } } } - } - os_freeifaddrs(ifa_root); + CU_ASSERT_EQUAL(have_ipv6, 1); + + os_freeifaddrs(ifa_root); + + CU_PASS("IPv6 enabled in test environment"); + } else { + CU_PASS("IPv6 disabled in test environment"); + } } /* Assume at least one IPv4 and one IPv6 interface are available when IPv6 is available on the platform. */ CUnit_Test(os_getifaddrs, ipv4_n_ipv6) { - int err; - int have_ipv4 = 0; - int have_ipv6 = 0; - os_ifaddrs_t *ifa_root, *ifa; - const int afs[] = { AF_INET, AF_INET6, 0 }; + if (ipv6_enabled == 1) { + int err; + int have_ipv4 = 0; + int have_ipv6 = 0; + os_ifaddrs_t *ifa_root, *ifa; + const int afs[] = { AF_INET, AF_INET6, 0 }; - err = os_getifaddrs(&ifa_root, afs); - CU_ASSERT_EQUAL_FATAL(err, 0); - for (ifa = ifa_root; ifa; ifa = ifa->next) { - CU_ASSERT(ifa->addr->sa_family == AF_INET || - ifa->addr->sa_family == AF_INET6); - if (ifa->addr->sa_family == AF_INET) { - have_ipv4 = 1; - } else if (ifa->addr->sa_family == AF_INET6) { - have_ipv6 = 1; - } + err = os_getifaddrs(&ifa_root, afs); + CU_ASSERT_EQUAL_FATAL(err, 0); + for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT(ifa->addr->sa_family == AF_INET || + ifa->addr->sa_family == AF_INET6); + if (ifa->addr->sa_family == AF_INET) { + have_ipv4 = 1; + } else if (ifa->addr->sa_family == AF_INET6) { + have_ipv6 = 1; + } + } + + CU_ASSERT_EQUAL(have_ipv4, 1); + CU_ASSERT_EQUAL(have_ipv6, 1); + + os_freeifaddrs(ifa_root); + + CU_PASS("IPv6 enabled in test environment"); + } else { + CU_PASS("IPv6 disabled in test environment"); } - - CU_ASSERT_EQUAL(have_ipv4, 1); - CU_ASSERT_EQUAL(have_ipv6, 1); - - os_freeifaddrs(ifa_root); } #endif /* OS_SOCKET_HAS_IPV6 */ From 25198e565ba11ede5443be36a9ae351395e0db5a Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 15:48:45 +0200 Subject: [PATCH 11/15] Rename os_sockaddr_size to os_sockaddr_get_size for consitency Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/src/ddsi_tcp.c | 6 +++--- src/core/ddsi/src/ddsi_udp.c | 2 +- src/os/include/os/os_socket.h | 2 +- src/os/src/os_socket.c | 4 ++-- src/os/src/posix/os_platform_ifaddrs.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 6a57fb1..b2b1f9e 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -560,7 +560,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d memset(&msg, 0, sizeof(msg)); set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov); msg.msg_name = &dstaddr; - msg.msg_namelen = (socklen_t) os_sockaddr_size((os_sockaddr *) &dstaddr); + msg.msg_namelen = (socklen_t) os_sockaddr_get_size((os_sockaddr *) &dstaddr); #if SYSDEPS_MSGHDR_FLAGS msg.msg_flags = (int) flags; #endif @@ -867,7 +867,7 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket sock, bool server, os_sockad ddsi_tcp_base_init (&conn->m_base); os_mutexInit (&conn->m_mutex); conn->m_sock = Q_INVALID_SOCKET; - (void)memcpy(&conn->m_peer_addr, peer, os_sockaddr_size(peer)); + (void)memcpy(&conn->m_peer_addr, peer, os_sockaddr_get_size(peer)); conn->m_peer_port = os_sockaddr_get_port (peer); conn->m_base.m_server = server; conn->m_base.m_base.m_port = INVALID_PORT; @@ -1009,7 +1009,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) } do { - ret = connect (sock, (struct sockaddr *) &addr, (unsigned) os_sockaddr_size((os_sockaddr *)&addr)); + ret = connect (sock, (struct sockaddr *) &addr, (unsigned) os_sockaddr_get_size((os_sockaddr *)&addr)); } while ((ret == -1) && (os_getErrno() == os_sockEINTR)); if (ret == -1) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 62d8441..bf08a9c 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -121,7 +121,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d ddsi_ipaddr_from_loc(&dstaddr, dst); set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov); msg.msg_name = &dstaddr; - msg.msg_namelen = (socklen_t) os_sockaddr_size((os_sockaddr *) &dstaddr); + msg.msg_namelen = (socklen_t) os_sockaddr_get_size((os_sockaddr *) &dstaddr); #if !defined(__sun) || defined(_XPG4_2) msg.msg_control = NULL; msg.msg_controllen = 0; diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index 5231798..6f168b4 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -257,7 +257,7 @@ extern "C" { * @pre sa is a valid os_sockaddr pointer. */ OSAPI_EXPORT size_t - os_sockaddr_size( + os_sockaddr_get_size( const os_sockaddr *const sa) __nonnull_all__; /** diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 82b8988..528abad 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -46,14 +46,14 @@ const os_in6_addr os_in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } #endif size_t -os_sockaddr_size(const os_sockaddr *const sa) +os_sockaddr_get_size(const os_sockaddr *const sa) { size_t sz; assert(sa != NULL); switch(sa->sa_family) { -#if (OS_SOCKET_HAS_IPV6 == 1) +#if OS_SOCKET_HAS_IPV6 case AF_INET6: sz = sizeof(os_sockaddr_in6); break; diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index c31f69c..9413352 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -24,7 +24,7 @@ copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) assert(ifap != NULL); assert(sys_ifa != NULL); - sz = os_sockaddr_size(sys_ifa->ifa_addr); + sz = os_sockaddr_get_size(sys_ifa->ifa_addr); ifa = os_calloc_s(1, sizeof(*ifa)); if (ifa == NULL) { err = errno; From 961706bb486540aa5d1a69428df4ef3533fd5d85 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 16:31:43 +0200 Subject: [PATCH 12/15] Replace NULL address family filter by supported address families Signed-off-by: Jeroen Koekkoek --- src/os/include/os/os_socket.h | 2 +- src/os/src/os_socket.c | 12 ++++++++++++ src/os/src/posix/os_platform_ifaddrs.c | 10 ++++++++-- src/os/src/windows/os_platform_ifaddrs.c | 10 ++++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index 6f168b4..bc344a3 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -141,7 +141,7 @@ extern "C" { OSAPI_EXPORT _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_opt_ const int *const afs); + _In_opt_ const int *afs); /** * @brief Free os_ifaddrs_t structure list allocated by os_getifaddrs() diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 528abad..7d763f7 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -45,6 +45,18 @@ const os_in6_addr os_in6addr_loopback = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } #define OS_INET_PTON inet_pton #endif +const int afs[] = { +#ifdef __linux + AF_PACKET, +#endif /* __linux */ +#if OS_SOCKET_HAS_IPV6 + AF_INET6, +#endif /* OS_SOCKET_HAS_IPV6 */ + AF_INET +}; + +const int *const os_supp_afs = afs; + size_t os_sockaddr_get_size(const os_sockaddr *const sa) { diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index 9413352..d1252b9 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -14,6 +14,8 @@ #include "os/os.h" +extern const int *const os_supp_afs; + static int copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) { @@ -55,7 +57,7 @@ copyaddr(os_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa) _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_opt_ const int *const afs) + _In_opt_ const int *afs) { int err = 0; int use; @@ -65,6 +67,10 @@ os_getifaddrs( assert(ifap != NULL); + if (afs == NULL) { + afs = os_supp_afs; + } + if (getifaddrs(&sys_ifa_root) == -1) { err = errno; } else { @@ -76,7 +82,7 @@ os_getifaddrs( { sa = sys_ifa->ifa_addr; if (sa != NULL) { - use = (afs == NULL); + use = 0; for (int i = 0; !use && afs[i] != 0; i++) { use = (sa->sa_family == afs[i]); } diff --git a/src/os/src/windows/os_platform_ifaddrs.c b/src/os/src/windows/os_platform_ifaddrs.c index 44ec688..e901f01 100644 --- a/src/os/src/windows/os_platform_ifaddrs.c +++ b/src/os/src/windows/os_platform_ifaddrs.c @@ -14,6 +14,8 @@ #include "os/os.h" +extern const int *const os_supp_afs; + static int getifaces(PIP_ADAPTER_ADDRESSES *ptr) { @@ -207,7 +209,7 @@ copyaddr( _Success_(return == 0) int os_getifaddrs( _Inout_ os_ifaddrs_t **ifap, - _In_opt_ const int *const afs) + _In_opt_ const int *afs) { int err = 0; int use; @@ -219,6 +221,10 @@ os_getifaddrs( assert(ifap != NULL); + if (afs == NULL) { + afs = os_supp_afs; + } + ifa = ifa_root = ifa_next = NULL; if ((err = getifaces(&ifaces)) == 0 && @@ -230,7 +236,7 @@ os_getifaddrs( addr = addr->Next) { sa = (struct sockaddr *)addr->Address.lpSockaddr; - use = (afs == NULL); + use = 0; for (int i = 0; !use && afs[i] != 0; i++) { use = (afs[i] == sa->sa_family); } From 4b3c6ed6437cdc3c62e140c7006c774175b4ffee Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 16:53:12 +0200 Subject: [PATCH 13/15] Fix warning caused by assert on parameter required to be nonnull Signed-off-by: Jeroen Koekkoek --- src/os/src/os_socket.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 7d763f7..0a39d73 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -110,9 +110,6 @@ int os_sockaddr_compare( int eq; size_t sz; - assert(sa1 != 0); - assert(sa2 != 0); - if ((eq = sa1->sa_family - sa2->sa_family) == 0) { switch(sa1->sa_family) { #if (OS_SOCKET_HAS_IPV6 == 1) From 40b7b5f423dc23088e5772e64140af57db5d6b68 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 19:33:51 +0200 Subject: [PATCH 14/15] Copy socket address regardless of interface state Signed-off-by: Jeroen Koekkoek --- src/os/src/windows/os_platform_ifaddrs.c | 2 +- src/os/tests/ifaddrs.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/os/src/windows/os_platform_ifaddrs.c b/src/os/src/windows/os_platform_ifaddrs.c index e901f01..d4b1c76 100644 --- a/src/os/src/windows/os_platform_ifaddrs.c +++ b/src/os/src/windows/os_platform_ifaddrs.c @@ -161,7 +161,7 @@ copyaddr( if (ifa->name == NULL) { err = ENOMEM; - } else if (ifa->flags & IFF_UP) { + } else { ifa->addr = os_memdup(sa, addr->Address.iSockaddrLength); if (ifa->addr == NULL) { err = ENOMEM; diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index 0e72065..59b37a2 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -70,6 +70,7 @@ CUnit_Test(os_getifaddrs, ipv4) err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL); CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET); if (ifa->addr->sa_family == AF_INET) { if (ifa->flags & IFF_LOOPBACK) { @@ -95,6 +96,7 @@ CUnit_Test(os_getifaddrs, null_filter) err = os_getifaddrs(&ifa_root, NULL); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL); cnt++; } @@ -128,6 +130,7 @@ CUnit_Test(os_getifaddrs, ipv6) err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL); CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET6); if (ifa->addr->sa_family == AF_INET6) { have_ipv6 = 1; @@ -163,6 +166,7 @@ CUnit_Test(os_getifaddrs, ipv4_n_ipv6) err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); for (ifa = ifa_root; ifa; ifa = ifa->next) { + CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL); CU_ASSERT(ifa->addr->sa_family == AF_INET || ifa->addr->sa_family == AF_INET6); if (ifa->addr->sa_family == AF_INET) { From 8fc95353169b7c1c7755a91a1bfe7740a7d7ec28 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 24 Oct 2018 22:32:27 +0200 Subject: [PATCH 15/15] Terminate address filter with OS_AF_NULL instead of 0 (AF_UNSPEC) Signed-off-by: Jeroen Koekkoek --- src/core/ddsi/src/ddsi_eth.c | 2 +- src/core/ddsi/src/ddsi_raweth.c | 2 +- src/os/include/os/os_socket.h | 4 +++- src/os/src/os_socket.c | 3 ++- src/os/src/posix/os_platform_ifaddrs.c | 2 +- src/os/src/windows/os_platform_ifaddrs.c | 2 +- src/os/tests/ifaddrs.c | 8 ++++---- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/core/ddsi/src/ddsi_eth.c b/src/core/ddsi/src/ddsi_eth.c index af3eff1..45cb563 100644 --- a/src/core/ddsi/src/ddsi_eth.c +++ b/src/core/ddsi/src/ddsi_eth.c @@ -13,7 +13,7 @@ int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, os_ifaddrs_t **ifs) { - int afs[] = { AF_INET, 0 }; + int afs[] = { AF_INET, OS_AF_NULL }; (void)fact; diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index 87e9352..807664c 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -349,7 +349,7 @@ static void ddsi_raweth_deinit(void) static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, os_ifaddrs_t **interfs) { - int afs[] = { AF_PACKET, 0 }; + int afs[] = { AF_PACKET, OS_AF_NULL }; (void)factory; diff --git a/src/os/include/os/os_socket.h b/src/os/include/os/os_socket.h index bc344a3..511c1b4 100644 --- a/src/os/include/os/os_socket.h +++ b/src/os/include/os/os_socket.h @@ -110,6 +110,8 @@ extern "C" { #define SD_FLAG_IS_SET(flags, flag) ((((uint32_t)(flags) & (uint32_t)(flag))) != 0U) +#define OS_AF_NULL (-1) + /** Network interface attributes */ typedef struct os_ifaddrs_s { struct os_ifaddrs_s *next; @@ -134,7 +136,7 @@ extern "C" { * @param[in] afs NULL-terminated array of address families (AF_xyz) to * restrict resulting set of network interfaces too. NULL to * return all network interfaces for all supported address - * families. + * families. Terminate the array with OS_AF_NULL. * * @returns Returns zero on success or a valid errno value on error. */ diff --git a/src/os/src/os_socket.c b/src/os/src/os_socket.c index 0a39d73..5cb7b71 100644 --- a/src/os/src/os_socket.c +++ b/src/os/src/os_socket.c @@ -52,7 +52,8 @@ const int afs[] = { #if OS_SOCKET_HAS_IPV6 AF_INET6, #endif /* OS_SOCKET_HAS_IPV6 */ - AF_INET + AF_INET, + OS_AF_NULL /* Terminator */ }; const int *const os_supp_afs = afs; diff --git a/src/os/src/posix/os_platform_ifaddrs.c b/src/os/src/posix/os_platform_ifaddrs.c index d1252b9..2872888 100644 --- a/src/os/src/posix/os_platform_ifaddrs.c +++ b/src/os/src/posix/os_platform_ifaddrs.c @@ -83,7 +83,7 @@ os_getifaddrs( sa = sys_ifa->ifa_addr; if (sa != NULL) { use = 0; - for (int i = 0; !use && afs[i] != 0; i++) { + for (int i = 0; !use && afs[i] != OS_AF_NULL; i++) { use = (sa->sa_family == afs[i]); } diff --git a/src/os/src/windows/os_platform_ifaddrs.c b/src/os/src/windows/os_platform_ifaddrs.c index d4b1c76..fb24835 100644 --- a/src/os/src/windows/os_platform_ifaddrs.c +++ b/src/os/src/windows/os_platform_ifaddrs.c @@ -237,7 +237,7 @@ os_getifaddrs( { sa = (struct sockaddr *)addr->Address.lpSockaddr; use = 0; - for (int i = 0; !use && afs[i] != 0; i++) { + for (int i = 0; !use && afs[i] != OS_AF_NULL; i++) { use = (afs[i] == sa->sa_family); } diff --git a/src/os/tests/ifaddrs.c b/src/os/tests/ifaddrs.c index 59b37a2..2f3266f 100644 --- a/src/os/tests/ifaddrs.c +++ b/src/os/tests/ifaddrs.c @@ -65,7 +65,7 @@ CUnit_Test(os_getifaddrs, ipv4) int err; int seen = 0; os_ifaddrs_t *ifa_root, *ifa; - const int afs[] = { AF_INET, 0 }; + const int afs[] = { AF_INET, OS_AF_NULL }; err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); @@ -109,7 +109,7 @@ CUnit_Test(os_getifaddrs, empty_filter) { int err; os_ifaddrs_t *ifa_root; - const int afs[] = { 0 }; + const int afs[] = { OS_AF_NULL }; err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); @@ -125,7 +125,7 @@ CUnit_Test(os_getifaddrs, ipv6) int err; int have_ipv6 = 0; os_ifaddrs_t *ifa_root, *ifa; - const int afs[] = { AF_INET6, 0 }; + const int afs[] = { AF_INET6, OS_AF_NULL }; err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0); @@ -161,7 +161,7 @@ CUnit_Test(os_getifaddrs, ipv4_n_ipv6) int have_ipv4 = 0; int have_ipv6 = 0; os_ifaddrs_t *ifa_root, *ifa; - const int afs[] = { AF_INET, AF_INET6, 0 }; + const int afs[] = { AF_INET, AF_INET6, OS_AF_NULL }; err = os_getifaddrs(&ifa_root, afs); CU_ASSERT_EQUAL_FATAL(err, 0);