From: David Disseldorp Date: Sun, 6 Sep 2020 22:17:11 +0000 (+0200) Subject: s3:ctdbd_conn: simplify get_public_ips() / find_in_public_ips() API X-Git-Tag: talloc-2.3.2~266 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6b9564c1084d8dc7319857fac984808571ef0eb9;p=thirdparty%2Fsamba.git s3:ctdbd_conn: simplify get_public_ips() / find_in_public_ips() API These calls are used to check whether an IP address is static to the host, or whether it could be migrated by ctdb. Combine the calls into a simple ctdbd_public_ip_foreach(cb) function, which avoids the need to expose struct ctdb_public_ip_list_old. Signed-off-by: David Disseldorp Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Oct 14 12:29:56 UTC 2020 on sn-devel-184 --- diff --git a/source3/include/ctdbd_conn.h b/source3/include/ctdbd_conn.h index b77dd06fd09..74db96e89e7 100644 --- a/source3/include/ctdbd_conn.h +++ b/source3/include/ctdbd_conn.h @@ -85,13 +85,20 @@ int ctdbd_register_ips(struct ctdbd_connection *conn, void *private_data), void *private_data); -struct ctdb_public_ip_list_old; -int ctdbd_control_get_public_ips(struct ctdbd_connection *conn, - uint32_t flags, - TALLOC_CTX *mem_ctx, - struct ctdb_public_ip_list_old **_ips); -bool ctdbd_find_in_public_ips(const struct ctdb_public_ip_list_old *ips, - const struct sockaddr_storage *ip); +/* + * call @cb for each public IP. If @cb returns non-zero, then break the loop + * and propagate the return value upwards. + * @returns: 0 on success, where all @cb invocations also returned zero + * ENOMEM on memory allocation failure + * EIO on ctdbd connection failure + * @cb() return value if non-zero + */ +int ctdbd_public_ip_foreach(struct ctdbd_connection *conn, + int (*cb)(uint32_t total_ip_count, + const struct sockaddr_storage *ip, + bool is_movable_ip, + void *private_data), + void *private_data); int ctdbd_control_local(struct ctdbd_connection *conn, uint32_t opcode, uint64_t srvid, uint32_t flags, TDB_DATA data, diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c index 062fa999b06..294d178966b 100644 --- a/source3/lib/ctdb_dummy.c +++ b/source3/lib/ctdb_dummy.c @@ -62,21 +62,16 @@ int ctdbd_register_ips(struct ctdbd_connection *conn, return ENOSYS; } -int ctdbd_control_get_public_ips(struct ctdbd_connection *conn, - uint32_t flags, - TALLOC_CTX *mem_ctx, - struct ctdb_public_ip_list_old **_ips) +int ctdbd_public_ip_foreach(struct ctdbd_connection *conn, + int (*cb)(uint32_t total_ip_count, + const struct sockaddr_storage *ip, + bool is_movable_ip, + void *private_data), + void *private_data) { - *_ips = NULL; return ENOSYS; } -bool ctdbd_find_in_public_ips(const struct ctdb_public_ip_list_old *ips, - const struct sockaddr_storage *ip) -{ - return false; -} - bool ctdbd_process_exists(struct ctdbd_connection *conn, uint32_t vnn, pid_t pid, uint64_t unique_id) { diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index a4a9f4e0cae..8fe94226590 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -1179,10 +1179,10 @@ int ctdbd_register_ips(struct ctdbd_connection *conn, return 0; } -int ctdbd_control_get_public_ips(struct ctdbd_connection *conn, - uint32_t flags, - TALLOC_CTX *mem_ctx, - struct ctdb_public_ip_list_old **_ips) +static int ctdbd_control_get_public_ips(struct ctdbd_connection *conn, + uint32_t flags, + TALLOC_CTX *mem_ctx, + struct ctdb_public_ip_list_old **_ips) { struct ctdb_public_ip_list_old *ips = NULL; TDB_DATA outdata; @@ -1225,27 +1225,44 @@ int ctdbd_control_get_public_ips(struct ctdbd_connection *conn, return 0; } -bool ctdbd_find_in_public_ips(const struct ctdb_public_ip_list_old *ips, - const struct sockaddr_storage *ip) +int ctdbd_public_ip_foreach(struct ctdbd_connection *conn, + int (*cb)(uint32_t total_ip_count, + const struct sockaddr_storage *ip, + bool is_movable_ip, + void *private_data), + void *private_data) { uint32_t i; + struct ctdb_public_ip_list_old *ips = NULL; + int ret = ENOMEM; + TALLOC_CTX *frame = talloc_stackframe(); + + ret = ctdbd_control_get_public_ips(conn, 0, frame, &ips); + if (ret < 0) { + ret = EIO; + goto out_free; + } for (i=0; i < ips->num; i++) { struct samba_sockaddr tmp = { .u = { - .ss = *ip, + .sa = ips->ips[i].addr.sa, }, }; - bool match; - match = sockaddr_equal(&ips->ips[i].addr.sa, - &tmp.u.sa); - if (match) { - return true; + ret = cb(ips->num, + &tmp.u.ss, + true, /* all ctdb public ips are movable */ + private_data); + if (ret != 0) { + goto out_free; } } - return false; + ret = 0; +out_free: + TALLOC_FREE(frame); + return ret; } /* diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7511b615520..4cf53720067 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2776,6 +2776,30 @@ static int release_ip(struct tevent_context *ev, return 0; } +static int match_cluster_movable_ip(uint32_t total_ip_count, + const struct sockaddr_storage *ip, + bool is_movable_ip, + void *private_data) +{ + const struct sockaddr_storage *srv = private_data; + struct samba_sockaddr pub_ip = { + .u = { + .ss = *ip, + }, + }; + struct samba_sockaddr srv_ip = { + .u = { + .ss = *srv, + }, + }; + + if (is_movable_ip && sockaddr_equal(&pub_ip.u.sa, &srv_ip.u.sa)) { + return EREMOTEIO; + } + + return 0; +} + static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn, struct sockaddr_storage *srv, struct sockaddr_storage *clnt) @@ -2803,21 +2827,17 @@ static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn, } if (xconn->client->server_multi_channel_enabled) { - struct ctdb_public_ip_list_old *ips = NULL; - - ret = ctdbd_control_get_public_ips(cconn, - 0, /* flags */ - state, - &ips); - if (ret != 0) { - return NT_STATUS_INTERNAL_ERROR; - } - - xconn->has_cluster_movable_ip = ctdbd_find_in_public_ips(ips, srv); - TALLOC_FREE(ips); - if (xconn->has_cluster_movable_ip) { + ret = ctdbd_public_ip_foreach(cconn, + match_cluster_movable_ip, + srv); + if (ret == EREMOTEIO) { + xconn->has_cluster_movable_ip = true; DBG_DEBUG("cluster movable IP on %s\n", smbXsrv_connection_dbg(xconn)); + } else if (ret != 0) { + DBG_ERR("failed to iterate cluster IPs: %s\n", + strerror(ret)); + return NT_STATUS_INTERNAL_ERROR; } } diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c index 0c32f36dcae..ceb57cefb06 100644 --- a/source3/smbd/smb2_ioctl_network_fs.c +++ b/source3/smbd/smb2_ioctl_network_fs.c @@ -291,6 +291,70 @@ static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req, return status; } +struct cluster_movable_ips { + uint32_t array_len; + uint32_t array_index; + struct sockaddr_storage *ips; +}; + +static int stash_cluster_movable_ips(uint32_t total_ip_count, + const struct sockaddr_storage *ip, + bool is_movable_ip, + void *private_data) +{ + struct cluster_movable_ips *cluster_movable_ips + = talloc_get_type_abort(private_data, + struct cluster_movable_ips); + + if (!is_movable_ip) { + return 0; + } + + if (cluster_movable_ips->array_len == 0) { + SMB_ASSERT(total_ip_count < INT_MAX); + cluster_movable_ips->ips + = talloc_zero_array(cluster_movable_ips, + struct sockaddr_storage, + total_ip_count); + if (cluster_movable_ips->ips == NULL) { + return ENOMEM; + } + cluster_movable_ips->array_len = total_ip_count; + } + + SMB_ASSERT(cluster_movable_ips->array_index + < cluster_movable_ips->array_len); + + cluster_movable_ips->ips[cluster_movable_ips->array_index] = *ip; + cluster_movable_ips->array_index++; + + return 0; +} + +static bool find_in_cluster_movable_ips( + struct cluster_movable_ips *cluster_movable_ips, + const struct sockaddr_storage *ifss) +{ + struct samba_sockaddr srv_ip = { + .u = { + .ss = *ifss, + }, + }; + int i; + + for (i = 0; i < cluster_movable_ips->array_index; i++) { + struct samba_sockaddr pub_ip = { + .u = { + .ss = cluster_movable_ips->ips[i], + }, + }; + if (sockaddr_equal(&pub_ip.u.sa, &srv_ip.u.sa)) { + return true; + } + } + return false; +} + static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbXsrv_connection *xconn, @@ -304,7 +368,8 @@ static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, size_t i; size_t num_ifaces = iface_count(); enum ndr_err_code ndr_err; - struct ctdb_public_ip_list_old *ips = NULL; + struct cluster_movable_ips *cluster_movable_ips = NULL; + int ret; if (in_input->length != 0) { return NT_STATUS_INVALID_PARAMETER; @@ -312,18 +377,6 @@ static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, *out_output = data_blob_null; - if (lp_clustering()) { - int ret; - - ret = ctdbd_control_get_public_ips(messaging_ctdb_connection(), - 0, /* flags */ - mem_ctx, - &ips); - if (ret != 0) { - return NT_STATUS_INTERNAL_ERROR; - } - } - array = talloc_zero_array(mem_ctx, struct fsctl_net_iface_info, num_ifaces); @@ -331,6 +384,22 @@ static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + if (lp_clustering()) { + cluster_movable_ips = talloc_zero(array, + struct cluster_movable_ips); + if (cluster_movable_ips == NULL) { + TALLOC_FREE(array); + return NT_STATUS_NO_MEMORY; + } + ret = ctdbd_public_ip_foreach(messaging_ctdb_connection(), + stash_cluster_movable_ips, + cluster_movable_ips); + if (ret != 0) { + TALLOC_FREE(array); + return NT_STATUS_INTERNAL_ERROR; + } + } + for (i=0; i < num_ifaces; i++) { struct fsctl_net_iface_info *cur = &array[i]; const struct interface *iface = get_interface(i); @@ -340,7 +409,6 @@ static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, struct tsocket_address *a = NULL; char *addr; bool ok; - int ret; ret = tsocket_address_bsd_from_sockaddr(array, ifsa, sizeof(struct sockaddr_storage), @@ -362,13 +430,13 @@ static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (ips != NULL) { - bool is_public_ip; - - is_public_ip = ctdbd_find_in_public_ips(ips, ifss); - if (is_public_ip) { + if (cluster_movable_ips != NULL) { + bool is_movable_ip = find_in_cluster_movable_ips( + cluster_movable_ips, + ifss); + if (is_movable_ip) { DBG_DEBUG("Interface [%s] - " - "has public ip - " + "has movable public ip - " "skipping address [%s].\n", iface->name, addr); continue;