]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Centralize Query Local Address handling
authorPieter Lexis <pieter.lexis@powerdns.com>
Mon, 16 Mar 2020 17:34:36 +0000 (18:34 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Wed, 1 Apr 2020 09:10:22 +0000 (11:10 +0200)
17 files changed:
pdns/Makefile.am
pdns/axfr-retriever.cc
pdns/common_startup.cc
pdns/lwres.cc
pdns/mastercommunicator.cc
pdns/pdns_recursor.cc
pdns/query-local-address.cc [new file with mode: 0644]
pdns/query-local-address.hh [new file with mode: 0644]
pdns/recursordist/Makefile.am
pdns/recursordist/query-local-address.cc [new symlink]
pdns/recursordist/query-local-address.hh [new symlink]
pdns/resolver.cc
pdns/rfc2136handler.cc
pdns/rpzloader.cc
pdns/slavecommunicator.cc
pdns/syncres.hh
pdns/tsig-tests.cc

index f6a5510bd24ca65528ab6bde0b6a0e74e676c92b..d63a2fadcab135fbf2b59ab2ac480c7bfe1ffde2 100644 (file)
@@ -204,6 +204,7 @@ pdns_server_SOURCES = \
        packethandler.cc packethandler.hh \
        pdnsexception.hh \
        qtype.cc qtype.hh \
+       query-local-address.hh query-local-address.cc \
        rcpgenerator.cc \
        receiver.cc \
        resolver.cc resolver.hh \
@@ -634,6 +635,7 @@ ixfrdist_SOURCES = \
        misc.cc misc.hh \
        mplexer.hh \
        nsecrecords.cc \
+       query-local-address.hh query-local-address.cc \
        qtype.cc \
        rcpgenerator.cc rcpgenerator.hh \
        resolver.cc \
@@ -689,6 +691,7 @@ ixplore_SOURCES = \
        logger.cc \
        misc.cc misc.hh \
        nsecrecords.cc \
+       query-local-address.hh query-local-address.cc \
        qtype.cc \
        rcpgenerator.cc rcpgenerator.hh \
        resolver.cc \
@@ -840,9 +843,11 @@ tsig_tests_SOURCES = \
        dnssecinfra.cc \
        dnswriter.cc dnswriter.hh \
        gss_context.cc gss_context.hh \
+       iputils.cc \
        logger.cc \
        misc.cc misc.hh \
        nsecrecords.cc \
+       query-local-address.cc \
        qtype.cc \
        rcpgenerator.cc rcpgenerator.hh \
        resolver.cc \
index cfac004079d24ec7413d7a5ffbb85dcbf6d5da95..4d2718efd34c90f8d87ca875560a2bac4ec5e7fa 100644 (file)
@@ -25,6 +25,7 @@
 #include "dns_random.hh"
 #include "utility.hh"
 #include "resolver.hh"
+#include "query-local-address.hh"
 
 using pdns::resolver::parseResult;
 
@@ -40,11 +41,10 @@ AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
   if (laddr != nullptr) {
     local = ComboAddress(*laddr);
   } else {
-    string qlas = remote.sin4.sin_family == AF_INET ? "query-local-address" : "query-local-address6";
-    if (::arg()[qlas].empty()) {
-      throw ResolverException("Unable to determine source address for AXFR request to " + remote.toStringWithPort() + " for " + domain.toLogString() + ". " + qlas + " is unset");
+    if (!pdns::isQueryLocalAddressFamilyEnabled(remote.sin4.sin_family)) {
+      throw ResolverException("Unable to determine source address for AXFR request to " + remote.toStringWithPort() + " for " + domain.toLogString() + ". Address family is not configured for outgoing queries");
     }
-    local=ComboAddress(::arg()[qlas]);
+    local = pdns::getQueryLocalAddress(remote.sin4.sin_family, 0);
   }
   d_sock = -1;
   try {
index da3c8e337153e386f30219efe87c24e6bdd674d0..8ba1ce6dfcf1cf47121a60de00eed2040c38897d 100644 (file)
@@ -31,6 +31,7 @@
 #include "dnsseckeeper.hh"
 #include "threadname.hh"
 #include "misc.hh"
+#include "query-local-address.hh"
 
 #include <thread>
 
@@ -628,6 +629,9 @@ void mainthread()
     }
   }
 
+  pdns::parseQueryLocalAddress(::arg()["query-local-address"]);
+  pdns::parseQueryLocalAddress(::arg()["query-local-address6"]);
+
   // NOW SAFE TO CREATE THREADS!
   dl->go();
 
index 2fb111fde1a878a16f858e184c80cb53f06089fd..cc40ae9b66ada023af6681ff14f11f7359864bf8 100644 (file)
@@ -47,6 +47,7 @@
 #include <boost/algorithm/string.hpp>
 #include "validate-recursor.hh"
 #include "ednssubnet.hh"
+#include "query-local-address.hh"
 
 #ifdef HAVE_PROTOBUF
 
@@ -55,6 +56,8 @@
 #ifdef HAVE_FSTRM
 #include "rec-dnstap.hh"
 #include "fstrm_logger.hh"
+
+
 bool g_syslog;
 
 static bool isEnabledForQueries(const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstreamLoggers)
@@ -315,7 +318,7 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d
       Socket s(ip.sin4.sin_family, SOCK_STREAM);
 
       s.setNonBlocking();
-      ComboAddress local = getQueryLocalAddress(ip.sin4.sin_family, 0);
+      ComboAddress local = pdns::getQueryLocalAddress(ip.sin4.sin_family, 0);
 
       s.bind(local);
         
index 4219e1d356bd0a374ef1e665e4029e232418fd09..7b45c76c89d817656a76a30bd600dec137dd366d 100644 (file)
@@ -40,6 +40,7 @@
 #include "packetcache.hh"
 #include "base64.hh"
 #include "namespaces.hh"
+#include "query-local-address.hh"
 
 
 void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
@@ -299,13 +300,13 @@ bool CommunicatorClass::justNotified(const DNSName &domain, const string &ip)
 
 void CommunicatorClass::makeNotifySockets()
 {
-  if(!::arg()["query-local-address"].empty()) {
-    d_nsock4 = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true, ::arg().mustDo("non-local-bind"));
+  if(pdns::isQueryLocalAddressFamilyEnabled(AF_INET)) {
+    d_nsock4 = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET, 0), true, ::arg().mustDo("non-local-bind"));
   } else {
     d_nsock4 = -1;
   }
-  if(!::arg()["query-local-address6"].empty()) {
-    d_nsock6 = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true, ::arg().mustDo("non-local-bind"));
+  if(pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
+    d_nsock6 = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET6, 0), true, ::arg().mustDo("non-local-bind"));
   } else {
     d_nsock6 = -1;
   }
index bfaf00ba43a7476b8caabd5c843811e22fed27d7..d94076e61e5dece06e3bc9109883d4f048ab7f71 100644 (file)
@@ -93,6 +93,7 @@
 #ifdef NOD_ENABLED
 #include "nod.hh"
 #endif /* NOD_ENABLED */
+#include "query-local-address.hh"
 
 #include "rec-protobuf.hh"
 #include "rec-snmp.hh"
@@ -190,10 +191,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
@@ -464,7 +463,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);
@@ -490,28 +489,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)
@@ -627,7 +604,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;
@@ -4013,30 +3990,22 @@ 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"]);
+    pdns::parseQueryLocalAddress(::arg()["query-local-address6"]);
   }
   catch(std::exception& e) {
     g_log<<Logger::Error<<"Assigning local query addresses: "<<e.what();
     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 - set 'query-local-address6=::' to enable"<<endl;
+  }
+
   // keep this ABOVE loadRecursorLuaConfig!
   if(::arg()["dnssec"]=="off")
     g_dnssecmode=DNSSECMode::Off;
@@ -4173,26 +4142,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"]);
diff --git a/pdns/query-local-address.cc b/pdns/query-local-address.cc
new file mode 100644 (file)
index 0000000..2acccab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "query-local-address.hh"
+#include "iputils.hh"
+#include "dns_random.hh"
+
+namespace pdns {
+  static const ComboAddress local4("0.0.0.0");
+  static const ComboAddress local6("::");
+
+  static vector<ComboAddress> g_localQueryAddresses4;
+  static vector<ComboAddress> g_localQueryAddresses6;
+
+  ComboAddress getQueryLocalAddress(const sa_family_t family, const in_port_t port) {
+    ComboAddress ret;
+    if (family==AF_INET) {
+      if (g_localQueryAddresses4.empty()) {
+        ret = local4;
+      } else if (g_localQueryAddresses4.size() == 1) {
+        ret = g_localQueryAddresses4.at(0);
+      } else {
+        ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
+      }
+      ret.sin4.sin_port = htons(port);
+    }
+    else {
+      if (g_localQueryAddresses6.empty()) {
+        ret = local6;
+      } else if (g_localQueryAddresses6.size() == 1) {
+        ret = g_localQueryAddresses6.at(0);
+      } else {
+        ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
+      }
+      ret.sin6.sin6_port = htons(port);
+    }
+    return ret;
+  }
+
+  ComboAddress getNonAnyQueryLocalAddress(const sa_family_t family) {
+    if (family == AF_INET) {
+      for (const auto& addr : pdns::g_localQueryAddresses4) {
+        if (!IsAnyAddress(addr)) {
+          return addr;
+        }
+      }
+    }
+    if (family == AF_INET6) {
+      for (const auto& addr : pdns::g_localQueryAddresses6) {
+        if (!IsAnyAddress(addr)) {
+          return addr;
+        }
+      }
+    }
+    ComboAddress ret("0.0.0.0");
+    ret.reset(); // Ensure all is zero, even the addr family
+    return ret;
+  }
+
+  void parseQueryLocalAddress(const std::string &qla) {
+    vector<string> addrs;
+    stringtok(addrs, qla, ", ;");
+    for(const string& addr : addrs) {
+      ComboAddress tmp(addr);
+      if (tmp.isIPv4()) {
+        g_localQueryAddresses4.push_back(tmp);
+        continue;
+      }
+      g_localQueryAddresses6.push_back(tmp);
+    }
+  }
+
+  bool isQueryLocalAddressFamilyEnabled(const sa_family_t family) {
+    if (family == AF_INET) {
+      return !g_localQueryAddresses4.empty();
+    }
+    if (family == AF_INET6) {
+      return !g_localQueryAddresses6.empty();
+    }
+    return false;
+  }
+} // namespace pdns
diff --git a/pdns/query-local-address.hh b/pdns/query-local-address.hh
new file mode 100644 (file)
index 0000000..9515f4a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include "iputils.hh"
+
+namespace pdns {
+  /*! pick a random query local address for family
+   *
+   * Will always return a ComboAddress.
+   *
+   * @param family Address Family, only AF_INET and AF_INET6 are supported
+   * @param port   Port to set in the returned ComboAddress
+   */
+  ComboAddress getQueryLocalAddress(const sa_family_t family, const in_port_t port);
+
+  /*! Returns a non-Any address QLA, or an empty QLA when the QLA is any
+   *
+   * @param family  Address Family
+   */
+  ComboAddress getNonAnyQueryLocalAddress(const sa_family_t family);
+
+  /*! Populate the query local address vectors
+   *
+   * Will throw when an address can't be parsed
+   *
+   * @param qla  A string of one or more ip addresses, separated by
+   *             spaces, semi-colons or commas
+   */
+  void parseQueryLocalAddress(const std::string &qla);
+
+  /*! Is the address family explicitly enabled
+   *
+   * i.e. was there an address parsed by parseQueryLocalAddress belonging
+   * to this family
+   *
+   * @param family  Address Family, only AF_INET and AF_INET6 are supported
+   */
+  bool isQueryLocalAddressFamilyEnabled(const sa_family_t family);
+} // namespace pdns
index 6e13a653b7f558cfd0af87fab2f172a68e51bc63..7cc26f45d9ebf846cecf59b0867809f699b5a1eb 100644 (file)
@@ -148,6 +148,7 @@ pdns_recursor_SOURCES = \
        pubsuffix.hh pubsuffix.cc \
        pubsuffixloader.cc \
        qtype.hh qtype.cc \
+       query-local-address.hh query-local-address.cc \
        rcpgenerator.cc rcpgenerator.hh \
        rec-carbon.cc \
        rec-lua-conf.hh rec-lua-conf.cc \
@@ -253,6 +254,7 @@ testrunner_SOURCES = \
        pollmplexer.cc \
        protobuf.cc protobuf.hh \
        qtype.cc qtype.hh \
+       query-local-address.hh query-local-address.cc \
        rcpgenerator.cc \
        rec-protobuf.cc rec-protobuf.hh \
        recpacketcache.cc recpacketcache.hh \
diff --git a/pdns/recursordist/query-local-address.cc b/pdns/recursordist/query-local-address.cc
new file mode 120000 (symlink)
index 0000000..fd2ad3c
--- /dev/null
@@ -0,0 +1 @@
+../query-local-address.cc
\ No newline at end of file
diff --git a/pdns/recursordist/query-local-address.hh b/pdns/recursordist/query-local-address.hh
new file mode 120000 (symlink)
index 0000000..18e39c8
--- /dev/null
@@ -0,0 +1 @@
+../query-local-address.hh
\ No newline at end of file
index d8977b8db5188b4f7efe09ed776e9b5888233af5..c9c456d5191aaee1c7d4740798b6ef1e37b3093c 100644 (file)
@@ -44,7 +44,7 @@
 #include "base64.hh"
 #include "dnswriter.hh"
 #include "dnsparser.hh"
-
+#include "query-local-address.hh"
 
 #include "dns_random.hh"
 #include <poll.h>
@@ -102,10 +102,12 @@ Resolver::Resolver()
   locals["default4"] = -1;
   locals["default6"] = -1;
   try {
-    if(!::arg()["query-local-address"].empty())
-      locals["default4"] = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true, ::arg().mustDo("non-local-bind"));
-    if(!::arg()["query-local-address6"].empty())
-      locals["default6"] = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true, ::arg().mustDo("non-local-bind"));
+    if (pdns::isQueryLocalAddressFamilyEnabled(AF_INET)) {
+      locals["default4"] = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET, 0), true, ::arg().mustDo("non-local-bind"));
+    }
+    if (pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
+      locals["default6"] = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET6, 0), true, ::arg().mustDo("non-local-bind"));
+    }
   }
   catch(...) {
     if(locals["default4"]>=0)
@@ -158,12 +160,13 @@ uint16_t Resolver::sendResolve(const ComboAddress& remote, const ComboAddress& l
   // choose socket based on local
   if (local.sin4.sin_family == 0) {
     // up to us.
-    sock = remote.sin4.sin_family == AF_INET ? locals["default4"] : locals["default6"];
-    if (sock == -1) {
-      string ipv = remote.sin4.sin_family == AF_INET ? "4" : "6";
-      string qla = remote.sin4.sin_family == AF_INET ? "" : "6";
-      throw ResolverException("No IPv" + ipv + " socket available, is query-local-address" + qla + " unset?");
+    if (remote.sin4.sin_family == AF_INET && !pdns::isQueryLocalAddressFamilyEnabled(AF_INET)) {
+      throw ResolverException("No IPv4 socket available, is query-local-address set?");
+    }
+    if (remote.sin4.sin_family == AF_INET6 && !pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
+      throw ResolverException("No IPv6 socket available, is query-local-address6 set?");
     }
+    sock = remote.sin4.sin_family == AF_INET ? locals["default4"] : locals["default6"];
   } else {
     std::string lstr = local.toString();
     std::map<std::string, int>::iterator lptr;
index 71173d015960f6597b16f1e5903999757ec78e46..ca5a3406530d99ca73f4cd7c5e93f3dfb7d0c34e 100644 (file)
@@ -16,6 +16,7 @@
 #include "dns_random.hh"
 #include "backends/gsql/ssql.hh"
 #include "communicator.hh"
+#include "query-local-address.hh"
 
 extern StatBag S;
 extern CommunicatorClass Communicator;
@@ -597,14 +598,10 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
   for(const auto& remote : di.masters) {
     g_log<<Logger::Notice<<msgPrefix<<"Forwarding packet to master "<<remote<<endl;
 
-    ComboAddress local;
-    if (remote.sin4.sin_family == AF_INET && !::arg()["query-local-address"].empty()) {
-      local = ComboAddress(::arg()["query-local-address"]);
-    } else if(remote.sin4.sin_family == AF_INET6 && !::arg()["query-local-address6"].empty()) {
-      local = ComboAddress(::arg()["query-local-address6"]);
-    } else {
+    if (!pdns::isQueryLocalAddressFamilyEnabled(remote.sin4.sin_family)) {
       continue;
     }
+    auto local = pdns::getQueryLocalAddress(remote.sin4.sin_family, 0);
     int sock = makeQuerySocket(local, false); // create TCP socket. RFC2136 section 6.2 seems to be ok with this.
     if(sock < 0) {
       g_log<<Logger::Error<<msgPrefix<<"Error creating socket: "<<stringerror()<<endl;
index 1562c5f94eaad392b25caa3649ec90e13d9fce23..287477a5826d20d02bc80fe86495e56fb6050cc2 100644 (file)
@@ -9,6 +9,7 @@
 #include "rpzloader.hh"
 #include "zoneparser-tng.hh"
 #include "threadname.hh"
+#include "query-local-address.hh"
 
 Netmask makeNetmaskFromRPZ(const DNSName& name)
 {
@@ -193,7 +194,7 @@ static shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master
 
   ComboAddress local(localAddress);
   if (local == ComboAddress())
-    local = getQueryLocalAddress(master.sin4.sin_family, 0);
+    local = pdns::getQueryLocalAddress(master.sin4.sin_family, 0);
 
   AXFRRetriever axfr(master, zoneName, tt, &local, maxReceivedBytes, axfrTimeout);
   unsigned int nrecords=0;
@@ -433,7 +434,7 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& masters, boost::optional<DN
 
       ComboAddress local(localAddress);
       if (local == ComboAddress()) {
-        local = getQueryLocalAddress(master.sin4.sin_family, 0);
+        local = pdns::getQueryLocalAddress(master.sin4.sin_family, 0);
       }
 
       try {
index 7e548ff08f51e7d85e63d6ac3bca5d28e0060f67..8941062e496879793fbf46aba2dc6c9fa27ce9aa 100644 (file)
@@ -44,6 +44,7 @@
 #include "inflighter.cc"
 #include "namespaces.hh"
 #include "common_startup.hh"
+#include "query-local-address.hh"
 
 #include "ixfr.hh"
 
@@ -373,15 +374,13 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
         return;
       }
     } else {
-      if(remote.sin4.sin_family == AF_INET && !::arg()["query-local-address"].empty()) {
-        laddr = ComboAddress(::arg()["query-local-address"]);
-      } else if(remote.sin4.sin_family == AF_INET6 && !::arg()["query-local-address6"].empty()) {
-        laddr = ComboAddress(::arg()["query-local-address6"]);
-      } else {
-        bool isv6 = remote.sin4.sin_family == AF_INET6;
-        g_log<<Logger::Error<<"Unable to AXFR, destination address is IPv" << (isv6 ? "6" : "4") << ", but query-local-address"<< (isv6 ? "6" : "") << " is unset!"<<endl;
+      if (!pdns::isQueryLocalAddressFamilyEnabled(remote.sin4.sin_family)) {
+        bool isV6 = remote.sin4.sin_family == AF_INET6;
+        g_log<<Logger::Error<<"Unable to AXFR, destination address is "<<remote<<" (IPv"<< (isV6 ? "6" : "4") <<
+          ", but that address family is not enabled for outgoing traffic (query-local-address"<<(isV6 ? "6" : "")<<")"<<endl;
         return;
       }
+      laddr = pdns::getQueryLocalAddress(remote.sin4.sin_family, 0);
     }
 
     bool hadDnssecZone = false;
index eaff86341e09dbcc6c89aa55c7c1338dc6d78855..e4c5a25c2ef8f19cc3aa48f341db19d21d44b429 100644 (file)
@@ -1085,7 +1085,6 @@ extern bool g_lowercaseOutgoing;
 
 std::string reloadAuthAndForwards();
 ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
-ComboAddress getQueryLocalAddress(int family, uint16_t port);
 typedef boost::function<void*(void)> pipefunc_t;
 void broadcastFunction(const pipefunc_t& func);
 void distributeAsyncFunction(const std::string& question, const pipefunc_t& func);
index d65bd563ab420890bff2720a23cfd3f8d50cd856..e63e29ebc5ecebbf617d1ce73f8f01acba19e58f 100644 (file)
@@ -14,6 +14,7 @@
 #include "axfr-retriever.hh"
 #include "arguments.hh"
 #include "dns_random.hh"
+#include "query-local-address.hh"
 
 StatBag S;
 
@@ -26,8 +27,7 @@ ArgvMap& arg()
 int main(int argc, char** argv)
 try
 {
-  ::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")="::";
+  pdns::parseQueryLocalAddress(":: 0.0.0.0");
 
   reportAllTypes();