From: Martin Schwenke Date: Thu, 3 Oct 2024 05:07:40 +0000 (+1000) Subject: ctdb-tcp: Only attempt to automatically bind to local IPs X-Git-Tag: tdb-1.4.13~996 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=939e5bdfd20b4029cc90d7d378319b26ed454dcc;p=thirdparty%2Fsamba.git ctdb-tcp: Only attempt to automatically bind to local IPs Automatic node address selection in the TCP transport does not work if net.ipv4.ip_nonlocal_bind=1 because all nodes will be able to bind() to the first address in the nodes list. Before getting to the bind() step, add a check to see if an address is local (i.e. on an interface). If not, it is not considered. This is defensively coded so that this step is skipped if local addresses can not be retrieved. Signed-off-by: Martin Schwenke Reviewed-by: John Mulligan Reviewed-by: Anoop C S --- diff --git a/ctdb/doc/ctdb.conf.5.xml b/ctdb/doc/ctdb.conf.5.xml index 615a61e5bfe..7bdbc038f7d 100644 --- a/ctdb/doc/ctdb.conf.5.xml +++ b/ctdb/doc/ctdb.conf.5.xml @@ -241,9 +241,11 @@ This option is only required when automatic address detection can not be used. This can be the case when running multiple ctdbd daemons/nodes on the same physical - host (usually for testing), using InfiniBand for the - private network or on Linux when sysctl - net.ipv4.ip_nonlocal_bind=1. + host (usually for testing) or using InfiniBand for the + private network. Another unlikely possibility would be + running on a platform with a feature like Linux's + net.ipv4.ip_nonlocal_bind=1 enabled and no usable + getifaddrs(3) implementation (or replacement) available. Default: CTDB selects the first address from the nodes diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 1ad3fa74d55..ca3d8a8c788 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -32,6 +32,7 @@ #include "ctdb_private.h" #include "common/system.h" +#include "common/system_socket.h" #include "common/common.h" #include "common/logging.h" #include "common/path.h" @@ -490,6 +491,7 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) unsigned int i; char *lock_path = NULL; struct flock lock; + struct ctdb_sys_local_ips_context *ips_ctx = NULL; int ret; /* @@ -534,11 +536,38 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) } talloc_free(lock_path); + ret = ctdb_sys_local_ips_init(ctdb, &ips_ctx); + if (ret != 0) { + /* + * What to do? The point here is to allow CTDB to + * bind to the local IP address from the nodes list if + * net.ipv4.ip_nonlocal_bind = 1, which probably just + * Linux... though other platforms may have a similar + * setting. Let's go ahead and skip checking + * addresses this way. That way, a platform with a + * replacement implementation of getifaddrs() that + * just returns, say, ENOSYS can still proceed and see + * if it can bind/listen on each address. + */ + DBG_WARNING( + "Failed to get local addresses, depending on bind\n"); + ips_ctx = NULL; /* Just in case */ + } + for (i=0; i < ctdb->num_nodes; i++) { if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) { continue; } + if (ips_ctx != NULL) { + bool have_ip = ctdb_sys_local_ip_check( + ips_ctx, &ctdb->nodes[i]->address); + + if (!have_ip) { + continue; + } + } + ret = ctdb_tcp_listen_addr(ctdb, &ctdb->nodes[i]->address, false); @@ -547,6 +576,8 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) } } + TALLOC_FREE(ips_ctx); + if (i == ctdb->num_nodes) { D_ERR("Unable to bind to any node address - giving up\n"); return -1; diff --git a/ctdb/wscript b/ctdb/wscript index 13cbfb267a5..74ad9af2a89 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -400,7 +400,13 @@ def build(bld): source=bld.SUBDIR('tcp', 'tcp_connect.c tcp_init.c tcp_io.c'), includes='include', - deps='replace tdb talloc tevent ctdb-protocol-util') + deps='''ctdb-protocol-util + ctdb-system + replace + talloc + tdb + tevent + ''') ib_deps = '' if bld.env.HAVE_INFINIBAND: