]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/pdns_recursor.cc
Merge pull request #8940 from pieterlexis/resolver-query-local-address6
[thirdparty/pdns.git] / pdns / pdns_recursor.cc
index 0db01c9d34419bea68d57e1e37e1a340691e86e9..c209fc81603d4dbcb897eeec9d1ce232d02beadf 100644 (file)
@@ -94,6 +94,7 @@
 #ifdef NOD_ENABLED
 #include "nod.hh"
 #endif /* NOD_ENABLED */
+#include "query-local-address.hh"
 
 #include "rec-protobuf.hh"
 #include "rec-snmp.hh"
@@ -191,10 +192,8 @@ static deferredAdd_t g_deferredAdds;
 typedef vector<int> tcpListenSockets_t;
 typedef map<int, ComboAddress> listenSocketsAddresses_t; // is shared across all threads right now
 
-static const ComboAddress g_local4("0.0.0.0"), g_local6("::");
 static listenSocketsAddresses_t g_listenSocketsAddresses; // is shared across all threads right now
 static set<int> g_fromtosockets; // listen sockets that use 'sendfromto()' mechanism
-static vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
 static AtomicCounter counter;
 static std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
 static std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
@@ -463,7 +462,7 @@ string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
 {
   Socket s(dest.sin4.sin_family, SOCK_DGRAM);
   s.setNonBlocking();
-  ComboAddress local = getQueryLocalAddress(dest.sin4.sin_family, 0);
+  ComboAddress local = pdns::getQueryLocalAddress(dest.sin4.sin_family, 0);
   
   s.bind(local);
   s.connect(dest);
@@ -489,28 +488,6 @@ string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
   return data;
 }
 
-//! pick a random query local address
-ComboAddress getQueryLocalAddress(int family, uint16_t port)
-{
-  ComboAddress ret;
-  if(family==AF_INET) {
-    if(g_localQueryAddresses4.empty())
-      ret = g_local4;
-    else
-      ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
-    ret.sin4.sin_port = htons(port);
-  }
-  else {
-    if(g_localQueryAddresses6.empty())
-      ret = g_local6;
-    else
-      ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
-
-    ret.sin6.sin6_port = htons(port);
-  }
-  return ret;
-}
-
 static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&);
 
 static void setSocketBuffer(int fd, int optname, uint32_t size)
@@ -626,7 +603,7 @@ private:
         while (s_avoidUdpSourcePorts.count(port));
       }
 
-      sin=getQueryLocalAddress(family, port); // does htons for us
+      sin=pdns::getQueryLocalAddress(family, port); // does htons for us
 
       if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)
         break;
@@ -4113,23 +4090,11 @@ static int serviceMain(int argc, char*argv[])
 
   checkLinuxIPv6Limits();
   try {
-    vector<string> addrs;
-    if(!::arg()["query-local-address6"].empty()) {
-      SyncRes::s_doIPv6=true;
-      g_log<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
-
-      stringtok(addrs, ::arg()["query-local-address6"], ", ;");
-      for(const string& addr : addrs) {
-        g_localQueryAddresses6.push_back(ComboAddress(addr));
-      }
-    }
-    else {
-      g_log<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
-    }
-    addrs.clear();
-    stringtok(addrs, ::arg()["query-local-address"], ", ;");
-    for(const string& addr : addrs) {
-      g_localQueryAddresses4.push_back(ComboAddress(addr));
+    pdns::parseQueryLocalAddress(::arg()["query-local-address"]);
+    if (!::arg()["query-local-address6"].empty()) {
+      // TODO remove in 4.5.0
+      g_log<<Logger::Warning<<"query-local-address6 is deprecated and will be removed in a future version. Please use query-local-address for IPv6 addresses as well"<<endl;
+      pdns::parseQueryLocalAddress(::arg()["query-local-address6"]);
     }
   }
   catch(std::exception& e) {
@@ -4137,6 +4102,14 @@ static int serviceMain(int argc, char*argv[])
     exit(99);
   }
 
+  if(pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
+    SyncRes::s_doIPv6=true;
+    g_log<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
+  }
+  else {
+    g_log<<Logger::Warning<<"NOT using IPv6 for outgoing queries - add an IPv6 address (like '::') to query-local-address to enable"<<endl;
+  }
+
   // keep this ABOVE loadRecursorLuaConfig!
   if(::arg()["dnssec"]=="off")
     g_dnssecmode=DNSSECMode::Off;
@@ -4273,26 +4246,25 @@ static int serviceMain(int argc, char*argv[])
     SyncRes::setECSScopeZeroAddress(Netmask(scopeZero, scopeZero.isIPv4() ? 32 : 128));
   }
   else {
-    bool found = false;
-    for (const auto& addr : g_localQueryAddresses4) {
-      if (!IsAnyAddress(addr)) {
-        SyncRes::setECSScopeZeroAddress(Netmask(addr, 32));
-        found = true;
-        break;
-      }
+    Netmask nm;
+    bool done = false;
+
+    auto addr = pdns::getNonAnyQueryLocalAddress(AF_INET);
+    if (addr.sin4.sin_family != 0) {
+      nm = Netmask(addr, 32);
+      done = true;
     }
-    if (!found) {
-      for (const auto& addr : g_localQueryAddresses6) {
-        if (!IsAnyAddress(addr)) {
-          SyncRes::setECSScopeZeroAddress(Netmask(addr, 128));
-          found = true;
-          break;
-        }
-      }
-      if (!found) {
-        SyncRes::setECSScopeZeroAddress(Netmask("127.0.0.1/32"));
+    if (!done) {
+      addr = pdns::getNonAnyQueryLocalAddress(AF_INET6);
+      if (addr.sin4.sin_family != 0) {
+        nm = Netmask(addr, 128);
+        done = true;
       }
     }
+    if (!done) {
+      nm = Netmask(ComboAddress("127.0.0.1"), 32);
+    }
+    SyncRes::setECSScopeZeroAddress(nm);
   }
 
   SyncRes::parseEDNSSubnetWhitelist(::arg()["edns-subnet-whitelist"]);
@@ -4958,7 +4930,7 @@ int main(int argc, char **argv)
 #endif
     ::arg().set("delegation-only","Which domains we only accept delegations from")="";
     ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
-    ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
+    ::arg().set("query-local-address6","DEPRECATED: Use query-local-address for IPv6 as well. Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
     ::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
     ::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
     ::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";