Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ include(GNUInstallDirs)
include(CheckFunctionExists)
include(CheckCSourceCompiles)
include(CheckIncludeFile)
include(CheckSymbolExists)
include(UseCompat)
include(ABICheck)
include(SourceFormat)
Expand Down Expand Up @@ -94,6 +95,7 @@ option(ENABLE_SSH_TLS "Enable NETCONF over SSH and TLS support (via libssh and O
option(ENABLE_DNSSEC "Enable support for SSHFP retrieval using DNSSEC for SSH (requires OpenSSL and libval)" OFF)
option(ENABLE_PAM "Detect and use PAM" ON)
option(ENABLE_COMMON_TARGETS "Define common custom target names such as 'doc' or 'uninstall', may cause conflicts when using add_subdirectory() to build this project" ON)
option(ENABLE_IP_FREEBIND "Enable the IP_FREEBIND/IPV6_FREEBIND options on the listening TCP socket" OFF)
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
set(READ_INACTIVE_TIMEOUT 20 CACHE STRING "Maximum number of seconds waiting for new data once some data have arrived")
set(READ_ACTIVE_TIMEOUT 300 CACHE STRING "Maximum number of seconds for receiving a full message")
Expand Down Expand Up @@ -128,6 +130,10 @@ if(ENABLE_SSH_TLS)
set(SSH_TLS_MACRO "#ifndef NC_ENABLED_SSH_TLS\n#define NC_ENABLED_SSH_TLS\n#endif")
endif()

if(ENABLE_IP_FREEBIND)
check_symbol_exists(IP_FREEBIND "netinet/in.h" NC_ENABLE_IP_FREEBIND)
endif()

set(headers
src/log.h
src/netconf.h
Expand Down
3 changes: 3 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@
/* Portability feature-check macros. */
#cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP

/* Enable IP_FREEBIND/IPV6_FREEBIND on listening sockets. */
#cmakedefine NC_ENABLE_IP_FREEBIND

#endif /* NC_CONFIG_H_ */
20 changes: 20 additions & 0 deletions src/session_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ nc_sock_bind_inet(int sock, const char *address, uint16_t port, int is_ipv4)
struct sockaddr_in *saddr4;
struct sockaddr_in6 *saddr6;

#ifdef NC_ENABLE_IP_FREEBIND
Comment thread
michalvasko marked this conversation as resolved.
int opt;
#endif

memset(&saddr, 0, sizeof(struct sockaddr_storage));

if (is_ipv4) {
Expand All @@ -307,6 +311,14 @@ nc_sock_bind_inet(int sock, const char *address, uint16_t port, int is_ipv4)
return -1;
}

#ifdef NC_ENABLE_IP_FREEBIND
opt = 1;
if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &opt, sizeof(opt))) {
ERR(NULL, "Could not add IP_FREEBIND option (%s).", strerror(errno));
return -1;
}
#endif

if (bind(sock, (struct sockaddr *)saddr4, sizeof(struct sockaddr_in)) == -1) {
ERR(NULL, "Could not bind %s:%" PRIu16 " (%s).", address, port, strerror(errno));
return -1;
Expand All @@ -328,6 +340,14 @@ nc_sock_bind_inet(int sock, const char *address, uint16_t port, int is_ipv4)
return -1;
}

#ifdef NC_ENABLE_IP_FREEBIND
opt = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_FREEBIND, &opt, sizeof(opt))) {
ERR(NULL, "Could not add IPV6_FREEBIND option (%s).", strerror(errno));
return -1;
}
#endif

if (bind(sock, (struct sockaddr *)saddr6, sizeof(struct sockaddr_in6)) == -1) {
ERR(NULL, "Could not bind [%s]:%" PRIu16 " (%s).", address, port, strerror(errno));
return -1;
Expand Down