[SCM] Socket Wrapper Repository - branch master updated

Andreas Schneider asn at samba.org
Mon Feb 8 18:34:21 UTC 2021


The branch, master has been updated
       via  0422a95 test_echo_tcp_sendmsg_recvmsg_fd: add test_tcp_sendmsg_recvmsg_fd_mixed() tests
       via  b35e3ce test_echo_tcp_sendmsg_recvmsg_fd: add test_tcp_sendmsg_recvmsg_fd_different() tests
       via  2d93f75 test_echo_tcp_sendmsg_recvmsg_fd: also test passing the same socket up to 6 times
       via  5aa939f test_echo_tcp_sendmsg_recvmsg_fd: split out test_tcp_sendmsg_recvmsg_fd_same()
       via  cbd5910 test_echo_tcp_sendmsg_recvmsg_fd: split out test_tcp_sendmsg_recvmsg_fd_array()
       via  b2e366d tests/echo_srv: allow more than once tcp connection at a time
       via  e896cec swrap: fix fd-passing without 4 padding bytes
       via  3c7ef47 swrap: fix invalid read in swrap_sendmsg_unix_scm_rights()
      from  13a6aca swrap: fix copy on write leak of ~38M for every fork.

https://git.samba.org/?p=socket_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0422a957c1b8959c5b48d7188a524296dc9b778b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 16:25:43 2021 +0100

    test_echo_tcp_sendmsg_recvmsg_fd: add test_tcp_sendmsg_recvmsg_fd_mixed() tests
    
    Here we mix sockets and other valid file descriptors.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit b35e3ce2e2b78fb7a1ccf6d5e011239c14fe27a9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 14:40:45 2021 +0100

    test_echo_tcp_sendmsg_recvmsg_fd: add test_tcp_sendmsg_recvmsg_fd_different() tests
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 2d93f75669a432723c90e20c3f9b2e2abfa55545
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 14:20:16 2021 +0100

    test_echo_tcp_sendmsg_recvmsg_fd: also test passing the same socket up to 6 times
    
    Note SWRAP_MAX_PASSED_FDS is currently 6.
    
    This test demonstrates that even 64-bit systems required commit:
    "swrap: fix fd-passing without 4 padding bytes"
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 5aa939f2eb3f3ab04b65fde031a0c1f151928121
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 14:10:03 2021 +0100

    test_echo_tcp_sendmsg_recvmsg_fd: split out test_tcp_sendmsg_recvmsg_fd_same()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit cbd5910b1814cad1f1c4e9c9e8515f217edcd4d2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 4 17:04:30 2021 +0100

    test_echo_tcp_sendmsg_recvmsg_fd: split out test_tcp_sendmsg_recvmsg_fd_array()
    
    This will allow us to test more combinations in order to
    get better coverage. For now we just test a single fd.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit b2e366d87bf8b340fe5e0b0186369cda7a94d186
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 15:41:27 2021 +0100

    tests/echo_srv: allow more than once tcp connection at a time
    
    We should not wait for the last connection to disconnect,
    there would not be any reason to use fork at all.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit e896cecf1fc08d091d09fa29f1cfbfc22dab89ff
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 4 16:20:13 2021 +0100

    swrap: fix fd-passing without 4 padding bytes
    
    We noticed the problem on 32 bit platforms and sending a single
    application fd, the hidden pipe-fd doesn't fit into the padding
    bytes. This can also happen on 64 bit platforms and an even number
    of application fds.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 3c7ef4751527bd8c93d5431d9f1e36c4fe648f3d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 5 19:36:26 2021 +0100

    swrap: fix invalid read in swrap_sendmsg_unix_scm_rights()
    
    Here the fds_out array is larger than the fds_in array, so we can
    only copy the fds_in array using size_fds_in, leaving the last slot
    of fds_out untouched, which is filled by fds_out[num_fds_in] = pipefd[0]
    later.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 src/socket_wrapper.c                     |  71 ++++-
 tests/echo_srv.c                         |   2 +-
 tests/test_echo_tcp_sendmsg_recvmsg_fd.c | 510 +++++++++++++++++++++++++++----
 3 files changed, 518 insertions(+), 65 deletions(-)


Changeset truncated at 500 lines:

diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index 43a5892..ece3493 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -5450,7 +5450,7 @@ static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
 	*new_cmsg = *cmsg;
 	__fds_out.p = CMSG_DATA(new_cmsg);
 	fds_out = __fds_out.fds;
-	memcpy(fds_out, fds_in, size_fds_out);
+	memcpy(fds_out, fds_in, size_fds_in);
 	new_cmsg->cmsg_len = cmsg->cmsg_len;
 
 	for (i = 0; i < num_fds_in; i++) {
@@ -5962,8 +5962,48 @@ static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
 				     struct msghdr *msg_tmp)
 {
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+	const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
+	uint8_t *cm_data = NULL;
+	size_t cm_data_space = 0;
+
+	*msg_tmp = *msg_in;
+
+	SWRAP_LOG(SWRAP_LOG_TRACE,
+		  "msg_in->msg_controllen=%zu",
+		  (size_t)msg_in->msg_controllen);
+
+	/* Nothing to do */
+	if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
+		return 0;
+	}
+
+	/*
+	 * We need to give the kernel a bit more space in order
+	 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
+	 * swrap_recvmsg_after_unix() will hide it again.
+	 */
+	cm_data_space = msg_in->msg_controllen;
+	if (cm_data_space < (INT32_MAX - cm_extra_space)) {
+		cm_data_space += cm_extra_space;
+	}
+	cm_data = calloc(1, cm_data_space);
+	if (cm_data == NULL) {
+		return -1;
+	}
+	memcpy(cm_data, msg_in->msg_control, msg_in->msg_controllen);
+
+	msg_tmp->msg_controllen = cm_data_space;
+	msg_tmp->msg_control = cm_data;
+
+	SWRAP_LOG(SWRAP_LOG_TRACE,
+		  "msg_tmp->msg_controllen=%zu",
+		  (size_t)msg_tmp->msg_controllen);
+	return 0;
+#else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
 	*msg_tmp = *msg_in;
 	return 0;
+#endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
 }
 
 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
@@ -5976,9 +6016,14 @@ static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
 	size_t cm_data_space = 0;
 	int rc = -1;
 
+	SWRAP_LOG(SWRAP_LOG_TRACE,
+		  "msg_tmp->msg_controllen=%zu",
+		  (size_t)msg_tmp->msg_controllen);
+
 	/* Nothing to do */
 	if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
-		goto done;
+		*msg_out = *msg_tmp;
+		return ret;
 	}
 
 	for (cmsg = CMSG_FIRSTHDR(msg_tmp);
@@ -6006,15 +6051,27 @@ static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
 	}
 
 	/*
-	 * msg_tmp->msg_control is still the buffer of the caller.
+	 * msg_tmp->msg_control was created by swrap_recvmsg_before_unix()
+	 * and msg_out->msg_control is still the buffer of the caller.
 	 */
-	memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
-	msg_tmp->msg_controllen = cm_data_space;
+	SAFE_FREE(msg_tmp->msg_control);
+	msg_tmp->msg_control = msg_out->msg_control;
+	msg_tmp->msg_controllen = msg_out->msg_controllen;
+	*msg_out = *msg_tmp;
+
+	cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
+	memcpy(msg_out->msg_control, cm_data, cm_data_space);
+	msg_out->msg_controllen = cm_data_space;
 	SAFE_FREE(cm_data);
-done:
-#endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
+	SWRAP_LOG(SWRAP_LOG_TRACE,
+		  "msg_out->msg_controllen=%zu",
+		  (size_t)msg_out->msg_controllen);
+	return ret;
+#else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
 	*msg_out = *msg_tmp;
 	return ret;
+#endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
 }
 
 static ssize_t swrap_sendmsg_before(int fd,
diff --git a/tests/echo_srv.c b/tests/echo_srv.c
index 0aefa9a..fbb6637 100644
--- a/tests/echo_srv.c
+++ b/tests/echo_srv.c
@@ -537,6 +537,7 @@ static void echo_tcp(int sock)
     pid_t pid;
 
     while (1) {
+        waitpid(-1, NULL, WNOHANG);
         s = accept(sock, &addr.sa.s, &addr.sa_socklen);
         if (s == -1 && errno == ECONNABORTED) {
             continue;
@@ -575,7 +576,6 @@ static void echo_tcp(int sock)
             close(s);
             exit(0);
         }
-        waitpid(-1, NULL, 0);
         close(s);
     }
 
diff --git a/tests/test_echo_tcp_sendmsg_recvmsg_fd.c b/tests/test_echo_tcp_sendmsg_recvmsg_fd.c
index 8ae1a60..215d5ff 100644
--- a/tests/test_echo_tcp_sendmsg_recvmsg_fd.c
+++ b/tests/test_echo_tcp_sendmsg_recvmsg_fd.c
@@ -33,33 +33,86 @@ static int teardown(void **state)
 	return 0;
 }
 
-static void test_tcp_sendmsg_recvmsg_fd(void **state)
+struct test_fd {
+	int fd;
+	struct torture_address sock_addr;
+	struct torture_address peer_addr;
+};
+
+static int test_fill_test_fd(struct test_fd *tfd, int fd)
 {
-	struct torture_address addr = {
-		.sa_socklen = sizeof(struct sockaddr_in),
+	struct torture_address saddr = {
+		.sa_socklen = sizeof(struct sockaddr_storage),
 	};
-	int pass_sock_fd;
-	int sv[2];
-	int child_fd, parent_fd;
-	pid_t pid;
-	int rc;
+	struct torture_address paddr = {
+		.sa_socklen = sizeof(struct sockaddr_storage),
+	};
+	int ret;
 
-	(void) state; /* unused */
+	*tfd = (struct test_fd) { .fd = fd, };
 
-	/* create socket file descriptor to be passed */
-	pass_sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	assert_int_not_equal(pass_sock_fd, -1);
+	ret = getsockname(fd, &saddr.sa.s, &saddr.sa_socklen);
+	if (ret == -1 && errno == ENOTSOCK) {
+		return 0;
+	}
+	if (ret == -1) {
+		return ret;
+	}
 
-	addr.sa.in.sin_family = AF_INET;
-	addr.sa.in.sin_port = htons(torture_server_port());
+	ret = getpeername(fd, &paddr.sa.s, &paddr.sa_socklen);
+	if (ret == -1) {
+		return ret;
+	}
 
-	rc = inet_pton(addr.sa.in.sin_family,
-		       torture_server_address(AF_INET),
-		       &addr.sa.in.sin_addr);
-	assert_int_equal(rc, 1);
+	tfd->sock_addr = saddr;
+	tfd->peer_addr = paddr;
+	return 0;
+}
 
-	rc = connect(pass_sock_fd, &addr.sa.s, addr.sa_socklen);
-	assert_int_equal(rc, 0);
+static void _assert_torture_address_equal(const struct torture_address *ga,
+					  const struct torture_address *ea,
+					  const char * const file,
+					  const int line)
+{
+	_assert_int_equal(ga->sa_socklen, ea->sa_socklen, file, line);
+	if (ga->sa_socklen == 0) {
+		return;
+	}
+	_assert_memory_equal(&ga->sa, &ea->sa, ga->sa_socklen, file, line);
+}
+
+#define assert_test_fd_equal(gfd, efd) \
+	_assert_test_fd_equal(gfd, efd, __FILE__, __LINE__)
+
+static void _assert_test_fd_equal(const struct test_fd *gfd,
+				  const struct test_fd *efd,
+				  const char * const file,
+				  const int line)
+{
+	if (efd->fd == -1) {
+		_assert_int_equal(gfd->fd, -1, file, line);
+		return;
+	}
+
+	_assert_int_not_equal(gfd->fd, -1, file, line);
+
+	_assert_torture_address_equal(&gfd->sock_addr, &efd->sock_addr, file, line);
+	_assert_torture_address_equal(&gfd->peer_addr, &efd->peer_addr, file, line);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_array(const int *fds, size_t num_fds)
+{
+	struct test_fd tfds[num_fds];
+	size_t idx;
+	int sv[2];
+	int child_fd, parent_fd;
+	pid_t pid;
+	int rc;
+
+	for (idx = 0; idx < num_fds; idx++) {
+		rc = test_fill_test_fd(&tfds[idx], fds[idx]);
+		assert_int_equal(rc, 0);
+	}
 
 	/* create unix domain socket stream */
 	rc = socketpair(AF_LOCAL, SOCK_STREAM, 0, sv);
@@ -73,17 +126,11 @@ static void test_tcp_sendmsg_recvmsg_fd(void **state)
 
 	if (pid == 0) {
 		/* Child */
-		struct torture_address peer_addr = {
-			.sa_socklen = sizeof(struct sockaddr_in),
-		};
 		struct msghdr child_msg;
-		char cmsgbuf[CMSG_SPACE(sizeof(int))];
+		int recv_fd_array[num_fds];
+		char cmsgbuf[CMSG_SPACE(sizeof(int)*num_fds)];
 		struct cmsghdr *cmsg;
-		int rcv_sock_fd, port;
 		ssize_t ret;
-		char send_buf[64] = {0};
-		char recv_buf[64] = {0};
-		char ipstr[INET_ADDRSTRLEN];
 		char byte = { 0, };
 		struct iovec iov;
 
@@ -104,45 +151,70 @@ static void test_tcp_sendmsg_recvmsg_fd(void **state)
 		assert_non_null(cmsg);
 		assert_int_equal(cmsg->cmsg_type, SCM_RIGHTS);
 
-		memcpy(&rcv_sock_fd, CMSG_DATA(cmsg), sizeof(rcv_sock_fd));
-		assert_int_not_equal(rcv_sock_fd, -1);
-
-		/* extract peer info from received socket fd */
-		ret = getpeername(rcv_sock_fd, &peer_addr.sa.s, &peer_addr.sa_socklen);
-		assert_int_not_equal(ret, -1);
-
-		port = ntohs(peer_addr.sa.in.sin_port);
-		inet_ntop(AF_INET, &peer_addr.sa.in.sin_addr, ipstr, sizeof(ipstr));
-
-		/* check whether it is the same socket previously connected */
-		assert_string_equal(ipstr, torture_server_address(AF_INET));
-		assert_int_equal(port, torture_server_port());
+		memcpy(recv_fd_array, CMSG_DATA(cmsg), sizeof(int)*num_fds);
+		for (idx = 0; idx < num_fds; idx++) {
+			assert_int_not_equal(recv_fd_array[idx], -1);
+		}
 
-		snprintf(send_buf, sizeof(send_buf), "packet");
+		for (idx = 0; idx < num_fds; idx++) {
+			struct test_fd recv_tfd = { .fd = -1, };
 
-		ret = write(rcv_sock_fd,
-			    send_buf,
-			    sizeof(send_buf));
-		assert_int_not_equal(ret, -1);
+			ret = test_fill_test_fd(&recv_tfd, recv_fd_array[idx]);
+			assert_int_equal(ret, 0);
 
-		ret = read(rcv_sock_fd,
-			   recv_buf,
-			   sizeof(recv_buf));
-		assert_int_not_equal(ret, -1);
+			assert_test_fd_equal(&recv_tfd, &tfds[idx]);
+		}
 
-		assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+		for (idx = 0; idx < num_fds; idx++) {
+			int recv_fd = recv_fd_array[idx];
+			char send_buf[64] = {0,};
+			char recv_buf[64] = {0,};
+
+			if (tfds[idx].sock_addr.sa_socklen == 0) {
+				/*
+				 * skip fds not belonging to
+				 * a socket.
+				 */
+				continue;
+			}
+
+			if (tfds[idx].sock_addr.sa.s.sa_family == AF_UNIX) {
+				/*
+				 * skip fds not belonging to
+				 * a socket.
+				 */
+				continue;
+			}
+
+			snprintf(send_buf, sizeof(send_buf), "packet");
+
+			ret = write(recv_fd,
+				    send_buf,
+				    sizeof(send_buf));
+			assert_int_not_equal(ret, -1);
+
+			ret = read(recv_fd,
+				   recv_buf,
+				   sizeof(recv_buf));
+			assert_int_not_equal(ret, -1);
+
+			assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+		}
 
 		exit(0);
 	} else {
 		/* Parent */
 		struct msghdr parent_msg;
 		struct cmsghdr *cmsg;
-		char cmsgbuf[CMSG_SPACE(sizeof(pass_sock_fd))];
+		char cmsgbuf[CMSG_SPACE(sizeof(int)*num_fds)];
+		int pass_fd_array[num_fds];
 		char byte = '!';
 		struct iovec iov;
 		int cs;
 
-		(void) state; /* unused */
+		for (idx = 0; idx < num_fds; idx++) {
+			pass_fd_array[idx] = tfds[idx].fd;
+		}
 
 		iov.iov_base = &byte;
 		iov.iov_len = 1;
@@ -156,10 +228,10 @@ static void test_tcp_sendmsg_recvmsg_fd(void **state)
 		cmsg = CMSG_FIRSTHDR(&parent_msg);
 		cmsg->cmsg_level = SOL_SOCKET;
 		cmsg->cmsg_type = SCM_RIGHTS;
-		cmsg->cmsg_len = CMSG_LEN(sizeof(pass_sock_fd));
+		cmsg->cmsg_len = CMSG_LEN(sizeof(int)*num_fds);
 
 		/* place previously connected socket fd as ancillary data */
-		memcpy(CMSG_DATA(cmsg), &pass_sock_fd, sizeof(pass_sock_fd));
+		memcpy(CMSG_DATA(cmsg), pass_fd_array, sizeof(int)*num_fds);
 		parent_msg.msg_controllen = cmsg->cmsg_len;
 
 		rc = sendmsg(parent_fd, &parent_msg, 0);
@@ -173,13 +245,337 @@ static void test_tcp_sendmsg_recvmsg_fd(void **state)
 	}
 }
 
+static void test_tcp_sendmsg_recvmsg_fd_same(size_t num_fds)
+{
+	struct torture_address addr = {
+		.sa_socklen = sizeof(struct sockaddr_in),
+	};
+	int pass_sock_fd;
+	int fd_array[num_fds];
+	size_t idx;
+	int rc;
+
+	/* create socket file descriptor to be passed */
+	pass_sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	assert_int_not_equal(pass_sock_fd, -1);
+
+	addr.sa.in.sin_family = AF_INET;
+	addr.sa.in.sin_port = htons(torture_server_port());
+
+	rc = inet_pton(addr.sa.in.sin_family,
+		       torture_server_address(AF_INET),
+		       &addr.sa.in.sin_addr);
+	assert_int_equal(rc, 1);
+
+	rc = connect(pass_sock_fd, &addr.sa.s, addr.sa_socklen);
+	assert_int_equal(rc, 0);
+
+	for (idx = 0; idx < num_fds; idx++) {
+		fd_array[idx] = pass_sock_fd;
+	}
+
+	test_tcp_sendmsg_recvmsg_fd_array(fd_array, num_fds);
+
+	close(pass_sock_fd);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_1(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(1);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_2s(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(2);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_3s(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(3);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_4s(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(4);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_5s(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(5);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_6s(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_same(6);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_different(size_t num_fds)
+{
+	int fd_array[num_fds];
+	size_t idx;
+
+	for (idx = 0; idx < num_fds; idx++) {
+		struct torture_address addr = {
+			.sa_socklen = sizeof(struct sockaddr_in),
+		};
+		int pass_sock_fd;
+		int rc;
+
+		/* create socket file descriptor to be passed */
+		pass_sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		assert_int_not_equal(pass_sock_fd, -1);
+
+		addr.sa.in.sin_family = AF_INET;
+		addr.sa.in.sin_port = htons(torture_server_port());
+
+		rc = inet_pton(addr.sa.in.sin_family,
+			       torture_server_address(AF_INET),
+			       &addr.sa.in.sin_addr);
+		assert_int_equal(rc, 1);
+
+		rc = connect(pass_sock_fd, &addr.sa.s, addr.sa_socklen);
+		assert_int_equal(rc, 0);
+
+		fd_array[idx] = pass_sock_fd;
+	}
+
+	test_tcp_sendmsg_recvmsg_fd_array(fd_array, num_fds);
+
+	for (idx = 0; idx < num_fds; idx++) {
+		close(fd_array[idx]);
+	}
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_2d(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_different(2);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_3d(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_different(3);
+}
+
+static void test_tcp_sendmsg_recvmsg_fd_4d(void **state)
+{
+	(void) state; /* unused */
+	test_tcp_sendmsg_recvmsg_fd_different(4);
+}
+


-- 
Socket Wrapper Repository



More information about the samba-cvs mailing list