]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ctdb-tcp: Only attempt to automatically bind to local IPs
authorMartin Schwenke <mschwenke@ddn.com>
Thu, 3 Oct 2024 05:07:40 +0000 (15:07 +1000)
committerAnoop C S <anoopcs@samba.org>
Mon, 7 Oct 2024 15:58:38 +0000 (15:58 +0000)
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 <mschwenke@ddn.com>
Reviewed-by: John Mulligan <jmulligan@redhat.com>
Reviewed-by: Anoop C S <anoopcs@samba.org>
ctdb/doc/ctdb.conf.5.xml
ctdb/tcp/tcp_connect.c
ctdb/wscript

index 615a61e5bfed0b8ba587bf7b88d126dd81753ad7..7bdbc038f7d25ce162415d805f619431ce02e092 100644 (file)
            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.
          </para>
          <para>
            Default: CTDB selects the first address from the nodes
index 1ad3fa74d55d3a4f7da892b45e4e2d2f33762076..ca3d8a8c788dd09ed1d87c3cbc59fdd104a27557 100644 (file)
@@ -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;
index 13cbfb267a55c58fbe075d622fe79ea2d6e7886b..74ad9af2a8919ffce143f54eda082cb52dd5007a 100644 (file)
@@ -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: