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,
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)
{
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;
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;
}
/*
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)
}
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;
}
}
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,
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;
*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);
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);
struct tsocket_address *a = NULL;
char *addr;
bool ok;
- int ret;
ret = tsocket_address_bsd_from_sockaddr(array,
ifsa, sizeof(struct sockaddr_storage),
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;