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 \
misc.cc misc.hh \
mplexer.hh \
nsecrecords.cc \
+ query-local-address.hh query-local-address.cc \
qtype.cc \
rcpgenerator.cc rcpgenerator.hh \
resolver.cc \
logger.cc \
misc.cc misc.hh \
nsecrecords.cc \
+ query-local-address.hh query-local-address.cc \
qtype.cc \
rcpgenerator.cc rcpgenerator.hh \
resolver.cc \
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 \
#include "dns_random.hh"
#include "utility.hh"
#include "resolver.hh"
+#include "query-local-address.hh"
using pdns::resolver::parseResult;
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 {
#include "dnsseckeeper.hh"
#include "threadname.hh"
#include "misc.hh"
+#include "query-local-address.hh"
#include <thread>
}
}
+ pdns::parseQueryLocalAddress(::arg()["query-local-address"]);
+ pdns::parseQueryLocalAddress(::arg()["query-local-address6"]);
+
// NOW SAFE TO CREATE THREADS!
dl->go();
#include <boost/algorithm/string.hpp>
#include "validate-recursor.hh"
#include "ednssubnet.hh"
+#include "query-local-address.hh"
#ifdef HAVE_PROTOBUF
#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)
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);
#include "packetcache.hh"
#include "base64.hh"
#include "namespaces.hh"
+#include "query-local-address.hh"
void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
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;
}
#ifdef NOD_ENABLED
#include "nod.hh"
#endif /* NOD_ENABLED */
+#include "query-local-address.hh"
#include "rec-protobuf.hh"
#include "rec-snmp.hh"
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
{
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);
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)
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;
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;
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"]);
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
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 \
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 \
--- /dev/null
+../query-local-address.cc
\ No newline at end of file
--- /dev/null
+../query-local-address.hh
\ No newline at end of file
#include "base64.hh"
#include "dnswriter.hh"
#include "dnsparser.hh"
-
+#include "query-local-address.hh"
#include "dns_random.hh"
#include <poll.h>
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)
// 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;
#include "dns_random.hh"
#include "backends/gsql/ssql.hh"
#include "communicator.hh"
+#include "query-local-address.hh"
extern StatBag S;
extern CommunicatorClass Communicator;
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;
#include "rpzloader.hh"
#include "zoneparser-tng.hh"
#include "threadname.hh"
+#include "query-local-address.hh"
Netmask makeNetmaskFromRPZ(const DNSName& name)
{
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;
ComboAddress local(localAddress);
if (local == ComboAddress()) {
- local = getQueryLocalAddress(master.sin4.sin_family, 0);
+ local = pdns::getQueryLocalAddress(master.sin4.sin_family, 0);
}
try {
#include "inflighter.cc"
#include "namespaces.hh"
#include "common_startup.hh"
+#include "query-local-address.hh"
#include "ixfr.hh"
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;
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);
#include "axfr-retriever.hh"
#include "arguments.hh"
#include "dns_random.hh"
+#include "query-local-address.hh"
StatBag S;
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();