Skip to content

Commit

Permalink
fixes #1496 Provide NNG_ENABLE_IPV6 option (disabled by default)
Browse files Browse the repository at this point in the history
This also checks if the build system has the definitions for AF_INET6, which might
help in some embedded IPv4 only settings.

The resolver test is enhanced to include a check for IPv6 enabled in the kernel.

IPv6 support is enabled by default, of course.
  • Loading branch information
gdamore committed Feb 26, 2024
1 parent 8e62028 commit e6baa17
Show file tree
Hide file tree
Showing 17 changed files with 347 additions and 186 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ endif ()

nng_defines_if(NNG_ENABLE_STATS NNG_ENABLE_STATS)

# IPv6 enable
nng_defines_if(NNG_ENABLE_IPV6 NNG_ENABLE_IPV6)

set(NNG_RESOLV_CONCURRENCY 4 CACHE STRING "Resolver (DNS) concurrency.")
mark_as_advanced(NNG_RESOLV_CONCURRENCY)
if (NNG_RESOLV_CONCURRENCY)
Expand Down
5 changes: 5 additions & 0 deletions cmake/NNGOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ if (NNG_ENABLE_HTTP)
endif()
mark_as_advanced(NNG_ENABLE_HTTP)

# Some sites or kernels lack IPv6 support. This override allows us
# to prevent the use of IPv6 in environments where it isn't supported.
option (NNG_ENABLE_IPV6 "Enable IPv6." ON)
mark_as_advanced(NNG_ENABLE_IPV6)

#
# Transport Options.
#
Expand Down
12 changes: 9 additions & 3 deletions src/core/stream.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
Expand All @@ -22,8 +22,8 @@

static struct {
const char *scheme;
int (*dialer_alloc)(nng_stream_dialer **, const nng_url *);
int (*listener_alloc)(nng_stream_listener **, const nng_url *);
int (*dialer_alloc)(nng_stream_dialer **, const nng_url *);
int (*listener_alloc)(nng_stream_listener **, const nng_url *);

} stream_drivers[] = {
{
Expand Down Expand Up @@ -55,11 +55,13 @@ static struct {
.dialer_alloc = nni_tcp_dialer_alloc,
.listener_alloc = nni_tcp_listener_alloc,
},
#ifdef NNG_ENABLE_IPV6
{
.scheme = "tcp6",
.dialer_alloc = nni_tcp_dialer_alloc,
.listener_alloc = nni_tcp_listener_alloc,
},
#endif
{
.scheme = "tls+tcp",
.dialer_alloc = nni_tls_dialer_alloc,
Expand All @@ -70,11 +72,13 @@ static struct {
.dialer_alloc = nni_tls_dialer_alloc,
.listener_alloc = nni_tls_listener_alloc,
},
#ifdef NNG_ENABLE_IPV6
{
.scheme = "tls+tcp6",
.dialer_alloc = nni_tls_dialer_alloc,
.listener_alloc = nni_tls_listener_alloc,
},
#endif
{
.scheme = "ws",
.dialer_alloc = nni_ws_dialer_alloc,
Expand All @@ -85,11 +89,13 @@ static struct {
.dialer_alloc = nni_ws_dialer_alloc,
.listener_alloc = nni_ws_listener_alloc,
},
#ifdef NNG_ENABLE_IPV6
{
.scheme = "ws6",
.dialer_alloc = nni_ws_dialer_alloc,
.listener_alloc = nni_ws_listener_alloc,
},
#endif
{
.scheme = "wss",
.dialer_alloc = nni_ws_dialer_alloc,
Expand Down
1 change: 1 addition & 0 deletions src/platform/posix/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ if (NNG_PLATFORM_POSIX)
nng_check_sym(getpeerucred ucred.h NNG_HAVE_GETPEERUCRED)
nng_check_sym(atomic_flag_test_and_set stdatomic.h NNG_HAVE_STDATOMIC)
nng_check_sym(socketpair sys/socket.h NNG_HAVE_SOCKETPAIR)
nng_check_sym(AF_INET6 netinet/in.h NNG_HAVE_INET6)

nng_sources(
posix_impl.h
Expand Down
49 changes: 42 additions & 7 deletions src/platform/posix/posix_resolv_gai.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#define AI_NUMERICSERV 0
#endif

#ifndef NNG_HAVE_INET6
#undef NNG_ENABLE_IPV6
#endif

static nni_mtx resolv_mtx = NNI_MTX_INITIALIZER;
static nni_cv resolv_cv = NNI_CV_INITIALIZER(&resolv_mtx);
static bool resolv_fini = false;
Expand Down Expand Up @@ -182,17 +186,23 @@ resolv_task(resolv_item *item)

rv = NNG_EADDRINVAL;
for (probe = results; probe != NULL; probe = probe->ai_next) {
if ((probe->ai_addr->sa_family == AF_INET) ||
(probe->ai_addr->sa_family == AF_INET6)) {
if (probe->ai_addr->sa_family == AF_INET) {
break;
}
#ifdef NNG_ENABLE_IPV6
if (probe->ai_addr->sa_family == AF_INET6) {
break;
}
#endif
}

nni_mtx_lock(&resolv_mtx);
if ((probe != NULL) && (item->aio != NULL)) {
struct sockaddr_in *sin;
struct sockaddr_in *sin;
#ifdef NNG_ENABLE_IPV6
struct sockaddr_in6 *sin6;
nng_sockaddr *sa = item->sa;
#endif
nng_sockaddr *sa = item->sa;

switch (probe->ai_addr->sa_family) {
case AF_INET:
Expand All @@ -202,6 +212,7 @@ resolv_task(resolv_item *item)
sa->s_in.sa_port = sin->sin_port;
sa->s_in.sa_addr = sin->sin_addr.s_addr;
break;
#ifdef NNG_ENABLE_IPV6
case AF_INET6:
rv = 0;
sin6 = (void *) probe->ai_addr;
Expand All @@ -210,6 +221,7 @@ resolv_task(resolv_item *item)
sa->s_in6.sa_scope = sin6->sin6_scope_id;
memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16);
break;
#endif
}
}
nni_mtx_unlock(&resolv_mtx);
Expand Down Expand Up @@ -238,12 +250,20 @@ nni_resolv_ip(const char *host, const char *serv, int af, bool passive,
case NNG_AF_INET:
fam = AF_INET;
break;

#ifdef NNG_ENABLE_IPV6
case NNG_AF_INET6:
fam = AF_INET6;
break;
case NNG_AF_UNSPEC:
fam = AF_UNSPEC;
break;
#else
case NNG_AF_UNSPEC:
fam = AF_INET;
break;
#endif

default:
nni_aio_finish_error(aio, NNG_ENOTSUP);
return;
Expand Down Expand Up @@ -342,13 +362,17 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port)
struct addrinfo hints;
struct addrinfo *results;
int rv;
bool v6 = false;
bool wrapped = false;
char *port;
char *host;
char *buf;
size_t buf_len;

#ifdef NNG_ENABLE_IPV6
bool v6 = false;
bool wrapped = false;
char *s;
#endif

if (addr == NULL) {
addr = "";
}
Expand All @@ -359,12 +383,12 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port)
}
memcpy(buf, addr, buf_len);
host = buf;
#ifdef NNG_ENABLE_IPV6
if (*host == '[') {
v6 = true;
wrapped = true;
host++;
} else {
char *s;
for (s = host; *s != '\0'; s++) {
if (*s == '.') {
break;
Expand Down Expand Up @@ -394,6 +418,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port)
rv = NNG_EADDRINVAL;
goto done;
}
#else // NNG_ENABLE_IPV6
for (port = host; *port != '\0'; port++) {
if (*port == ':') {
break;
}
}
#endif // NNG_ENABLE_IPV6

if ((!want_port) && (*port != '\0')) {
rv = NNG_EADDRINVAL;
Expand All @@ -408,9 +439,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port)

memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE;
#ifdef NNG_ENABLE_IPV6
if (v6) {
hints.ai_family = AF_INET6;
}
#else
hints.ai_family = AF_INET;
#endif
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif
Expand Down
48 changes: 31 additions & 17 deletions src/platform/posix/posix_sockaddr.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
Expand All @@ -22,17 +22,23 @@
#include <sys/types.h>
#include <sys/un.h>

#ifndef NNG_HAVE_INET6
#undef NNG_ENABLE_IPV6
#endif

size_t
nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na)
{
struct sockaddr_in * sin;
struct sockaddr_in6 * sin6;
struct sockaddr_un * spath;
const nng_sockaddr_in * nsin;
const nng_sockaddr_in6 * nsin6;
const nng_sockaddr_path * nspath;
struct sockaddr_in *sin;
struct sockaddr_un *spath;
const nng_sockaddr_in *nsin;
const nng_sockaddr_path *nspath;
const nng_sockaddr_abstract *nsabs;
size_t sz;
#ifdef NNG_ENABLE_IPV6
struct sockaddr_in6 *sin6;
const nng_sockaddr_in6 *nsin6;
#endif

if ((sa == NULL) || (na == NULL)) {
return (0);
Expand All @@ -47,6 +53,7 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na)
sin->sin_addr.s_addr = nsin->sa_addr;
return (sizeof(*sin));

#ifdef NNG_ENABLE_IPV6
case NNG_AF_INET6:
sin6 = (void *) sa;
nsin6 = &na->s_in6;
Expand All @@ -59,6 +66,7 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na)
sin6->sin6_scope_id = nsin6->sa_scope;
memcpy(sin6->sin6_addr.s6_addr, nsin6->sa_addr, 16);
return (sizeof(*sin6));
#endif

case NNG_AF_IPC:
spath = (void *) sa;
Expand All @@ -75,18 +83,18 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na)
case NNG_AF_ABSTRACT:
spath = (void *) sa;
nsabs = &na->s_abstract;
if (nsabs->sa_len >= sizeof (spath->sun_path)) {
if (nsabs->sa_len >= sizeof(spath->sun_path)) {
return (0);
}
memset(spath, 0, sizeof(*spath));
spath->sun_family = PF_UNIX;
spath->sun_family = PF_UNIX;
spath->sun_path[0] = '\0'; // abstract starts with nul

// We support auto-bind with an empty string. There is
// a subtle caveat here, which is that we cannot bind to
// the *empty* name.
if (nsabs->sa_len == 0) {
return (sizeof (sa_family_t)); // auto bind
return (sizeof(sa_family_t)); // auto bind
} else {
memcpy(&spath->sun_path[1], nsabs->sa_name,
nsabs->sa_len);
Expand All @@ -99,13 +107,15 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na)
int
nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz)
{
const struct sockaddr_in * sin;
const struct sockaddr_in *sin;
const struct sockaddr_un *spath;
nng_sockaddr_in *nsin;
nng_sockaddr_path *nspath;
nng_sockaddr_abstract *nsabs;
#ifdef NNG_ENABLE_IPV6
const struct sockaddr_in6 *sin6;
const struct sockaddr_un * spath;
nng_sockaddr_in * nsin;
nng_sockaddr_in6 * nsin6;
nng_sockaddr_path * nspath;
nng_sockaddr_abstract * nsabs;
nng_sockaddr_in6 *nsin6;
#endif

if ((na == NULL) || (sa == NULL)) {
return (-1);
Expand All @@ -121,6 +131,8 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz)
nsin->sa_port = sin->sin_port;
nsin->sa_addr = sin->sin_addr.s_addr;
break;

#ifdef NNG_ENABLE_IPV6
case AF_INET6:
if (sz < sizeof(*sin6)) {
return (-1);
Expand All @@ -132,6 +144,8 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz)
nsin6->sa_scope = sin6->sin6_scope_id;
memcpy(nsin6->sa_addr, sin6->sin6_addr.s6_addr, 16);
break;
#endif

case AF_UNIX:
// AF_UNIX can be NNG_AF_IPC, or NNG_AF_ABSTRACT.
spath = (void *) sa;
Expand All @@ -153,7 +167,7 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz)
nsabs->sa_len = sz - 1;
memcpy(nsabs->sa_name, &spath->sun_path[1], sz - 1);
} else {
nspath = &na->s_ipc;
nspath = &na->s_ipc;
nspath->sa_family = NNG_AF_IPC;
nni_strlcpy(nspath->sa_path, spath->sun_path,
sizeof(nspath->sa_path));
Expand Down
Loading

0 comments on commit e6baa17

Please sign in to comment.