/* we get launched with a pipe on which we receive file descriptors from clients that we own
from that point on */
- typedef std::function<bool(const DNSQuestion*)> blockfilter_t;
bool outstanding = false;
blockfilter_t blockFilter = 0;
if(!getNonBlockingMsgLen(ci.fd, &qlen, g_tcpRecvTimeout))
break;
+ ci.cs->queries++;
+ g_stats.queries++;
+
if (qlen < sizeof(dnsheader)) {
g_stats.nonCompliantQueries++;
break;
char queryBuffer[querySize];
const char* query = queryBuffer;
readn2WithTimeout(ci.fd, queryBuffer, qlen, g_tcpRecvTimeout);
+
#ifdef HAVE_DNSCRYPT
std::shared_ptr<DnsCryptQuery> dnsCryptQuery = 0;
goto drop;
}
+ if (dh->rd) {
+ g_stats.rdQueries++;
+ }
+
+ const uint16_t* flags = getFlagsFromDNSHeader(dh);
+ uint16_t origFlags = *flags;
uint16_t qtype, qclass;
unsigned int consumed = 0;
DNSName qname(query, qlen, sizeof(dnsheader), false, &qtype, &qclass, &consumed);
DNSQuestion dq(&qname, qtype, qclass, &ci.cs->local, &ci.remote, (dnsheader*)query, querySize, qlen, true);
- string ruleresult;
- const uint16_t * flags = getFlagsFromDNSHeader(dq.dh);
- uint16_t origFlags = *flags;
+
+ string poolname;
+ int delayMsec=0;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
- {
- WriteLock wl(&g_rings.queryLock);
- g_rings.queryRing.push_back({now,ci.remote,qname,dq.len,dq.qtype,*dq.dh});
- }
-
- g_stats.queries++;
- if (ci.cs) {
- ci.cs->queries++;
- }
-
- if(auto got=localDynBlockNMG->lookup(ci.remote)) {
- if(now < got->second.until) {
- vinfolog("Query from %s dropped because of dynamic block", ci.remote.toStringWithPort());
- g_stats.dynBlocked++;
- got->second.blocks++;
- goto drop;
- }
- }
-
- if (dq.dh->rd) {
- g_stats.rdQueries++;
- }
-
- if(blockFilter) {
- std::lock_guard<std::mutex> lock(g_luamutex);
-
- if(blockFilter(&dq)) {
- g_stats.blockFilter++;
- goto drop;
- }
- if(dq.dh->tc && dq.dh->qr) { // don't truncate on TCP/IP!
- dq.dh->tc=false; // maybe we should just pass blockFilter the TCP status
- dq.dh->qr=false;
- }
- }
-
- bool done=false;
- DNSAction::Action action=DNSAction::Action::None;
- for(const auto& lr : *localRulactions) {
- if(lr.first->matches(&dq)) {
- lr.first->d_matches++;
- action=(*lr.second)(&dq, &ruleresult);
- switch(action) {
- case DNSAction::Action::Allow:
- done = true;
- break;
- case DNSAction::Action::Drop:
- g_stats.ruleDrop++;
- goto drop;
- break;
- case DNSAction::Action::Nxdomain:
- dq.dh->rcode = RCode::NXDomain;
- dq.dh->qr=true;
- g_stats.ruleNXDomain++;
- done = true;
- break;
- case DNSAction::Action::Spoof:
- spoofResponseFromString(dq, ruleresult);
- done = true;
- break;
- case DNSAction::Action::HeaderModify:
- done = true;
- break;
- case DNSAction::Action::Pool:
- poolname=ruleresult;
- done = true;
- break;
- /* non-terminal actions follow */
- case DNSAction::Action::Delay:
- case DNSAction::Action::None:
- break;
- }
- if(done) {
- break;
- }
- }
+ if (!processQuery(localDynBlockNMG, localRulactions, blockFilter, dq, ci.remote, poolname, &delayMsec, now)) {
+ goto drop;
}
if(dq.dh->qr) { // something turned it into a response
--state->outstanding; // you'd think an attacker could game this, but we're using connected socket
if(dh->tc && g_truncateTC) {
- truncateTC(response, (uint16_t*) &responseLen);
+ truncateTC(response, &responseLen);
}
dh->id = ids->origID;
}
}
+bool processQuery(LocalStateHolder<NetmaskTree<DynBlock> >& localDynBlock, LocalStateHolder<vector<pair<std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction> > > >& localRulactions, blockfilter_t blockFilter, DNSQuestion& dq, const ComboAddress& remote, string& poolname, int* delayMsec, const struct timespec& now)
+{
+ {
+ WriteLock wl(&g_rings.queryLock);
+ g_rings.queryRing.push_back({now,remote,*dq.qname,dq.len,dq.qtype,*dq.dh});
+ }
+
+ if(auto got=localDynBlock->lookup(remote)) {
+ if(now < got->second.until) {
+ vinfolog("Query from %s dropped because of dynamic block", remote.toStringWithPort());
+ g_stats.dynBlocked++;
+ got->second.blocks++;
+ return false;
+ }
+ }
+
+ if(blockFilter) {
+ std::lock_guard<std::mutex> lock(g_luamutex);
+
+ if(blockFilter(&dq)) {
+ g_stats.blockFilter++;
+ return false;
+ }
+ }
+
+ DNSAction::Action action=DNSAction::Action::None;
+ string ruleresult;
+ for(const auto& lr : *localRulactions) {
+ if(lr.first->matches(&dq)) {
+ lr.first->d_matches++;
+ action=(*lr.second)(&dq, &ruleresult);
+
+ switch(action) {
+ case DNSAction::Action::Allow:
+ return true;
+ break;
+ case DNSAction::Action::Drop:
+ g_stats.ruleDrop++;
+ return false;
+ break;
+ case DNSAction::Action::Nxdomain:
+ dq.dh->rcode = RCode::NXDomain;
+ dq.dh->qr=true;
+ g_stats.ruleNXDomain++;
+ return true;
+ break;
+ case DNSAction::Action::Spoof:
+ spoofResponseFromString(dq, ruleresult);
+ return true;
+ break;
+ case DNSAction::Action::HeaderModify:
+ return true;
+ break;
+ case DNSAction::Action::Pool:
+ poolname=ruleresult;
+ return true;
+ break;
+ /* non-terminal actions follow */
+ case DNSAction::Action::Delay:
+ *delayMsec = static_cast<int>(pdns_stou(ruleresult)); // sorry
+ break;
+ case DNSAction::Action::None:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
static ssize_t udpClientSendRequestToBackend(DownstreamState* ss, const int sd, const char* request, const size_t requestLen)
{
if (ss->sourceItf == 0) {
string largerQuery;
uint16_t qtype, qclass;
- typedef std::function<bool(DNSQuestion*)> blockfilter_t;
blockfilter_t blockFilter = 0;
{
std::lock_guard<std::mutex> lock(g_luamutex);
ssize_t ret = recvmsg(cs->udpFD, &msgh, 0);
queryId = 0;
+ if(!acl->match(remote)) {
+ vinfolog("Query from %s dropped because of ACL", remote.toStringWithPort());
+ g_stats.aclDrops++;
+ continue;
+ }
+
cs->queries++;
g_stats.queries++;
continue;
}
- if(!acl->match(remote)) {
- vinfolog("Query from %s dropped because of ACL", remote.toStringWithPort());
- g_stats.aclDrops++;
- continue;
- }
-
uint16_t len = (uint16_t) ret;
#ifdef HAVE_DNSCRYPT
if (cs->dnscryptCtx) {
if(!HarvestDestinationAddress(&msgh, &dest)) {
dest.sin4.sin_family = 0;
}
- sendUDPResponse(cs->udpFD, reinterpret_cast<char*>(response.data()), response.size(), response.size(),
-#ifdef HAVE_DNSCRYPT
- nullptr,
-#endif
- 0, dest, remote);
+ sendUDPResponse(cs->udpFD, reinterpret_cast<char*>(response.data()), response.size(), response.size(), nullptr, 0, dest, remote);
}
continue;
}
const uint16_t origFlags = *flags;
unsigned int consumed = 0;
DNSName qname(query, len, sizeof(dnsheader), false, &qtype, &qclass, &consumed);
-
DNSQuestion dq(&qname, qtype, qclass, &cs->local, &remote, dh, sizeof(packet), len, false);
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- {
- WriteLock wl(&g_rings.queryLock);
- g_rings.queryRing.push_back({now,remote,qname,dq.len,dq.qtype,*dq.dh});
- }
-
- if(auto got=localDynBlock->lookup(remote)) {
- if(now < got->second.until) {
- vinfolog("Query from %s dropped because of dynamic block", remote.toStringWithPort());
- g_stats.dynBlocked++;
- got->second.blocks++;
- continue;
- }
- }
-
- if(blockFilter) {
- std::lock_guard<std::mutex> lock(g_luamutex);
-
- if(blockFilter(&dq)) {
- g_stats.blockFilter++;
- continue;
- }
- }
-
- DNSAction::Action action=DNSAction::Action::None;
- string ruleresult;
string poolname;
int delayMsec=0;
- bool done=false;
- for(const auto& lr : *localRulactions) {
- if(lr.first->matches(&dq)) {
- lr.first->d_matches++;
- action=(*lr.second)(&dq, &ruleresult);
-
- switch(action) {
- case DNSAction::Action::Allow:
- done = true;
- break;
- case DNSAction::Action::Drop:
- g_stats.ruleDrop++;
- done = true;
- break;
- case DNSAction::Action::Nxdomain:
- dq.dh->rcode = RCode::NXDomain;
- dq.dh->qr=true;
- g_stats.ruleNXDomain++;
- done = true;
- break;
- case DNSAction::Action::Spoof:
- spoofResponseFromString(dq, ruleresult);
- done = true;
- break;
- case DNSAction::Action::HeaderModify:
- done = true;
- break;
- case DNSAction::Action::Pool:
- poolname=ruleresult;
- done = true;
- break;
- /* non-terminal actions follow */
- case DNSAction::Action::Delay:
- delayMsec = static_cast<int>(pdns_stou(ruleresult)); // sorry
- break;
- case DNSAction::Action::None:
- break;
- }
- if (done) {
- break;
- }
- }
- }
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
- if (action == DNSAction::Action::Drop) {
+ if (!processQuery(localDynBlock, localRulactions, blockFilter, dq, remote, poolname, &delayMsec, now))
+ {
continue;
}