]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:ctdbd_conn: simplify get_public_ips() / find_in_public_ips() API
authorDavid Disseldorp <ddiss@samba.org>
Sun, 6 Sep 2020 22:17:11 +0000 (00:17 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 14 Oct 2020 12:29:55 +0000 (12:29 +0000)
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 <ddiss@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Wed Oct 14 12:29:56 UTC 2020 on sn-devel-184

source3/include/ctdbd_conn.h
source3/lib/ctdb_dummy.c
source3/lib/ctdbd_conn.c
source3/smbd/process.c
source3/smbd/smb2_ioctl_network_fs.c

index b77dd06fd09e2145ec447e076b1095e748e86c07..74db96e89e7d750bddea66ff0059e4c0b0d063c4 100644 (file)
@@ -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,
index 062fa999b0635bb3d90025a6228720138793bb3d..294d178966b2ba92713f47b66d623f3ec0b7e750 100644 (file)
@@ -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)
 {
index a4a9f4e0caea0990360d03eb6a82615b09c55296..8fe942265900a136e4e585d4555376c066138c77 100644 (file)
@@ -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;
 }
 
 /*
index 7511b6155203d6abd64bbf38ff50ce9656bdbe44..4cf537200679a2c3bc7cadd9e0e6df66102ca893 100644 (file)
@@ -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;
                }
        }
 
index 0c32f36dcae6f16b24283a58a5b244066e4b6873..ceb57cefb06d6b6b65f15f5475f4e0e844872d72 100644 (file)
@@ -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;