[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Fri Dec 15 12:10:01 UTC 2023


The branch, master has been updated
       via  4b7329f1582 ctdb-server: Drop unnecessary copy of destination address
       via  8fc3872557f ctdb-daemon: Use ctdb_connection_to_buf() to simplify
       via  ddf47e7fe31 smbd: Remove callback for release_ip when "state" is free'ed
       via  082c7df4d04 s3:selftest: add samba3.blackbox.smbXsrv_client_ctdb_registered_ips
       via  38b74d4ca9a selftest: export/use CTDB related envvars in order to run the ctdb command
       via  2e784789d78 ctdbd_conn: add ctdbd_passed_ips()
       via  f3a03f3f774 ctdbd_conn: add ctdbd_unregister_ips()
       via  75aa6693940 ctdbd_conn: Add deregister_from_ctdbd()
       via  77a559432ff ctdbd_conn: let register_with_ctdbd() call CTDB_CONTROL_REGISTER_SRVID just once
       via  240139370aa ctdbd_conn: don't use uninitialized memory in ctdbd_register_ips()
       via  037e8e449de ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED
       via  c6602b686b4 ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_DISCONNECTED
       via  8395fd369d3 ctdb: add ctdb_connection_same() helper
       via  5f52d140f7b ctdb: make use of ctdb_canonicalize_ip_inplace() in ctdb_control_tcp_client()
       via  f2d9c012fc8 ctdb: add ctdb_canonicalize_ip_inplace() helper
       via  92badd3bdd8 ctdb: remove unused ctdb->client_ip_list and print debug on ctdb_tcp_list instead
      from  d23d6145bf0 VERSION: move COPYRIGHT_STARTUP_MESSAGE as SAMBA_COPYRIGHT_STRING into version.h

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


- Log -----------------------------------------------------------------
commit 4b7329f15820f1b4d9a7b7f0947719c4217b312a
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

commit 8fc3872557f715dc38f9898754a785fd073ace96
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>

commit ddf47e7fe314e0f5bf71ff53e35350e0ba530d08
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>

commit 082c7df4d04c2a94c5413c1d6b7eae7be610f950
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>

commit 38b74d4ca9a59e7f12850c20c410f9df26cbad0a
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>

commit 2e784789d78d09dfbc599085e5eb1c70c5b866b8
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>

commit f3a03f3f774f0795fc1a163f12cccb9cedeebec1
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>

commit 75aa6693940201a928b46f6880b43820c0e1c555
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>

commit 77a559432ffde2d435e29bed126d20a09d33f48e
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>

commit 240139370aa19f53dd3de0ff468afd994d3bd973
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>

commit 037e8e449deb136ad5ed5e4de05439411b545b6d
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>

commit c6602b686b4e50d93272667ef86d3904181fb1ab
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>

commit 8395fd369d3c9d216817e922423727748581f133
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>

commit 5f52d140f7b676ed68b5ce49d4445357bcbcb1a6
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>

commit f2d9c012fc803b48564c3203ed640c02f99bcbaa
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>

commit 92badd3bdd82d1fa79727efcf81b6f479016811f
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>

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

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