]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Bind to the requested src interface without a src address
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 14 Jun 2022 16:15:15 +0000 (18:15 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 14 Jun 2022 16:15:15 +0000 (18:15 +0200)
In some cases we want to bind to a specific interface when contacting
a backend without specifying an exact source address, leaving the
kernel select one for us.

pdns/dnsdistdist/dnsdist-backend.cc
pdns/dnsdistdist/dnsdist-healthchecks.cc
pdns/dnsdistdist/dnsdist-tcp-downstream.cc

index ac655111fab141e2b6c815d52197b1879ba13f16..f2094606e089fa3792561c2832821a2f07293fd7 100644 (file)
@@ -58,17 +58,18 @@ bool DownstreamState::reconnect()
     }
     if (!IsAnyAddress(d_config.remote)) {
       fd = SSocket(d_config.remote.sin4.sin_family, SOCK_DGRAM, 0);
-      if (!IsAnyAddress(d_config.sourceAddr)) {
-        SSetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1);
-        if (!d_config.sourceItfName.empty()) {
+
+      if (!d_config.sourceItfName.empty()) {
 #ifdef SO_BINDTODEVICE
-          int res = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, d_config.sourceItfName.c_str(), d_config.sourceItfName.length());
-          if (res != 0) {
-            infolog("Error setting up the interface on backend socket '%s': %s", d_config.remote.toStringWithPort(), stringerror());
-          }
-#endif
+        int res = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, d_config.sourceItfName.c_str(), d_config.sourceItfName.length());
+        if (res != 0) {
+          infolog("Error setting up the interface on backend socket '%s': %s", d_config.remote.toStringWithPort(), stringerror());
         }
+#endif
+      }
 
+      if (!IsAnyAddress(d_config.sourceAddr)) {
+        SSetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1);
         SBind(fd, d_config.sourceAddr);
       }
       try {
@@ -78,7 +79,7 @@ bool DownstreamState::reconnect()
         }
         connected = true;
       }
-      catch(const std::runtime_error& error) {
+      catch (const std::runtime_error& error) {
         infolog("Error connecting to new server with address %s: %s", d_config.remote.toStringWithPort(), error.what());
         connected = false;
         break;
index 64efdf534182e42e8efcef867753f794772613e8..5430555924210b217eb363135975ec1aa3d864d3 100644 (file)
@@ -368,6 +368,15 @@ bool queueHealthCheck(std::unique_ptr<FDMultiplexer>& mplexer, const std::shared
     Socket sock(ds->d_config.remote.sin4.sin_family, ds->doHealthcheckOverTCP() ? SOCK_STREAM : SOCK_DGRAM);
 
     sock.setNonBlocking();
+    if (!ds->d_config.sourceItfName.empty()) {
+#ifdef SO_BINDTODEVICE
+      int res = setsockopt(sock.getHandle(), SOL_SOCKET, SO_BINDTODEVICE, ds->d_config.sourceItfName.c_str(), ds->d_config.sourceItfName.length());
+      if (res != 0 && g_verboseHealthChecks) {
+        infolog("Error setting SO_BINDTODEVICE on the health check socket for backend '%s': %s", ds->getNameWithAddr(), stringerror());
+      }
+#endif
+    }
+
     if (!IsAnyAddress(ds->d_config.sourceAddr)) {
       sock.setReuseAddr();
 #ifdef IP_BIND_ADDRESS_NO_PORT
@@ -375,15 +384,6 @@ bool queueHealthCheck(std::unique_ptr<FDMultiplexer>& mplexer, const std::shared
         SSetsockopt(sock.getHandle(), SOL_IP, IP_BIND_ADDRESS_NO_PORT, 1);
       }
 #endif
-
-      if (!ds->d_config.sourceItfName.empty()) {
-#ifdef SO_BINDTODEVICE
-        int res = setsockopt(sock.getHandle(), SOL_SOCKET, SO_BINDTODEVICE, ds->d_config.sourceItfName.c_str(), ds->d_config.sourceItfName.length());
-        if (res != 0 && g_verboseHealthChecks) {
-          infolog("Error setting SO_BINDTODEVICE on the health check socket for backend '%s': %s", ds->getNameWithAddr(), stringerror());
-        }
-#endif
-      }
       sock.bind(ds->d_config.sourceAddr);
     }
 
index 1dbf7cc96c9450316c1164f363c88cd322f2cd59..b254c6732bb038bb4e9a4e6a2057678ff085009d 100644 (file)
@@ -76,23 +76,25 @@ bool ConnectionToBackend::reconnect()
       auto socket = std::make_unique<Socket>(d_ds->d_config.remote.sin4.sin_family, SOCK_STREAM, 0);
       DEBUGLOG("result of socket() is "<<socket->getHandle());
 
+#ifdef SO_BINDTODEVICE
+      if (!d_ds->d_config.sourceItfName.empty()) {
+        int res = setsockopt(socket->getHandle(), SOL_SOCKET, SO_BINDTODEVICE, d_ds->d_config.sourceItfName.c_str(), d_ds->d_config.sourceItfName.length());
+        if (res != 0) {
+          vinfolog("Error setting up the interface on backend TCP socket '%s': %s", d_ds->getNameWithAddr(), stringerror());
+        }
+      }
+#endif
+
       if (!IsAnyAddress(d_ds->d_config.sourceAddr)) {
         SSetsockopt(socket->getHandle(), SOL_SOCKET, SO_REUSEADDR, 1);
 #ifdef IP_BIND_ADDRESS_NO_PORT
         if (d_ds->d_config.ipBindAddrNoPort) {
           SSetsockopt(socket->getHandle(), SOL_IP, IP_BIND_ADDRESS_NO_PORT, 1);
         }
-#endif
-#ifdef SO_BINDTODEVICE
-        if (!d_ds->d_config.sourceItfName.empty()) {
-          int res = setsockopt(socket->getHandle(), SOL_SOCKET, SO_BINDTODEVICE, d_ds->d_config.sourceItfName.c_str(), d_ds->d_config.sourceItfName.length());
-          if (res != 0) {
-            vinfolog("Error setting up the interface on backend TCP socket '%s': %s", d_ds->getNameWithAddr(), stringerror());
-          }
-        }
 #endif
         socket->bind(d_ds->d_config.sourceAddr, false);
       }
+
       socket->setNonBlocking();
 
       gettimeofday(&d_connectionStartTime, nullptr);