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

Add test for ZMQ_BINDTODEVICE
This commit is contained in:
Luca Boccassi 2019-02-07 14:53:48 +00:00 committed by GitHub
commit 4bdb05df78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 7 deletions

View File

@ -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 \

View File

@ -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
}

View File

@ -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 ();

View File

@ -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;
}

View File

@ -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)

View File

@ -0,0 +1,89 @@
/*
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 ();
}