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

Jule Anger janger at samba.org
Sat Dec 16 16:09:01 UTC 2023


The branch, v4-19-test has been updated
       via  853efb9dd7b ctdb-server: Drop unnecessary copy of destination address
       via  2e93e358ef9 ctdb-daemon: Use ctdb_connection_to_buf() to simplify
       via  2640bae75e3 smbd: Remove callback for release_ip when "state" is free'ed
       via  43b7068676a s3:selftest: add samba3.blackbox.smbXsrv_client_ctdb_registered_ips
       via  d96cb627b66 selftest: export/use CTDB related envvars in order to run the ctdb command
       via  8add947b212 ctdbd_conn: add ctdbd_passed_ips()
       via  e3a4feda112 ctdbd_conn: add ctdbd_unregister_ips()
       via  acf080817b5 ctdbd_conn: Add deregister_from_ctdbd()
       via  d039fa07f7e ctdbd_conn: let register_with_ctdbd() call CTDB_CONTROL_REGISTER_SRVID just once
       via  e09f92422eb ctdbd_conn: don't use uninitialized memory in ctdbd_register_ips()
       via  118d6c81ec9 ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED
       via  b6906f37c66 ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_DISCONNECTED
       via  24bd10ebfc1 ctdb: add ctdb_connection_same() helper
       via  0d6a38604b2 ctdb: make use of ctdb_canonicalize_ip_inplace() in ctdb_control_tcp_client()
       via  69c4f498c84 ctdb: add ctdb_canonicalize_ip_inplace() helper
       via  38134f374ca ctdb: remove unused ctdb->client_ip_list and print debug on ctdb_tcp_list instead
      from  1b6096a1dff s3:utils: Fix auth callback with smburl

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


- Log -----------------------------------------------------------------
commit 853efb9dd7b7eccebc5bd8a4129f2dc487ad8120
Author: Martin Schwenke <mschwenke at ddn.com>
Date:   Wed Dec 13 10:29:05 2023 +1100

    ctdb-server: Drop unnecessary copy of destination address
    
    Modernise debug while touching the code.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Martin Schwenke <mschwenke at ddn.com>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Fri Dec 15 12:09:21 UTC 2023 on atb-devel-224
    
    (cherry picked from commit 4b7329f15820f1b4d9a7b7f0947719c4217b312a)
    
    Autobuild-User(v4-19-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-19-test): Sat Dec 16 16:08:41 UTC 2023 on atb-devel-224

commit 2e93e358ef9f3d55065cd5e9ad1b03126df06b63
Author: Martin Schwenke <mschwenke at ddn.com>
Date:   Wed Dec 13 10:22:04 2023 +1100

    ctdb-daemon: Use ctdb_connection_to_buf() to simplify
    
    The one case that is no longer handled specially is when the
    destination address is IPv4 loopback.  This may previously have been
    used to avoid flooding the logs when testing.  However, that seems
    unnecessary - if testing with 127.0.0.1 then make it a public address.
    
    Modernise debug while touching the code.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Martin Schwenke <mschwenke at ddn.com>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    (cherry picked from commit 8fc3872557f715dc38f9898754a785fd073ace96)

commit 2640bae75e3abab1a9959b2de14dad29020852de
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 12 17:19:45 2023 +0200

    smbd: Remove callback for release_ip when "state" is free'ed
    
    If a client connects to a non-public address first followed by a connect
    to public address with the same client_guid and a connection to
    the non-public address gets disconnected first, we hit by a use-after-free
    talloc_get_type_abort() called from release_ip() as
    "xconn" is already gone, taking smbd_release_ip_state with it.
    
    We need to decide between calling ctdbd_unregister_ips() by default, as
    it means the tcp connection is really gone and ctdb needs to remove the
    'tickle' information.  But when a connection was passed to a different
    smbd process, we need to use ctdbd_passed_ips() as the tcp connection is
    still alive and the 'tickle' information should not be removed within
    ctdb.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit ddf47e7fe314e0f5bf71ff53e35350e0ba530d08)

commit 43b7068676a00a5169ac6f34e97a1bacf8d0c29d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Nov 17 11:46:27 2023 +0100

    s3:selftest: add samba3.blackbox.smbXsrv_client_ctdb_registered_ips
    
    This demonstrates the crash that happens if a client connects to a
    non-public address first followed by a connect
    to public address with the same client_guid and a connection to
    the non-public address gets disconnected first, we hit by a
    use-after-free talloc_get_type_abort() called from release_ip() as
    "xconn" is already gone, taking smbd_release_ip_state with it.
    
    Note that we also need to mark some subtests as flapping
    as there's a 2nd problem that happens in the interaction
    between smbd processes and ctdb when passing a multichannel
    connection to an existing process, it means we sometimes
    loose the 'tickle' information within ctdb to that tcp connection.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 082c7df4d04c2a94c5413c1d6b7eae7be610f950)

commit d96cb627b66d4c63d0407f4e434b429bb03a47af
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Nov 17 11:45:30 2023 +0100

    selftest: export/use CTDB related envvars in order to run the ctdb command
    
    This makes it easier to test things...
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 38b74d4ca9a59e7f12850c20c410f9df26cbad0a)

commit 8add947b2127e3a2dd2fd515d7701c396733f8e4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 20 14:57:46 2023 +0100

    ctdbd_conn: add ctdbd_passed_ips()
    
    This is similar to ctdbd_unregister_ips(), but with the
    difference that ctdb keeps the 'tickle' information for
    the tcp connection alive, because another smbd process
    took care of that tcp connection in a multichannel scenario.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 2e784789d78d09dfbc599085e5eb1c70c5b866b8)

commit e3a4feda112a174eebf9c866032aff899202eed7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Nov 16 13:18:03 2023 +0100

    ctdbd_conn: add ctdbd_unregister_ips()
    
    This reverts the effect of ctdbd_register_ips().
    We'll use this in order to disconnect individual
    multichannel connections.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit f3a03f3f774f0795fc1a163f12cccb9cedeebec1)

commit acf080817b538968d6e7cbcd5a037399c9a66c28
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 12 17:11:42 2023 +0200

    ctdbd_conn: Add deregister_from_ctdbd()
    
    This is to remove a callback during rundown of smbds.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 75aa6693940201a928b46f6880b43820c0e1c555)

commit d039fa07f7ee1f0eed6777f812a0ba4913e76ac7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Nov 16 13:04:12 2023 +0100

    ctdbd_conn: let register_with_ctdbd() call CTDB_CONTROL_REGISTER_SRVID just once
    
    We do the dispatching to multiple handlers in ctdbd_msg_call_back()
    and we don't need more than one message from ctdb.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 77a559432ffde2d435e29bed126d20a09d33f48e)

commit e09f92422ebff3454332ebbb28d578d8103e7203
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Nov 16 13:29:18 2023 +0100

    ctdbd_conn: don't use uninitialized memory in ctdbd_register_ips()
    
    We dump the structure into the socket, so we need to zero the content
    including possible padding.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 240139370aa19f53dd3de0ff468afd994d3bd973)

commit 118d6c81ec9fd19a98d5f674ccff2a57aed81881
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Nov 17 15:59:57 2023 +0100

    ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED
    
    With multichannel a tcp connection is registered first with
    a temporary smbd process, that calls CTDB_CONTROL_TCP_CLIENT
    first and then passes the tcp connection to the longterm smbd
    that already handles all connections belonging to the specific
    client_guid. That smbd process calls CTDB_CONTROL_TCP_CLIENT
    again, but the 'tickle' information is already there.
    When the temporary smbd process exists/disconnects from ctdb
    or calls CTDB_CONTROL_TCP_CLIENT_DISCONNECTED, the 'tickle'
    information is removed, while the longterm smbd process
    still serves the tcp connection.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 037e8e449deb136ad5ed5e4de05439411b545b6d)

commit b6906f37c667677dcac9bcfd6cc182869cb6f569
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Nov 15 16:31:53 2023 +0100

    ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_DISCONNECTED
    
    With multichannel a ctdb connection from smbd may hold multiple
    tcp connections, which can be disconnected before the smbd
    process terminates the whole ctdb connection, so we a
    way to remove undo 'CTDB_CONTROL_TCP_CLIENT' again.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit c6602b686b4e50d93272667ef86d3904181fb1ab)

commit 24bd10ebfc12a150bee214f830c328d61c42e591
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 12 13:39:21 2023 +0100

    ctdb: add ctdb_connection_same() helper
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 8395fd369d3c9d216817e922423727748581f133)

commit 0d6a38604b247d94869d80a2caf310175a27f605
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 12 13:27:17 2023 +0100

    ctdb: make use of ctdb_canonicalize_ip_inplace() in ctdb_control_tcp_client()
    
    We could also remove the src_addr and dest_addr helper variables
    completely, but that would be too much for this commit.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 5f52d140f7b676ed68b5ce49d4445357bcbcb1a6)

commit 69c4f498c84f42626efd71773a5e4509cbfaf29f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 12 13:26:46 2023 +0100

    ctdb: add ctdb_canonicalize_ip_inplace() helper
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit f2d9c012fc803b48564c3203ed640c02f99bcbaa)

commit 38134f374ca5c76cf636dd9d10ab8e2cf5e4bf1e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Nov 16 11:56:59 2023 +0100

    ctdb: remove unused ctdb->client_ip_list and print debug on ctdb_tcp_list instead
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    (cherry picked from commit 92badd3bdd82d1fa79727efcf81b6f479016811f)

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

Summary of changes:
 ctdb/common/common.h                               |   1 +
 ctdb/common/ctdb_util.c                            |   7 +
 ctdb/include/ctdb_private.h                        |   7 +-
 ctdb/protocol/protocol.h                           |   2 +
 ctdb/protocol/protocol_control.c                   |  30 +++
 ctdb/protocol/protocol_debug.c                     |   2 +
 ctdb/protocol/protocol_util.c                      |  18 ++
 ctdb/protocol/protocol_util.h                      |   3 +
 ctdb/server/ctdb_control.c                         |   8 +
 ctdb/server/ctdb_takeover.c                        | 292 ++++++++++++++-------
 selftest/target/Samba.pm                           |  19 ++
 selftest/target/Samba3.pm                          |  22 +-
 source3/include/ctdbd_conn.h                       |  32 +++
 source3/lib/ctdb_dummy.c                           |  42 +++
 source3/lib/ctdbd_conn.c                           | 228 +++++++++++++++-
 .../test_smbXsrv_client_ctdb_registered_ips.sh     | 159 +++++++++++
 source3/selftest/tests.py                          |   8 +-
 source3/smbd/smb2_negprot.c                        |   7 +
 source3/smbd/smb2_process.c                        |  33 +++
 19 files changed, 808 insertions(+), 112 deletions(-)
 create mode 100755 source3/script/tests/test_smbXsrv_client_ctdb_registered_ips.sh


Changeset truncated at 500 lines:

diff --git a/ctdb/common/common.h b/ctdb/common/common.h
index c50b52a5eb5..9a73bec1ac6 100644
--- a/ctdb/common/common.h
+++ b/ctdb/common/common.h
@@ -132,6 +132,7 @@ struct ctdb_rec_data_old *ctdb_marshall_loop_next(
 					TDB_DATA *key, TDB_DATA *data);
 
 void ctdb_canonicalize_ip(const ctdb_sock_addr *ip, ctdb_sock_addr *cip);
+void ctdb_canonicalize_ip_inplace(ctdb_sock_addr *ip);
 
 bool ctdb_same_ip(const ctdb_sock_addr *tip1, const ctdb_sock_addr *tip2);
 
diff --git a/ctdb/common/ctdb_util.c b/ctdb/common/ctdb_util.c
index 3f8fff925f0..5c7731c5d2a 100644
--- a/ctdb/common/ctdb_util.c
+++ b/ctdb/common/ctdb_util.c
@@ -388,6 +388,13 @@ void ctdb_canonicalize_ip(const ctdb_sock_addr *ip, ctdb_sock_addr *cip)
 	}
 }
 
+void ctdb_canonicalize_ip_inplace(ctdb_sock_addr *ip)
+{
+	ctdb_sock_addr tmp;
+	ctdb_canonicalize_ip(ip, &tmp);
+	memcpy(ip, &tmp, sizeof(tmp));
+}
+
 bool ctdb_same_ip(const ctdb_sock_addr *tip1, const ctdb_sock_addr *tip2)
 {
 	ctdb_sock_addr ip1, ip2;
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index 3395f077ab9..80278123778 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -296,7 +296,6 @@ struct ctdb_context {
 	struct ctdb_statistics statistics_history[MAX_STAT_HISTORY];
 	struct ctdb_vnn_map *vnn_map;
 	uint32_t num_clients;
-	struct ctdb_client_ip *client_ip_list;
 	bool do_checkpublicip;
 	bool do_setsched;
 	const char *event_script_dir;
@@ -893,6 +892,12 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses);
 
 int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 				TDB_DATA indata);
+int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb,
+					     uint32_t client_id,
+					     TDB_DATA indata);
+int32_t ctdb_control_tcp_client_passed(struct ctdb_context *ctdb,
+				       uint32_t client_id,
+				       TDB_DATA indata);
 int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata,
 			     bool tcp_update_needed);
 int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata);
diff --git a/ctdb/protocol/protocol.h b/ctdb/protocol/protocol.h
index fb6e39f33b5..3b66c403ab8 100644
--- a/ctdb/protocol/protocol.h
+++ b/ctdb/protocol/protocol.h
@@ -381,6 +381,8 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS          = 0,
 		    CTDB_CONTROL_ECHO_DATA               = 156,
 		    CTDB_CONTROL_DISABLE_NODE            = 157,
 		    CTDB_CONTROL_ENABLE_NODE             = 158,
+		    CTDB_CONTROL_TCP_CLIENT_DISCONNECTED = 159,
+		    CTDB_CONTROL_TCP_CLIENT_PASSED       = 160,
 };
 
 #define MAX_COUNT_BUCKETS 16
diff --git a/ctdb/protocol/protocol_control.c b/ctdb/protocol/protocol_control.c
index a7c797f5dbc..83ed6cb4ee1 100644
--- a/ctdb/protocol/protocol_control.c
+++ b/ctdb/protocol/protocol_control.c
@@ -410,6 +410,14 @@ static size_t ctdb_req_control_data_len(struct ctdb_req_control_data *cd)
 
 	case CTDB_CONTROL_ENABLE_NODE:
 		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED:
+		len = ctdb_connection_len(cd->data.conn);
+		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_PASSED:
+		len = ctdb_connection_len(cd->data.conn);
+		break;
 	}
 
 	return len;
@@ -1016,6 +1024,22 @@ static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen,
 					  &cd->data.echo_data,
 					  &np);
 		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED:
+		ret = ctdb_connection_pull(buf,
+					   buflen,
+					   mem_ctx,
+					   &cd->data.conn,
+					   &np);
+		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_PASSED:
+		ret = ctdb_connection_pull(buf,
+					   buflen,
+					   mem_ctx,
+					   &cd->data.conn,
+					   &np);
+		break;
 	}
 
 	if (ret != 0) {
@@ -1376,6 +1400,12 @@ static size_t ctdb_reply_control_data_len(struct ctdb_reply_control_data *cd)
 
 	case CTDB_CONTROL_ENABLE_NODE:
 		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED:
+		break;
+
+	case CTDB_CONTROL_TCP_CLIENT_PASSED:
+		break;
 	}
 
 	return len;
diff --git a/ctdb/protocol/protocol_debug.c b/ctdb/protocol/protocol_debug.c
index d94cb548d68..ae091b04d32 100644
--- a/ctdb/protocol/protocol_debug.c
+++ b/ctdb/protocol/protocol_debug.c
@@ -245,6 +245,8 @@ static void ctdb_opcode_print(uint32_t opcode, FILE *fp)
 		{ CTDB_CONTROL_ECHO_DATA, "ECHO_DATA" },
 		{ CTDB_CONTROL_DISABLE_NODE, "DISABLE_NODE" },
 		{ CTDB_CONTROL_ENABLE_NODE, "ENABLE_NODE" },
+		{ CTDB_CONTROL_TCP_CLIENT_DISCONNECTED, "TCP_CLIENT_DISCONNECTED" },
+		{ CTDB_CONTROL_TCP_CLIENT_PASSED, "TCP_CLIENT_PASSED" },
 		{ MAP_END, "" },
 	};
 
diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c
index fe757658f48..87ecc87ac36 100644
--- a/ctdb/protocol/protocol_util.c
+++ b/ctdb/protocol/protocol_util.c
@@ -497,6 +497,24 @@ bool ctdb_sock_addr_same(const ctdb_sock_addr *addr1,
 	return (ctdb_sock_addr_cmp(addr1, addr2) == 0);
 }
 
+bool ctdb_connection_same(const struct ctdb_connection *conn1,
+			  const struct ctdb_connection *conn2)
+{
+	bool same;
+
+	same = ctdb_sock_addr_same(&conn1->src, &conn2->src);
+	if (!same) {
+		return false;
+	}
+
+	same = ctdb_sock_addr_same(&conn1->dst, &conn2->dst);
+	if (!same) {
+		return false;
+	}
+
+	return true;
+}
+
 int ctdb_connection_to_buf(char *buf,
 			   size_t buflen,
 			   struct ctdb_connection *conn,
diff --git a/ctdb/protocol/protocol_util.h b/ctdb/protocol/protocol_util.h
index 2bdbb0c2ad0..70f35d122a8 100644
--- a/ctdb/protocol/protocol_util.h
+++ b/ctdb/protocol/protocol_util.h
@@ -55,6 +55,9 @@ bool ctdb_sock_addr_same_ip(const ctdb_sock_addr *addr1,
 bool ctdb_sock_addr_same(const ctdb_sock_addr *addr1,
 			 const ctdb_sock_addr *addr2);
 
+bool ctdb_connection_same(const struct ctdb_connection *conn1,
+			  const struct ctdb_connection *conn2);
+
 int ctdb_connection_to_buf(char *buf,
 			   size_t buflen,
 			   struct ctdb_connection * conn,
diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c
index 08268512bfa..422c4cf1e58 100644
--- a/ctdb/server/ctdb_control.c
+++ b/ctdb/server/ctdb_control.c
@@ -868,6 +868,14 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 		CHECK_CONTROL_DATA_SIZE(0);
 		return ctdb_control_enable_node(ctdb);
 
+	case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED:
+		CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_connection));
+		return ctdb_control_tcp_client_disconnected(ctdb, client_id, indata);
+
+	case CTDB_CONTROL_TCP_CLIENT_PASSED:
+		CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_connection));
+		return ctdb_control_tcp_client_passed(ctdb, client_id, indata);
+
 	default:
 		DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
 		return -1;
diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c
index 26cca1aefff..e333105e633 100644
--- a/ctdb/server/ctdb_takeover.c
+++ b/ctdb/server/ctdb_takeover.c
@@ -348,20 +348,10 @@ struct ctdb_takeover_arp {
  */
 struct ctdb_tcp_list {
 	struct ctdb_tcp_list *prev, *next;
+	struct ctdb_client *client;
 	struct ctdb_connection connection;
 };
 
-/*
-  list of clients to kill on IP release
- */
-struct ctdb_client_ip {
-	struct ctdb_client_ip *prev, *next;
-	struct ctdb_context *ctdb;
-	ctdb_sock_addr addr;
-	uint32_t client_id;
-};
-
-
 /*
   send a gratuitous arp
  */
@@ -1233,16 +1223,37 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses)
 }
 
 /*
-  destroy a ctdb_client_ip structure
+  destroy a ctdb_tcp_list structure
  */
-static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip)
+static int ctdb_tcp_list_destructor(struct ctdb_tcp_list *tcp)
 {
-	DEBUG(DEBUG_DEBUG,("destroying client tcp for %s:%u (client_id %u)\n",
-		ctdb_addr_to_str(&ip->addr),
-		ntohs(ip->addr.ip.sin_port),
-		ip->client_id));
+	struct ctdb_client *client = tcp->client;
+	struct ctdb_connection *conn = &tcp->connection;
+	char conn_str[132] = { 0, };
+	int ret;
+
+	ret = ctdb_connection_to_buf(conn_str,
+				     sizeof(conn_str),
+				     conn,
+				     false,
+				     " -> ");
+	if (ret != 0) {
+		strlcpy(conn_str, "UNKNOWN", sizeof(conn_str));
+	}
+
+	D_DEBUG("removing client TCP connection %s "
+		"(client_id %u pid %d)\n",
+		conn_str, client->client_id, client->pid);
+
+	DLIST_REMOVE(client->tcp_list, tcp);
+
+	/*
+	 * We don't call ctdb_remove_connection(vnn, conn) here
+	 * as we want the caller to decide if it's called
+	 * directly (local only) or indirectly via a
+	 * CTDB_CONTROL_TCP_REMOVE broadcast
+	 */
 
-	DLIST_REMOVE(ip->ctdb->client_ip_list, ip);
 	return 0;
 }
 
@@ -1259,10 +1270,8 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 	struct ctdb_connection t;
 	int ret;
 	TDB_DATA data;
-	struct ctdb_client_ip *ip;
 	struct ctdb_vnn *vnn;
-	ctdb_sock_addr src_addr;
-	ctdb_sock_addr dst_addr;
+	char conn_str[132] = { 0, };
 
 	/* If we don't have public IPs, tickles are useless */
 	if (ctdb->vnn == NULL) {
@@ -1271,75 +1280,44 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 
 	tcp_sock = (struct ctdb_connection *)indata.dptr;
 
-	src_addr = tcp_sock->src;
-	ctdb_canonicalize_ip(&src_addr,  &tcp_sock->src);
-	ZERO_STRUCT(src_addr);
-	memcpy(&src_addr, &tcp_sock->src, sizeof(src_addr));
+	ctdb_canonicalize_ip_inplace(&tcp_sock->src);
+	ctdb_canonicalize_ip_inplace(&tcp_sock->dst);
 
-	dst_addr = tcp_sock->dst;
-	ctdb_canonicalize_ip(&dst_addr, &tcp_sock->dst);
-	ZERO_STRUCT(dst_addr);
-	memcpy(&dst_addr, &tcp_sock->dst, sizeof(dst_addr));
+	ret = ctdb_connection_to_buf(conn_str,
+				     sizeof(conn_str),
+				     tcp_sock,
+				     false,
+				     " -> ");
+	if (ret != 0) {
+		strlcpy(conn_str, "UNKNOWN", sizeof(conn_str));
+	}
 
-	vnn = find_public_ip_vnn(ctdb, &dst_addr);
+	vnn = find_public_ip_vnn(ctdb, &tcp_sock->dst);
 	if (vnn == NULL) {
-		char *src_addr_str = NULL;
-		char *dst_addr_str = NULL;
-
-		switch (dst_addr.sa.sa_family) {
-		case AF_INET:
-			if (ntohl(dst_addr.ip.sin_addr.s_addr) == INADDR_LOOPBACK) {
-				/* ignore ... */
-				return 0;
-			}
-			break;
-		case AF_INET6:
-			break;
-		default:
-			DEBUG(DEBUG_ERR,(__location__ " Unknown family type %d\n",
-			      dst_addr.sa.sa_family));
-			return 0;
-		}
-
-		src_addr_str = ctdb_sock_addr_to_string(client, &src_addr, false);
-		dst_addr_str = ctdb_sock_addr_to_string(client, &dst_addr, false);
-		DEBUG(DEBUG_ERR,(
-		      "Could not register TCP connection from "
-		      "%s to %s (not a public address) (port %u) "
-		      "(client_id %u pid %u).\n",
-		      src_addr_str,
-		      dst_addr_str,
-		      ctdb_sock_addr_port(&dst_addr),
-		      client_id, client->pid));
-		TALLOC_FREE(src_addr_str);
-		TALLOC_FREE(dst_addr_str);
+		D_ERR("Could not register TCP connection %s - "
+		      "not a public address (client_id %u pid %u)\n",
+			conn_str, client_id, client->pid);
 		return 0;
 	}
 
 	if (vnn->pnn != ctdb->pnn) {
-		DEBUG(DEBUG_ERR,("Attempt to register tcp client for IP %s we don't hold - failing (client_id %u pid %u)\n",
-			ctdb_addr_to_str(&dst_addr),
-			client_id, client->pid));
+		D_ERR("Attempt to register tcp client for IP %s we don't hold - "
+		      "failing (client_id %u pid %u)\n",
+		      ctdb_addr_to_str(&tcp_sock->dst),
+		      client_id, client->pid);
 		/* failing this call will tell smbd to die */
 		return -1;
 	}
 
-	ip = talloc(client, struct ctdb_client_ip);
-	CTDB_NO_MEMORY(ctdb, ip);
-
-	ip->ctdb      = ctdb;
-	ip->addr      = dst_addr;
-	ip->client_id = client_id;
-	talloc_set_destructor(ip, ctdb_client_ip_destructor);
-	DLIST_ADD(ctdb->client_ip_list, ip);
-
 	tcp = talloc(client, struct ctdb_tcp_list);
 	CTDB_NO_MEMORY(ctdb, tcp);
+	tcp->client = client;
 
 	tcp->connection.src = tcp_sock->src;
 	tcp->connection.dst = tcp_sock->dst;
 
 	DLIST_ADD(client->tcp_list, tcp);
+	talloc_set_destructor(tcp, ctdb_tcp_list_destructor);
 
 	t.src = tcp_sock->src;
 	t.dst = tcp_sock->dst;
@@ -1347,24 +1325,8 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 	data.dptr = (uint8_t *)&t;
 	data.dsize = sizeof(t);
 
-	switch (dst_addr.sa.sa_family) {
-	case AF_INET:
-		DEBUG(DEBUG_INFO,("registered tcp client for %u->%s:%u (client_id %u pid %u)\n",
-			(unsigned)ntohs(tcp_sock->dst.ip.sin_port),
-			ctdb_addr_to_str(&tcp_sock->src),
-			(unsigned)ntohs(tcp_sock->src.ip.sin_port), client_id, client->pid));
-		break;
-	case AF_INET6:
-		DEBUG(DEBUG_INFO,("registered tcp client for %u->%s:%u (client_id %u pid %u)\n",
-			(unsigned)ntohs(tcp_sock->dst.ip6.sin6_port),
-			ctdb_addr_to_str(&tcp_sock->src),
-			(unsigned)ntohs(tcp_sock->src.ip6.sin6_port), client_id, client->pid));
-		break;
-	default:
-		DEBUG(DEBUG_ERR,(__location__ " Unknown family %d\n",
-		      dst_addr.sa.sa_family));
-	}
-
+	D_INFO("Registered TCP connection %s (client_id %u pid %u)\n",
+	       conn_str, client_id, client->pid);
 
 	/* tell all nodes about this tcp connection */
 	ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0, 
@@ -1378,6 +1340,141 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
 	return 0;
 }
 
+static bool ctdb_client_remove_tcp(struct ctdb_client *client,
+				   const struct ctdb_connection *conn)
+{
+	struct ctdb_tcp_list *tcp = NULL;
+	struct ctdb_tcp_list *tcp_next = NULL;
+	bool found = false;
+
+	for (tcp = client->tcp_list; tcp != NULL; tcp = tcp_next) {
+		bool same;
+
+		tcp_next = tcp->next;
+
+		same = ctdb_connection_same(conn, &tcp->connection);
+		if (!same) {
+			continue;
+		}
+
+		TALLOC_FREE(tcp);
+		found = true;
+	}
+
+	return found;
+}
+
+/*
+  called by a client to inform us of a TCP connection that was disconnected
+ */
+int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb,
+					     uint32_t client_id,
+					     TDB_DATA indata)
+{
+	struct ctdb_client *client = reqid_find(ctdb->idr, client_id, struct ctdb_client);
+	struct ctdb_connection *tcp_sock = NULL;
+	int ret;
+	TDB_DATA data;
+	char conn_str[132] = { 0, };
+	bool found = false;
+
+	tcp_sock = (struct ctdb_connection *)indata.dptr;
+
+	ctdb_canonicalize_ip_inplace(&tcp_sock->src);
+	ctdb_canonicalize_ip_inplace(&tcp_sock->dst);
+
+	ret = ctdb_connection_to_buf(conn_str,
+				     sizeof(conn_str),
+				     tcp_sock,
+				     false,
+				     " -> ");
+	if (ret != 0) {
+		strlcpy(conn_str, "UNKNOWN", sizeof(conn_str));
+	}
+
+	found = ctdb_client_remove_tcp(client, tcp_sock);
+	if (!found) {
+		DBG_DEBUG("TCP connection %s not found "
+			  "(client_id %u pid %u).\n",
+			  conn_str, client_id, client->pid);
+		return 0;
+	}
+
+	D_INFO("deregistered TCP connection %s "
+	       "(client_id %u pid %u)\n",
+	       conn_str, client_id, client->pid);
+
+	data.dptr = (uint8_t *)tcp_sock;
+	data.dsize = sizeof(*tcp_sock);
+
+	/* tell all nodes about this tcp connection is gone */
+	ret = ctdb_daemon_send_control(ctdb,
+				       CTDB_BROADCAST_CONNECTED,
+				       0,
+				       CTDB_CONTROL_TCP_REMOVE,
+				       0,
+				       CTDB_CTRL_FLAG_NOREPLY,
+				       data,
+				       NULL,
+				       NULL);
+	if (ret != 0) {
+		DBG_ERR("Failed to send CTDB_CONTROL_TCP_REMOVE: %s\n",
+			conn_str);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+  called by a client to inform us of a TCP connection was passed to a different
+  "client" (typically with multichannel to another smbd process).
+ */
+int32_t ctdb_control_tcp_client_passed(struct ctdb_context *ctdb,
+				       uint32_t client_id,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list