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

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


The branch, v4-18-test has been updated
       via  a149a96eaf2 ctdb-server: Drop unnecessary copy of destination address
       via  ff4ed4d760a ctdb-daemon: Use ctdb_connection_to_buf() to simplify
       via  279187965b8 smbd: Remove callback for release_ip when "state" is free'ed
       via  f8c02609f48 s3:selftest: add samba3.blackbox.smbXsrv_client_ctdb_registered_ips
       via  d9ed96c908c selftest: export/use CTDB related envvars in order to run the ctdb command
       via  6ca3ce4db30 ctdbd_conn: add ctdbd_passed_ips()
       via  18d34cea2a1 ctdbd_conn: add ctdbd_unregister_ips()
       via  ecc0acbbff2 ctdbd_conn: Add deregister_from_ctdbd()
       via  562e360ed7c ctdbd_conn: let register_with_ctdbd() call CTDB_CONTROL_REGISTER_SRVID just once
       via  24d960d02b8 ctdbd_conn: don't use uninitialized memory in ctdbd_register_ips()
       via  813e7186719 ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED
       via  f7694157993 ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_DISCONNECTED
       via  0de804ac5d6 ctdb: add ctdb_connection_same() helper
       via  9d8768ffd35 ctdb: make use of ctdb_canonicalize_ip_inplace() in ctdb_control_tcp_client()
       via  d7249b3cbd2 ctdb: add ctdb_canonicalize_ip_inplace() helper
       via  30fddc01431 ctdb: remove unused ctdb->client_ip_list and print debug on ctdb_tcp_list instead
      from  849c370d92a vfs_ceph: call 'ceph_fgetxattr' only if valid fd

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


- Log -----------------------------------------------------------------
commit a149a96eaf250625b4be89aa1059330bd953a06c
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-18-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-18-test): Sat Dec 16 15:26:50 UTC 2023 on atb-devel-224

commit ff4ed4d760a61e59d2e23f1e3d956308585b846d
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 279187965b8b2adbd2939bf2a9e587edce04431d
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 f8c02609f4807435cbdee1d1433429a549fc981e
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 d9ed96c908cf83fc0765372c4e54919551fe94f5
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 6ca3ce4db30cf2d4cd906cf2a695bb928ec9f2ba
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 18d34cea2a19232dc30cbe45545885a6406e2be0
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 ecc0acbbff21ddae9b8b676993fa8ac20db4b55b
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 562e360ed7ce131e8e6f08d521aee2f21a1e0160
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 24d960d02b84a498cfacc5ee2b283d7bd5b2e1f6
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 813e7186719d8f0277671918fe00d407ab8d35d3
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 f769415799332387ea7b2daa73d47f2f18fbe386
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 0de804ac5d68af6b5ff7cf8fe227e4608d96ff55
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 9d8768ffd35f1a082bfda85274c08e8f3fe8e863
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 d7249b3cbd204a839c279e753d59c118b9b8dc8b
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 30fddc01431ace1ea345db0fcd96415cf60495f9
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 4d2d0416752..3ecb7382e2a 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