[SCM] Samba Shared Repository - branch v4-17-test updated

Jule Anger janger at samba.org
Mon Oct 31 10:09:01 UTC 2022


The branch, v4-17-test has been updated
       via  057f60cc715 python/samba/tests: fix samba.tests.auth_log_pass_change for later gnutls
       via  e84108f30a1 s4/rpc_server/sambr: don't mutate the return of samdb_set_password_aes
       via  c57b3d3751d s4:libnet: If we successfully changed the password we are done
       via  d26e2da30c0 s3:rpcclient: Pass salt down to init_samr_CryptPasswordAES()
       via  c59f9c33192 s3:librpc: Improve GSE error message
       via  743a56e5ccf s4:ldap_server: let ldapsrv_call_writev_start use conn_idle_time to limit the time
       via  b615bf4333a lib/tsocket: avoid endless cpu-spinning in tstream_bsd_fde_handler()
       via  419986dcc0b lib/tsocket: remember the first error as tstream_bsd->error
       via  5c051d38065 lib/tsocket: check for errors indicated by poll() before getsockopt(fd, SOL_SOCKET, SO_ERROR)
       via  8a4ef3d92e7 lib/tsocket: split out tsocket_bsd_error() from tsocket_bsd_pending()
       via  dcac415e949 lib/tsocket: Add tests for loop on EAGAIN
      from  0b562285733 VERSION: Bump version up to Samba 4.17.3...

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-17-test


- Log -----------------------------------------------------------------
commit 057f60cc71516de6d0f169bb74c7f8f7d88cc231
Author: Noel Power <noel.power at suse.com>
Date:   Fri Oct 21 17:14:44 2022 +0100

    python/samba/tests: fix samba.tests.auth_log_pass_change for later gnutls
    
    later gnutls that support GNUTLS_PBKDF2 currently fail,
    we need to conditionally switch test data to reflect use of
    'samr_ChangePasswordUser3' or 'samr_ChangePasswordUser4'
    depending on whether GNUTLS_PBKDF2 is supported or not
    
    Signed-off-by: Noel Power <noel.power at suse.com>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    (cherry picked from commit ce7c418ca4f8f82e61a9a02a6589ab1c4df51d63)
    
    Autobuild-User(v4-17-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-17-test): Mon Oct 31 10:08:34 UTC 2022 on sn-devel-184

commit e84108f30a1bec44b0add92f77590d0ea032d06e
Author: Noel Power <noel.power at suse.com>
Date:   Fri Oct 21 17:40:36 2022 +0100

    s4/rpc_server/sambr: don't mutate the return of samdb_set_password_aes
    
    prior to this commit return of samdb_set_password_aes was set to
    NT_STATUS_WRONG_PASSWORD on failure. Useful status that should be
    returned such as NT_STATUS_PASSWORD_RESTRICTION are swallowed here
    otherwise (and in this case can be partially responsible for failures
    in test samba.tests.auth_log_pass_change (with later gnutls)
    
    Signed-off-by: Noel Power <noel.power at suse.com>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    (cherry picked from commit 416bf5a41827a4e486215bfc8e47abc570c6e899)

commit c57b3d3751df90c945c96467a897416c892b8bf6
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Oct 17 09:02:28 2022 +0200

    s4:libnet: If we successfully changed the password we are done
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15206
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Noel Power <noel.power at suse.com>
    (cherry picked from commit 30ca92a8164e1c3a76cdb798ee997d27621a5abb)

commit d26e2da30c08658bb3cf3643ac9b906239351c09
Author: Andreas Schneider <asn at samba.org>
Date:   Fri Oct 7 14:35:15 2022 +0200

    s3:rpcclient: Pass salt down to init_samr_CryptPasswordAES()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15206
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Noel Power <noel.power at suse.com>
    (cherry picked from commit 16335412ff312ecb330f7890bd3e94117a5fa6ff)

commit c59f9c33192d7ca985023db5bdfe6c3939458f75
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Oct 10 15:15:20 2022 +0200

    s3:librpc: Improve GSE error message
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15206
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Noel Power <noel.power at suse.com>
    (cherry picked from commit e3ebda8c6ae6e0c202e2b11a65b98b4f247ae4db)

commit 743a56e5ccf358deb7b7093c55ea796e7000de3f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 13 10:17:25 2022 +0200

    s4:ldap_server: let ldapsrv_call_writev_start use conn_idle_time to limit the time
    
    If the client is not able to receive the results within connections idle
    time, then we should treat it as dead. It's value is 15 minutes (900 s)
    by default.
    
    In order to limit that further an admin can use 'socket options'
    and set TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL and/or TCP_USER_TIMEOUT
    to useful values.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Wed Oct 19 17:13:39 UTC 2022 on sn-devel-184
    
    (cherry picked from commit eb2f3526032803f34c88ef1619a832a741f71910)

commit b615bf4333a1a1a3c80bd93a186f1a137c8b13dc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 17:26:16 2022 +0200

    lib/tsocket: avoid endless cpu-spinning in tstream_bsd_fde_handler()
    
    There were some reports that strace output an LDAP server socket is in
    CLOSE_WAIT state, returning EAGAIN for writev over and over (after a call to
    epoll() each time).
    
    In the tstream_bsd code the problem happens when we have a pending
    writev_send, while there's no readv_send pending. In that case
    we still ask for TEVENT_FD_READ in order to notice connection errors
    early, so we try to call writev even if the socket doesn't report TEVENT_FD_WRITE.
    And there are situations where we do that over and over again.
    
    It happens like this with a Linux kernel:
    
        tcp_fin() has this:
            struct tcp_sock *tp = tcp_sk(sk);
    
            inet_csk_schedule_ack(sk);
    
            sk->sk_shutdown |= RCV_SHUTDOWN;
            sock_set_flag(sk, SOCK_DONE);
    
            switch (sk->sk_state) {
            case TCP_SYN_RECV:
            case TCP_ESTABLISHED:
                    /* Move to CLOSE_WAIT */
                    tcp_set_state(sk, TCP_CLOSE_WAIT);
                    inet_csk_enter_pingpong_mode(sk);
                    break;
    
    It means RCV_SHUTDOWN gets set as well as TCP_CLOSE_WAIT, but
    sk->sk_err is not changed to indicate an error.
    
        tcp_sendmsg_locked has this:
        ...
            err = -EPIPE;
            if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
                    goto do_error;
    
            while (msg_data_left(msg)) {
                    int copy = 0;
    
                    skb = tcp_write_queue_tail(sk);
                    if (skb)
                            copy = size_goal - skb->len;
    
                    if (copy <= 0 || !tcp_skb_can_collapse_to(skb)) {
                            bool first_skb;
    
        new_segment:
                            if (!sk_stream_memory_free(sk))
                                    goto wait_for_space;
    
        ...
    
        wait_for_space:
                    set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                    if (copied)
                            tcp_push(sk, flags & ~MSG_MORE, mss_now,
                                     TCP_NAGLE_PUSH, size_goal);
    
                    err = sk_stream_wait_memory(sk, &timeo);
                    if (err != 0)
                            goto do_error;
    
    It means if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) doesn't
    hit as we only have RCV_SHUTDOWN and sk_stream_wait_memory returns
    -EAGAIN.
    
        tcp_poll has this:
    
            if (sk->sk_shutdown & RCV_SHUTDOWN)
                    mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
    
    So we'll get EPOLLIN | EPOLLRDNORM | EPOLLRDHUP triggering
    TEVENT_FD_READ and writev/sendmsg keeps getting EAGAIN.
    
    So we need to always clear TEVENT_FD_READ if we don't
    have readable handler in order to avoid burning cpu.
    But we turn it on again after a timeout of 1 second
    in order to monitor the error state of the connection.
    
    And now that our tsocket_bsd_error() helper checks for POLLRDHUP,
    we can check if the socket is in an error state before calling the
    writable handler when TEVENT_FD_READ was reported.
    Only on error we'll call the writable handler, which will pick
    the error without calling writev().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit e232ba946f00aac39d67197d9939bc923814479c)

commit 419986dcc0bc850e82f1d0229fbe57a3be8bb59e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 13 16:23:03 2022 +0200

    lib/tsocket: remember the first error as tstream_bsd->error
    
    If we found that the connection is broken, there's no point
    in trying to use it anymore, so just return the first error we detected.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 4c7e2b9b60de5d02bb3f69effe7eddbf466a6155)

commit 5c051d3806521e2e25a2a8a1e459d1d69722c96f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 13 14:46:14 2022 +0200

    lib/tsocket: check for errors indicated by poll() before getsockopt(fd, SOL_SOCKET, SO_ERROR)
    
    This also returns an error if we got TCP_FIN from the peer,
    which is only reported by an explicit POLLRDHUP check.
    
    Also on FreeBSD getsockopt(fd, SOL_SOCKET, SO_ERROR) fetches
    and resets the error, so a 2nd call no longer returns an error.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 29a65da63d730ecead1e7d4a81a76dd1c8c179ea)

commit 8a4ef3d92e7df83245a76a2396ee328a940a1cf2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 13 10:39:59 2022 +0200

    lib/tsocket: split out tsocket_bsd_error() from tsocket_bsd_pending()
    
    This will be used on its own soon.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 9950efd83e1a4b5e711f1d36fefa8a5d5e8b2410)

commit dcac415e9493fe14eb0972ac0c97f66b02a232d0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Oct 17 16:08:42 2022 +1300

    lib/tsocket: Add tests for loop on EAGAIN
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit f0fb8b9508346aed50528216fd959a9b1a941409)

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

Summary of changes:
 lib/tsocket/tests/socketpair_tcp.c                 |  89 ++++
 .../tsocket/tests/socketpair_tcp.h                 |  30 +-
 lib/tsocket/tests/test_tstream.c                   | 517 +++++++++++++++++++++
 lib/tsocket/tsocket_bsd.c                          | 274 ++++++++++-
 lib/tsocket/wscript_build                          |   6 +
 python/samba/tests/auth_log_pass_change.py         |  20 +-
 selftest/tests.py                                  |   3 +
 source3/librpc/crypto/gse.c                        |  21 +-
 source3/rpc_client/init_samr.c                     |  15 +-
 source3/rpc_client/init_samr.h                     |   1 +
 source3/rpcclient/cmd_samr.c                       |   8 +
 source4/ldap_server/ldap_server.c                  |   5 +
 source4/libnet/libnet_passwd.c                     |  45 +-
 source4/rpc_server/samr/samr_password.c            |   1 -
 source4/selftest/tests.py                          |   9 +-
 source4/torture/rpc/samr.c                         |  27 ++
 16 files changed, 989 insertions(+), 82 deletions(-)
 create mode 100644 lib/tsocket/tests/socketpair_tcp.c
 copy source3/lib/namearray.c => lib/tsocket/tests/socketpair_tcp.h (61%)
 create mode 100644 lib/tsocket/tests/test_tstream.c


Changeset truncated at 500 lines:

diff --git a/lib/tsocket/tests/socketpair_tcp.c b/lib/tsocket/tests/socketpair_tcp.c
new file mode 100644
index 00000000000..251b8bc0212
--- /dev/null
+++ b/lib/tsocket/tests/socketpair_tcp.c
@@ -0,0 +1,89 @@
+/*
+   Unix SMB/CIFS implementation.
+   Samba utility functions
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Tim Potter      2000-2001
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/network.h"
+#include "socketpair_tcp.h"
+
+/*******************************************************************
+this is like socketpair but uses tcp. It is used by the Samba
+regression test code
+The function guarantees that nobody else can attach to the socket,
+or if they do that this function fails and the socket gets closed
+returns 0 on success, -1 on failure
+the resulting file descriptors are symmetrical
+ ******************************************************************/
+int socketpair_tcp(int fd[2])
+{
+	int listener;
+	struct sockaddr_in sock;
+	struct sockaddr_in sock2;
+	socklen_t socklen = sizeof(sock);
+	int connect_done = 0;
+
+	fd[0] = fd[1] = listener = -1;
+
+	memset(&sock, 0, sizeof(sock));
+
+	if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
+
+	memset(&sock2, 0, sizeof(sock2));
+#ifdef HAVE_SOCK_SIN_LEN
+	sock2.sin_len = sizeof(sock2);
+#endif
+	sock2.sin_family = PF_INET;
+
+	if (bind(listener, (struct sockaddr *)&sock2, sizeof(sock2)) != 0) goto failed;
+
+	if (listen(listener, 1) != 0) goto failed;
+
+	if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
+
+	if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
+
+	set_blocking(fd[1], 0);
+
+	sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	if (connect(fd[1], (struct sockaddr *)&sock, socklen) == -1) {
+		if (errno != EINPROGRESS) goto failed;
+	} else {
+		connect_done = 1;
+	}
+
+	if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
+
+	if (connect_done == 0) {
+		if (connect(fd[1], (struct sockaddr *)&sock, socklen) != 0
+		    && errno != EISCONN) goto failed;
+	}
+	close(listener);
+
+	set_blocking(fd[1], 1);
+
+	/* all OK! */
+	return 0;
+
+ failed:
+	if (fd[0] != -1) close(fd[0]);
+	if (fd[1] != -1) close(fd[1]);
+	if (listener != -1) close(listener);
+	return -1;
+}
diff --git a/source3/lib/namearray.c b/lib/tsocket/tests/socketpair_tcp.h
similarity index 61%
copy from source3/lib/namearray.c
copy to lib/tsocket/tests/socketpair_tcp.h
index e5c3bd983b5..dbee4efec70 100644
--- a/source3/lib/namearray.c
+++ b/lib/tsocket/tests/socketpair_tcp.h
@@ -2,10 +2,7 @@
    Unix SMB/CIFS implementation.
    Samba utility functions
    Copyright (C) Andrew Tridgell 1992-1998
-   Copyright (C) Jeremy Allison 2001-2007
-   Copyright (C) Simo Sorce 2001
-   Copyright (C) Jim McDonough <jmcd at us.ibm.com> 2003
-   Copyright (C) James Peach 2006
+   Copyright (C) Tim Potter      2000-2001
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,19 +18,12 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "includes.h"
-/****************************************************************************
- Routine to free a namearray.
-****************************************************************************/
-
-void free_namearray(name_compare_entry *name_array)
-{
-	int i;
-
-	if(name_array == NULL)
-		return;
-
-	for(i=0; name_array[i].name!=NULL; i++)
-		SAFE_FREE(name_array[i].name);
-	SAFE_FREE(name_array);
-}
+/*******************************************************************
+this is like socketpair but uses tcp. It is used by the Samba
+regression test code
+The function guarantees that nobody else can attach to the socket,
+or if they do that this function fails and the socket gets closed
+returns 0 on success, -1 on failure
+the resulting file descriptors are symmetrical
+ ******************************************************************/
+int socketpair_tcp(int fd[2]);
diff --git a/lib/tsocket/tests/test_tstream.c b/lib/tsocket/tests/test_tstream.c
new file mode 100644
index 00000000000..a920e671cda
--- /dev/null
+++ b/lib/tsocket/tests/test_tstream.c
@@ -0,0 +1,517 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) 2022      Andrew Bartlett <abartlet at samba.org>
+ * Copyright (C) 2021      Andreas Schneider <asn at samba.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include "includes.h"
+#include "system/network.h"
+#include "socketpair_tcp.h"
+#include "tsocket.h"
+
+enum socket_pair_selector {
+	SOCKET_SERVER = 0,
+	SOCKET_CLIENT = 1,
+};
+
+struct socket_pair {
+	struct tevent_context *ev;
+	int socket_server;
+	int socket_client;
+
+	/* for tstream tests */
+	int rc;
+	int sys_errno;
+	int expected_errno;
+	struct timeval endtime;
+	size_t max_loops;
+	size_t num_loops;
+};
+
+/* If this is too large, we get EPIPE rather than EAGAIN */
+static const uint8_t TEST_STRING[128] = { 0 };
+
+static int sigpipe_setup(void **state)
+{
+	BlockSignals(true, SIGPIPE);
+	return 0;
+}
+
+static int setup_socketpair_tcp_context(void **state)
+{
+	int fd[2];
+	struct socket_pair *sp = talloc_zero(NULL, struct socket_pair);
+	assert_non_null(sp);
+
+	/* Set up a socketpair over TCP to test with */
+	assert_return_code(socketpair_tcp(fd), errno);
+
+	sp->socket_server = fd[SOCKET_SERVER];
+	sp->socket_client = fd[SOCKET_CLIENT];
+
+	sp->ev = tevent_context_init(sp);
+	assert_non_null(sp->ev);
+
+	*state = sp;
+	return 0;
+}
+
+static int setup_socketpair_context(void **state)
+{
+	int fd[2];
+	struct socket_pair *sp = talloc_zero(NULL, struct socket_pair);
+	assert_non_null(sp);
+
+	/* Set up a socketpair over TCP to test with */
+	assert_return_code(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), errno);
+
+	sp->socket_server = fd[SOCKET_SERVER];
+	sp->socket_client = fd[SOCKET_CLIENT];
+
+	sp->ev = tevent_context_init(sp);
+	assert_non_null(sp->ev);
+
+	*state = sp;
+	return 0;
+}
+
+static int teardown_socketpair_context(void **state)
+{
+	struct socket_pair *sp = *state;
+	struct socket_pair sp_save = *sp;
+
+	TALLOC_FREE(sp);
+
+	/*
+	 * Close these after the TALLOC_FREE() to allow clean shutdown
+	 * of epoll() in tstream
+	 */
+	if (sp_save.socket_client != -1) {
+		close(sp_save.socket_client);
+	}
+	if (sp_save.socket_server != -1) {
+		close(sp_save.socket_server);
+	}
+	return 0;
+}
+
+
+/* Test socket behaviour */
+static void test_simple_socketpair(void **state) {
+
+	struct socket_pair *sp = *state;
+
+	char buf[sizeof(TEST_STRING)];
+
+	assert_int_equal(write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING)),
+			 sizeof(TEST_STRING));
+	assert_int_equal(read(sp->socket_client, buf, sizeof(buf)),
+			 sizeof(buf));
+
+
+}
+
+/* Test socket behaviour */
+static void test_read_client_after_close_server_socket(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+	char buf[sizeof(TEST_STRING)];
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+
+	assert_return_code(close(sp->socket_server), 0);
+
+	rc = read(sp->socket_client, buf, sizeof(buf));
+
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(buf));
+}
+
+static void test_write_server_after_close_client_socket(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+
+	assert_return_code(close(sp->socket_client), 0);
+	sp->socket_client = -1;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+}
+
+static void test_fill_socket(int sock)
+{
+	size_t num_busy = 0;
+	int rc;
+
+	while (true) {
+		rc = write(sock, TEST_STRING, sizeof(TEST_STRING));
+		if (rc == -1 && errno == EAGAIN) {
+			/*
+			 * This makes sure we write until we get a whole second
+			 * only with EAGAIN every 50 ms (20 times)
+			 *
+			 * Otherwise the tests are not reliable...
+			 */
+			num_busy++;
+			if (num_busy > 20) {
+				break;
+			}
+			smb_msleep(50);
+			continue;
+		}
+		/* try again next time */
+		num_busy = 0;
+	}
+
+	assert_int_equal(rc, -1);
+	assert_int_equal(errno, EAGAIN);
+}
+
+static void test_big_write_server(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+
+	rc = set_blocking(sp->socket_server, 0);
+	assert_return_code(rc, errno);
+
+	test_fill_socket(sp->socket_server);
+}
+
+static void test_big_write_server_close_write(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+
+	rc = set_blocking(sp->socket_server, 0);
+	assert_return_code(rc, errno);
+
+	test_fill_socket(sp->socket_server);
+
+	assert_return_code(close(sp->socket_client), 0);
+	sp->socket_client = -1;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_int_equal(errno, ECONNRESET);
+
+}
+
+static void test_big_write_server_shutdown_wr_write(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+
+	rc = set_blocking(sp->socket_server, 0);
+	assert_return_code(rc, errno);
+
+	test_fill_socket(sp->socket_server);
+
+	assert_return_code(shutdown(sp->socket_client, SHUT_WR), 0);
+	sp->socket_client = -1;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_int_equal(rc, -1);
+	assert_int_equal(errno, EAGAIN);
+}
+
+static void test_big_write_server_shutdown_rd_write(void **state) {
+
+	struct socket_pair *sp = *state;
+	int rc;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	assert_int_equal(rc, sizeof(TEST_STRING));
+
+	rc = set_blocking(sp->socket_server, 0);
+	assert_return_code(rc, errno);
+
+	test_fill_socket(sp->socket_server);
+
+	assert_return_code(shutdown(sp->socket_client, SHUT_RD), 0);
+	sp->socket_client = -1;
+
+	rc = write(sp->socket_server, TEST_STRING, sizeof(TEST_STRING));
+	assert_int_equal(rc, -1);
+	assert_int_equal(errno, EAGAIN);
+}
+
+static void test_call_writev_done(struct tevent_req *subreq)
+{
+	struct socket_pair *sp =
+		tevent_req_callback_data(subreq,
+		struct socket_pair);
+	int rc;
+
+	rc = tstream_writev_recv(subreq, &sp->sys_errno);
+	TALLOC_FREE(subreq);
+
+	sp->rc = rc;
+}
+
+static void test_tstream_server_spin_client_shutdown(struct socket_pair *sp)
+{
+	int rc;
+
+	rc = shutdown(sp->socket_client, SHUT_WR);
+	assert_return_code(rc, errno);
+	/*
+	 * It should only take a few additional loop to realise that this socket is
+	 * in CLOSE_WAIT
+	 */
+	sp->max_loops = sp->num_loops + 2;
+	sp->expected_errno = ECONNRESET;
+}
+
+static void test_tstream_server_spin_client_write(struct socket_pair *sp)
+{
+	int rc;
+	int timeout = 5000;
+
+	sp->endtime = timeval_current_ofs_msec(timeout);
+
+	rc = write(sp->socket_client, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	sp->expected_errno = ETIMEDOUT;
+}
+
+static void test_tstream_server_spin_client_tcp_user_timeout(struct socket_pair *sp)
+{
+	int rc;
+	int timeout = 5000;
+
+	rc = setsockopt(sp->socket_server, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));
+	assert_return_code(rc, errno);
+
+	rc = write(sp->socket_client, TEST_STRING, sizeof(TEST_STRING));
+	assert_return_code(rc, errno);
+	sp->expected_errno = ETIMEDOUT;
+	sp->max_loops = 15;
+}
+
+static void test_tstream_server_spin_client_both_timer(struct tevent_context *ev,
+						       struct tevent_timer *te,
+						       struct timeval current_time,
+						       void *private_data)
+{
+	struct socket_pair *sp =
+		talloc_get_type_abort(private_data,
+		struct socket_pair);
+
+	test_tstream_server_spin_client_shutdown(sp);
+}
+
+static void test_tstream_server_spin_client_both(struct socket_pair *sp)
+{
+	struct tevent_timer *te = NULL;
+	struct timeval endtime;
+
+	test_tstream_server_spin_client_write(sp);
+
+	endtime = timeval_current_ofs_msec(2500);
+
+	te = tevent_add_timer(sp->ev,
+			      sp,
+			      endtime,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list