]> granicus.if.org Git - pdns/commitdiff
dnsdist: Use SO_BINDTODEVICE when available for newServer's source itf
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 2 Oct 2019 13:37:35 +0000 (15:37 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 2 Oct 2019 13:37:35 +0000 (15:37 +0200)
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh

index 04c08ca21c37789578e55e41cb3b8f5a0e501121..07a6ec1df409732d8ab1b69c2979076a9ef9c935 100644 (file)
@@ -195,6 +195,7 @@ void setupLuaConfig(bool client)
       }
 
       ComboAddress sourceAddr;
+      std::string sourceItfName;
       unsigned int sourceItf = 0;
       size_t numberOfSockets = 1;
       std::set<int> cpus;
@@ -224,8 +225,8 @@ void setupLuaConfig(bool client)
                          if (parsed == false)
                          {
                            /* try to parse as interface name, or v4/v6@itf */
-                           string itfName = source.substr(pos == std::string::npos ? 0 : pos + 1);
-                           unsigned int itfIdx = if_nametoindex(itfName.c_str());
+                           string sourceItfName = source.substr(pos == std::string::npos ? 0 : pos + 1);
+                           unsigned int itfIdx = if_nametoindex(sourceItfName.c_str());
 
                            if (itfIdx != 0) {
                              if (pos == 0 || pos == std::string::npos) {
@@ -240,7 +241,7 @@ void setupLuaConfig(bool client)
                            }
                            else
                            {
-                             warnlog("Dismissing source %s because '%s' is not a valid interface name", source, itfName);
+                             warnlog("Dismissing source %s because '%s' is not a valid interface name", source, sourceItfName);
                            }
                          }
                        }
@@ -257,7 +258,7 @@ void setupLuaConfig(bool client)
         // do not construct DownstreamState now, it would try binding sockets.
         return ret;
       }
-      ret=std::make_shared<DownstreamState>(serverAddr, sourceAddr, sourceItf, numberOfSockets);
+      ret=std::make_shared<DownstreamState>(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets);
 
                        if(vars.count("qps")) {
                          int qpsVal=std::stoi(boost::get<string>(vars["qps"]));
index 1c3f54a62f659a74a8e3f9065e5d00f0009a331b..c55002476ca29d39f76d18c011443a8ac35216a7 100644 (file)
@@ -702,6 +702,15 @@ bool DownstreamState::reconnect()
       fd = SSocket(remote.sin4.sin_family, SOCK_DGRAM, 0);
       if (!IsAnyAddress(sourceAddr)) {
         SSetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1);
+        if (!sourceItfName.empty()) {
+#ifdef SO_BINDTODEVICE
+          int res = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, sourceItfName.c_str(), sourceItfName.length());
+          if (res != 0) {
+            infolog("Error setting up the interface on backend socket '%s': %s", remote.toStringWithPort(), stringerror());
+          }
+#endif
+        }
+
         SBind(fd, sourceAddr);
       }
       try {
@@ -773,7 +782,7 @@ void DownstreamState::setWeight(int newWeight)
   }
 }
 
-DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf_, size_t numberOfSockets): remote(remote_), sourceAddr(sourceAddr_), sourceItf(sourceItf_)
+DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf_, const std::string& sourceItfName_, size_t numberOfSockets): sourceItfName(sourceItfName_), remote(remote_), sourceAddr(sourceAddr_), sourceItf(sourceItf_)
 {
   pthread_rwlock_init(&d_lock, nullptr);
   id = getUniqueID();
index e654b9e1556a1b0db57342e435966cb823052470..fa7349a19deaa860a69c70c4300e6143406c09c2 100644 (file)
@@ -824,8 +824,8 @@ struct DownstreamState
 {
    typedef std::function<std::tuple<DNSName, uint16_t, uint16_t>(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t;
 
-  DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, size_t numberOfSockets);
-  DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, 1) {}
+  DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf, const std::string& sourceItfName, size_t numberOfSockets);
+  DownstreamState(const ComboAddress& remote_): DownstreamState(remote_, ComboAddress(), 0, std::string(), 1) {}
   ~DownstreamState()
   {
     for (auto& fd : sockets) {
@@ -839,6 +839,7 @@ struct DownstreamState
   std::set<unsigned int> hashes;
   mutable pthread_rwlock_t d_lock;
   std::vector<int> sockets;
+  const std::string sourceItfName;
   std::mutex socketsLock;
   std::mutex connectLock;
   std::unique_ptr<FDMultiplexer> mplexer{nullptr};