Skip to content

Commit

Permalink
Centralize Query Local Address handling
Browse files Browse the repository at this point in the history
  • Loading branch information
pieterlexis committed Apr 1, 2020
1 parent 0dd42db commit 2082958
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 98 deletions.
5 changes: 5 additions & 0 deletions pdns/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
8 changes: 4 additions & 4 deletions pdns/axfr-retriever.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "dns_random.hh"
#include "utility.hh"
#include "resolver.hh"
#include "query-local-address.hh"

using pdns::resolver::parseResult;

Expand All @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions pdns/common_startup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "dnsseckeeper.hh"
#include "threadname.hh"
#include "misc.hh"
#include "query-local-address.hh"

#include <thread>

Expand Down Expand Up @@ -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();

Expand Down
5 changes: 4 additions & 1 deletion pdns/lwres.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <boost/algorithm/string.hpp>
#include "validate-recursor.hh"
#include "ednssubnet.hh"
#include "query-local-address.hh"

#ifdef HAVE_PROTOBUF

Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
9 changes: 5 additions & 4 deletions pdns/mastercommunicator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
90 changes: 29 additions & 61 deletions pdns/pdns_recursor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -627,7 +604,7 @@ class UDPClientSocks
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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"]);
Expand Down
100 changes: 100 additions & 0 deletions pdns/query-local-address.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 2082958

Please sign in to comment.