[SCM] Socket Wrapper Repository - branch master updated
Michael Adam
obnox at samba.org
Sun Jun 1 02:06:09 MDT 2014
The branch, master has been updated
via 9e91b00 tests: add new test test_bind_ipv4_addr_in_use()
via 0c3efeb tests: extend the ipv6 bind test
via a14a1af tests: greatly extend the ipv4 bind test
via f38c0b4 swrap: check whether an address:port is already in use in swrap_bind()
via da04f94 swrap: implement check_addr_port_in_use()
via f04ea32 swrap: fix AF_UNSPEC special case in swrap_bind()
via 97a65a1 swrap: extend input checks in swrap_bind()
via af40930 Update the todo list.
via b357525 tests: Avoid using getenv() to retrieve the path.
via 3029067 swrap: add check for rpc/rpc.h - needed on freebsd for bindresvport
via 0025857 tests: Add tests for bindresvport().
via ccf4e64 swrap: Add support for bindresvport().
via b124fcb tests: Add tests for bind().
via 45eb7c9 swrap: Add missing family check in bind().
via 37b472d tests: Add test that getsockname is correct after socket().
via bdbbf38 swrap: Setup myname in swrap_socket() for getsockname().
via 205d5c2 torture: Wait for the pidfile and then start the tests.
via 323feb7 echo_srv: Write pidfile after we setup the listeners.
from 1dbbd72 README.install: improvements and fixes.
http://gitweb.samba.org/?p=socket_wrapper.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 9e91b00ee329578987c579b2c9d6db967055a59a
Author: Michael Adam <obnox at samba.org>
Date: Sat May 31 03:35:22 2014 +0200
tests: add new test test_bind_ipv4_addr_in_use()
This tests binding an address that is already in use.
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit 0c3efeb3b07083e36068e354b20208316d02c79a
Author: Michael Adam <obnox at samba.org>
Date: Sat May 31 03:31:56 2014 +0200
tests: extend the ipv6 bind test
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit a14a1afe966a45000fa768df43a25d84a68772dd
Author: Michael Adam <obnox at samba.org>
Date: Sat May 31 03:31:29 2014 +0200
tests: greatly extend the ipv4 bind test
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit f38c0b43d5620ab6457bf8a4fbdaf3a7bf90627c
Author: Michael Adam <obnox at samba.org>
Date: Fri May 30 14:20:40 2014 +0200
swrap: check whether an address:port is already in use in swrap_bind()
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit da04f94dd0575245424cf7853d0a9fc5b7caacee
Author: Michael Adam <obnox at samba.org>
Date: Fri May 30 14:20:17 2014 +0200
swrap: implement check_addr_port_in_use()
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit f04ea324f6079e74532ee1ae085945097073a305
Author: Michael Adam <obnox at samba.org>
Date: Fri May 30 13:21:00 2014 +0200
swrap: fix AF_UNSPEC special case in swrap_bind()
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit 97a65a132d1b14cbfd539f327f260237c1afff3d
Author: Michael Adam <obnox at samba.org>
Date: Fri May 30 13:06:02 2014 +0200
swrap: extend input checks in swrap_bind()
Not only check family, but depending on family, also check the length.
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit af40930bebe0322d5876bda2aa36598e1bae2056
Author: Andreas Schneider <asn at samba.org>
Date: Wed May 28 10:04:04 2014 +0200
Update the todo list.
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit b357525a2958e394fceb8c7b6165b572e944e8f2
Author: Andreas Schneider <asn at samba.org>
Date: Wed May 28 09:46:57 2014 +0200
tests: Avoid using getenv() to retrieve the path.
CID 17221
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 3029067b21775c1f6fec43e0b03712defa69e9a6
Author: Michael Adam <obnox at samba.org>
Date: Sun Jun 1 01:48:15 2014 +0200
swrap: add check for rpc/rpc.h - needed on freebsd for bindresvport
Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
commit 00258577e86f4b6c15d504954ee6233086638a3e
Author: Andreas Schneider <asn at samba.org>
Date: Wed May 28 09:46:40 2014 +0200
tests: Add tests for bindresvport().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit ccf4e64fe7bf788c17ca1a41e456e3b9ecdcb85b
Author: Andreas Schneider <asn at samba.org>
Date: Tue May 20 20:04:02 2014 +0200
swrap: Add support for bindresvport().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit b124fcb2dfb6193f198bd47891c3286e527bd530
Author: Andreas Schneider <asn at samba.org>
Date: Wed May 21 09:15:10 2014 +0200
tests: Add tests for bind().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 45eb7c9070fdd99b63fe01d31e26616d8f047f71
Author: Andreas Schneider <asn at samba.org>
Date: Wed May 21 08:30:53 2014 +0200
swrap: Add missing family check in bind().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 37b472d7972f0d18bd343137d4991f5e091a2ed7
Author: Andreas Schneider <asn at samba.org>
Date: Tue May 27 20:53:51 2014 +0200
tests: Add test that getsockname is correct after socket().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit bdbbf3853c644da05e1fd74c523380a846394cec
Author: Andreas Schneider <asn at samba.org>
Date: Tue May 27 20:43:51 2014 +0200
swrap: Setup myname in swrap_socket() for getsockname().
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 205d5c2348a5ae4858c2fe07a8b3080b19c900be
Author: Andreas Schneider <asn at samba.org>
Date: Fri May 30 13:59:43 2014 +0200
torture: Wait for the pidfile and then start the tests.
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 323feb7398527294d1102e24470c0761b1661d99
Author: Andreas Schneider <asn at samba.org>
Date: Fri May 30 13:57:25 2014 +0200
echo_srv: Write pidfile after we setup the listeners.
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
-----------------------------------------------------------------------
Summary of changes:
ConfigureChecks.cmake | 5 +
TODO | 7 +-
config.h.cmake | 2 +
src/socket_wrapper.c | 287 ++++++++++++++++++++++++
tests/CMakeLists.txt | 2 +
tests/echo_srv.c | 20 +-
tests/test_echo_tcp_bind.c | 494 ++++++++++++++++++++++++++++++++++++++++++
tests/test_echo_tcp_socket.c | 69 ++++++
tests/test_ioctl.c | 14 +-
tests/torture.c | 14 +-
10 files changed, 896 insertions(+), 18 deletions(-)
create mode 100644 tests/test_echo_tcp_bind.c
create mode 100644 tests/test_echo_tcp_socket.c
Changeset truncated at 500 lines:
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 3a31f50..df65411 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -52,6 +52,7 @@ check_include_file(sys/signalfd.h HAVE_SYS_SIGNALFD_H)
check_include_file(sys/eventfd.h HAVE_SYS_EVENTFD_H)
check_include_file(sys/timerfd.h HAVE_SYS_TIMERFD_H)
check_include_file(gnu/lib-names.h HAVE_GNU_LIB_NAMES_H)
+check_include_file(rpc/rpc.h HAVE_RPC_RPC_H)
# FUNCTIONS
check_function_exists(strncpy HAVE_STRNCPY)
@@ -60,6 +61,10 @@ check_function_exists(snprintf HAVE_SNPRINTF)
check_function_exists(signalfd HAVE_SIGNALFD)
check_function_exists(eventfd HAVE_EVENTFD)
check_function_exists(timerfd_create HAVE_TIMERFD_CREATE)
+set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE)
+check_function_exists(bindresvport HAVE_BINDRESVPORT)
+set(CMAKE_REQUIRED_FLAGS)
+
if (UNIX)
if (NOT LINUX)
diff --git a/TODO b/TODO
index 205cfaf..fe05c75 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,14 @@
TODO
=====
+This is the TODO list of this project. It should give you some hints of things
+which need to be implemented. If you can spend some time on this project, then
+look at the list below.
+
+
Library:
---------
-* Add IP_PKTINFO support for sendmsg/recvmsg.
* Add support for fd passing in sendmsg/recvmsg.
Scenario:
We accept a connection from a client and need to pass the fd to another
@@ -12,6 +16,7 @@ Library:
to the child first and set it up there.
Or do it like swrap_accept() and call getpeername() and getsockname().
* Add support for threading.
+* Use realpath() in socket_wrapper_dir().
Testing:
---------
diff --git a/config.h.cmake b/config.h.cmake
index 02c016e..466b951 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -19,6 +19,7 @@
#cmakedefine HAVE_SYS_EVENTFD_H 1
#cmakedefine HAVE_SYS_TIMERFD_H 1
#cmakedefine HAVE_GNU_LIB_NAMES_H 1
+#cmakedefine HAVE_RPC_RPC_H 1
/**************************** STRUCTS ****************************/
@@ -37,6 +38,7 @@
#cmakedefine HAVE_SIGNALFD 1
#cmakedefine HAVE_EVENTFD 1
#cmakedefine HAVE_TIMERFD_CREATE 1
+#cmakedefine HAVE_BINDRESVPORT 1
#cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1
#cmakedefine HAVE_IOCTL_INT 1
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index b8b1ca3..f6adc95 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -76,6 +76,9 @@
#ifdef HAVE_GNU_LIB_NAMES_H
#include <gnu/lib-names.h>
#endif
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
enum swrap_dbglvl_e {
SWRAP_LOG_ERROR = 0,
@@ -111,6 +114,13 @@ enum swrap_dbglvl_e {
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
#endif
+#ifndef ZERO_STRUCTP
+#define ZERO_STRUCTP(x) do { \
+ if ((x) != NULL) \
+ memset((char *)(x), 0, sizeof(*(x))); \
+ } while(0)
+#endif
+
#ifndef discard_const
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
#endif
@@ -843,6 +853,7 @@ static const char *socket_wrapper_dir(void)
if (s == NULL) {
return NULL;
}
+ /* TODO use realpath(3) here, when we add support for threads */
if (strncmp(s, "./", 2) == 0) {
s += 2;
}
@@ -1256,6 +1267,89 @@ static struct socket_info *find_socket_info(int fd)
return NULL;
}
+static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
+{
+ struct socket_info *s;
+
+ /* first catch invalid input */
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (len < sizeof(struct sockaddr_in)) {
+ return false;
+ }
+ break;
+#if HAVE_IPV6
+ case AF_INET6:
+ if (len < sizeof(struct sockaddr_in6)) {
+ return false;
+ }
+ break;
+#endif
+ default:
+ return false;
+ break;
+ }
+
+ for (s = sockets; s != NULL; s = s->next) {
+ if (s->myname == NULL) {
+ continue;
+ }
+ if (s->myname->sa_family != sa->sa_family) {
+ continue;
+ }
+ switch (s->myname->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in *)s->myname;
+ sin2 = (struct sockaddr_in *)sa;
+
+ if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ continue;
+ }
+ if (sin1->sin_port != sin2->sin_port) {
+ continue;
+ }
+ if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#if HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in6 *)s->myname;
+ sin2 = (struct sockaddr_in6 *)sa;
+
+ if (sin1->sin6_port != sin2->sin6_port) {
+ continue;
+ }
+ if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
+ &sin2->sin6_addr))
+ {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#endif
+ default:
+ continue;
+ break;
+
+ }
+ }
+
+ return false;
+}
+
+
static void swrap_remove_stale(int fd)
{
struct socket_info *si = find_socket_info(fd);
@@ -1298,6 +1392,26 @@ static int sockaddr_convert_to_un(struct socket_info *si,
#endif
switch (in_addr->sa_family) {
+ case AF_UNSPEC: {
+ struct sockaddr_in *sin;
+ if (si->family != AF_INET) {
+ break;
+ }
+ if (in_len < sizeof(struct sockaddr_in)) {
+ break;
+ }
+ sin = (struct sockaddr_in *)in_addr;
+ if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
+ break;
+ }
+
+ /*
+ * Note: in the special case of AF_UNSPEC and INADDR_ANY,
+ * AF_UNSPEC is mapped to AF_INET and must be treated here.
+ */
+
+ /* FALL THROUGH */
+ }
case AF_INET:
#ifdef HAVE_IPV6
case AF_INET6:
@@ -2223,8 +2337,40 @@ static int swrap_socket(int family, int type, int protocol)
si->type = real_type;
si->protocol = protocol;
+ /*
+ * Setup myname so getsockname() can succeed to find out the socket
+ * type.
+ */
+ switch(si->family) {
+ case AF_INET: {
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
+
+ si->myname_len = sizeof(struct sockaddr_in);
+ si->myname = sockaddr_dup(&sin, si->myname_len);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ };
+
+ si->myname_len = sizeof(struct sockaddr_in6);
+ si->myname = sockaddr_dup(&sin6, si->myname_len);
+ break;
+ }
+ default:
+ free(si);
+ errno = EINVAL;
+ return -1;
+ }
+
fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
if (fi == NULL) {
+ if (si->myname != NULL) {
+ free (si->myname);
+ }
free(si);
errno = ENOMEM;
return -1;
@@ -2503,6 +2649,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
in.sin_addr.s_addr = htonl(127<<24 |
socket_wrapper_default_iface());
+ free(si->myname);
si->myname_len = sizeof(in);
si->myname = sockaddr_dup(&in, si->myname_len);
break;
@@ -2532,6 +2679,7 @@ static int swrap_auto_bind(int fd, struct socket_info *si, int family)
in6.sin6_family = AF_INET6;
in6.sin6_addr = *swrap_ipv6();
in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
+ free(si->myname);
si->myname_len = sizeof(in6);
si->myname = sockaddr_dup(&in6, si->myname_len);
break;
@@ -2680,11 +2828,70 @@ static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
int ret;
struct sockaddr_un un_addr;
struct socket_info *si = find_socket_info(s);
+ int bind_error = 0;
+ bool in_use;
if (!si) {
return libc_bind(s, myaddr, addrlen);
}
+ switch (si->family) {
+ case AF_INET: {
+ const struct sockaddr_in *sin;
+ if (addrlen < sizeof(struct sockaddr_in)) {
+ bind_error = EINVAL;
+ break;
+ }
+
+ sin = (struct sockaddr_in *)myaddr;
+
+ if (sin->sin_family != AF_INET) {
+ bind_error = EAFNOSUPPORT;
+ }
+
+ /* special case for AF_UNSPEC */
+ if (sin->sin_family == AF_UNSPEC &&
+ (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
+ {
+ bind_error = 0;
+ }
+
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *sin6;
+ if (addrlen < sizeof(struct sockaddr_in6)) {
+ bind_error = EINVAL;
+ break;
+ }
+
+ sin6 = (struct sockaddr_in6 *)myaddr;
+
+ if (sin6->sin6_family != AF_INET6) {
+ bind_error = EAFNOSUPPORT;
+ }
+
+ break;
+ }
+#endif
+ default:
+ bind_error = EINVAL;
+ break;
+ }
+
+ if (bind_error != 0) {
+ errno = bind_error;
+ return -1;
+ }
+
+ in_use = check_addr_port_in_use(myaddr, addrlen);
+ if (in_use) {
+ errno = EADDRINUSE;
+ return -1;
+ }
+
+ free(si->myname);
si->myname_len = addrlen;
si->myname = sockaddr_dup(myaddr, addrlen);
@@ -2713,6 +2920,86 @@ int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
}
/****************************************************************************
+ * BINDRESVPORT
+ ***************************************************************************/
+
+#ifdef HAVE_BINDRESVPORT
+static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
+
+static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
+{
+ struct sockaddr_storage myaddr;
+ socklen_t salen;
+ static uint16_t port;
+ uint16_t i;
+ int rc = -1;
+ int af;
+
+#define SWRAP_STARTPORT 600
+#define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
+#define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
+
+ if (port == 0) {
+ port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
+ }
+
+ if (sa == NULL) {
+ salen = sizeof(struct sockaddr);
+ sa = (struct sockaddr *)&myaddr;
+
+ rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
+ if (rc < 0) {
+ return -1;
+ }
+
+ af = sa->sa_family;
+ memset(&myaddr, 0, salen);
+ } else {
+ af = sa->sa_family;
+ }
+
+ for (i = 0; i < SWRAP_NPORTS; i++, port++) {
+ switch(af) {
+ case AF_INET: {
+ struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
+
+ salen = sizeof(struct sockaddr_in);
+ sinp->sin_port = htons(port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
+
+ salen = sizeof(struct sockaddr_in6);
+ sin6p->sin6_port = htons(port);
+ break;
+ }
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ sa->sa_family = af;
+
+ if (port > SWRAP_ENDPORT) {
+ port = SWRAP_STARTPORT;
+ }
+
+ rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
+ if (rc == 0 || errno != EADDRINUSE) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int bindresvport(int sockfd, struct sockaddr_in *sinp)
+{
+ return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
+}
+#endif
+
+/****************************************************************************
* LISTEN
***************************************************************************/
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 287539b..d3a4156 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -20,7 +20,9 @@ target_link_libraries(${TORTURE_LIBRARY}
set(SWRAP_TESTS
test_ioctl
+ test_echo_tcp_socket
test_echo_tcp_connect
+ test_echo_tcp_bind
test_echo_tcp_socket_options
test_echo_tcp_write_read
test_echo_tcp_writev_readv
diff --git a/tests/echo_srv.c b/tests/echo_srv.c
index 88d8170..e3973f5 100644
--- a/tests/echo_srv.c
+++ b/tests/echo_srv.c
@@ -153,7 +153,7 @@ static int pidfile(const char *path)
return 0;
}
-static int become_daemon(struct echo_srv_opts *opts)
+static int become_daemon(void)
{
int ret;
pid_t child_pid;
@@ -178,13 +178,6 @@ static int become_daemon(struct echo_srv_opts *opts)
chdir(WORKING_DIR);
#endif
- ret = pidfile(opts->pidfile);
- if (ret != 0) {
- fprintf(stderr, "Cannot create pidfile %s: %s\n",
- opts->pidfile, strerror(ret));
- return ret;
- }
-
ret = setsid();
if (ret == -1) {
ret = errno;
@@ -895,7 +888,7 @@ int main(int argc, char **argv)
}
if (opts.daemon) {
- ret = become_daemon(&opts);
+ ret = become_daemon();
if (ret != 0) {
fprintf(stderr, "Cannot become daemon: %s\n", strerror(ret));
goto done;
@@ -908,6 +901,15 @@ int main(int argc, char **argv)
goto done;
}
+ if (opts.daemon && opts.pidfile != NULL) {
+ ret = pidfile(opts.pidfile);
+ if (ret != 0) {
+ fprintf(stderr, "Cannot create pidfile %s: %s\n",
+ opts.pidfile, strerror(ret));
+ goto done;
+ }
--
Socket Wrapper Repository
More information about the samba-cvs
mailing list