Unverified Commit 4bdb05df authored by Luca Boccassi's avatar Luca Boccassi Committed by GitHub

Merge pull request #3400 from sigiesec/fix-issue-3397

Add test for ZMQ_BINDTODEVICE
parents a3a40a01 9cb1fca1
......@@ -1075,8 +1075,9 @@ EXTRA_DIST = \
src/libzmq.vers \
src/version.rc.in \
tests/CMakeLists.txt \
tests/test_pair_tcp_cap_net_admin.cpp \
unittests/CMakeLists.txt \
tools/curve_keygen.cpp
tools/curve_keygen.cpp
MAINTAINERCLEANFILES = \
$(srcdir)/aclocal.m4 \
......
......@@ -227,20 +227,31 @@ int zmq::set_nosigpipe (fd_t s_)
return 0;
}
void zmq::bind_to_device (fd_t s_, const std::string &bound_device_)
int zmq::bind_to_device (fd_t s_, const std::string &bound_device_)
{
#ifdef ZMQ_HAVE_SO_BINDTODEVICE
int rc = setsockopt (s_, SOL_SOCKET, SO_BINDTODEVICE,
bound_device_.c_str (), bound_device_.length ());
#ifdef ZMQ_HAVE_WINDOWS
wsa_assert (rc != SOCKET_ERROR);
if (rc != SOCKET_ERROR)
return 0;
const int lastError = WSAGetLastError ();
errno = wsa_error_to_errno (lastError);
wsa_assert (lastError != WSAENOTSOCK);
return -1;
#else
errno_assert (rc == 0);
if (rc == 0)
return 0;
errno_assert (errno != ENOTSOCK);
return -1;
#endif
#else
LIBZMQ_UNUSED (s_);
LIBZMQ_UNUSED (bound_device_);
errno = ENOTSUP;
return -1;
#endif
}
......
......@@ -56,7 +56,7 @@ void set_ip_type_of_service (fd_t s_, int iptos_);
int set_nosigpipe (fd_t s_);
// Binds the underlying socket to the given device, eg. VRF or interface
void bind_to_device (fd_t s_, const std::string &bound_device_);
int bind_to_device (fd_t s_, const std::string &bound_device_);
// Initialize network subsystem. May be called multiple times. Each call must be matched by a call to shutdown_network.
bool initialize_network ();
......
......@@ -40,6 +40,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#ifdef ZMQ_HAVE_VXWORKS
#include <sockLib.h>
#endif
......@@ -427,7 +428,8 @@ zmq::fd_t zmq::tcp_open_socket (const char *address_,
// Bind the socket to a device if applicable
if (!options_.bound_device.empty ())
bind_to_device (s, options_.bound_device);
if (bind_to_device (s, options_.bound_device) == -1)
goto setsockopt_error;
// Set the socket buffer limits for the underlying socket.
if (options_.sndbuf >= 0)
......@@ -436,4 +438,14 @@ zmq::fd_t zmq::tcp_open_socket (const char *address_,
set_tcp_receive_buffer (s, options_.rcvbuf);
return s;
setsockopt_error:
#ifdef ZMQ_HAVE_WINDOWS
rc = closesocket (s);
wsa_assert (rc != SOCKET_ERROR);
#else
rc = ::close (s);
errno_assert (rc == 0);
#endif
return retired_fd;
}
......@@ -79,6 +79,16 @@ if(ZMQ_HAVE_CURVE)
test_security_curve)
endif()
find_program(CAPSH_PROGRAM NAMES capsh)
if (CAPSH_PROGRAM)
list(APPEND tests
test_pair_tcp_cap_net_admin
)
else()
message(STATUS "capsh not found, skipping tests that require CAP_NET_ADMIN")
endif()
if(NOT WIN32)
list(APPEND tests
test_ipc_wildcard
......@@ -208,7 +218,11 @@ foreach(test ${tests})
if(WIN32)
add_test(NAME ${test} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} COMMAND ${test})
else()
add_test(NAME ${test} COMMAND ${test})
if (${test} MATCHES "_cap_net_admin")
add_test(NAME ${test} COMMAND sh -c "sudo ${CAPSH_PROGRAM} --caps=cap_net_admin+eip -- -c $<TARGET_FILE:${test}>")
else()
add_test(NAME ${test} COMMAND ${test})
endif()
endif()
set_tests_properties(${test} PROPERTIES TIMEOUT 10)
set_tests_properties(${test} PROPERTIES SKIP_RETURN_CODE 77)
......
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
typedef void (*extra_func_t) (void *socket_);
void set_sockopt_bind_to_device (void *socket)
{
const char device[] = "lo";
int rc =
zmq_setsockopt (socket, ZMQ_BINDTODEVICE, &device, sizeof (device) - 1);
assert (rc == 0);
}
// TODO this is duplicated from test_pair_tcp
void test_pair_tcp (extra_func_t extra_func_ = NULL)
{
void *sb = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sb);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_pair_tcp_bind_to_device ()
{
test_pair_tcp (set_sockopt_bind_to_device);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_pair_tcp_bind_to_device);
return UNITY_END ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment