return false;
}
-bool DNSDistPacketCache::cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, bool dnssecOK, const boost::optional<Netmask>& subnet) const
+bool DNSDistPacketCache::cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool receivedOverUDP, bool dnssecOK, const boost::optional<Netmask>& subnet) const
{
- if (cachedValue.queryFlags != queryFlags || cachedValue.dnssecOK != dnssecOK || cachedValue.tcp != tcp || cachedValue.qtype != qtype || cachedValue.qclass != qclass || cachedValue.qname != qname) {
+ if (cachedValue.queryFlags != queryFlags || cachedValue.dnssecOK != dnssecOK || cachedValue.receivedOverUDP != receivedOverUDP || cachedValue.qtype != qtype || cachedValue.qclass != qclass || cachedValue.qname != qname) {
return false;
}
CacheValue& value = it->second;
bool wasExpired = value.validity <= newValue.added;
- if (!wasExpired && !cachedValueMatches(value, newValue.queryFlags, newValue.qname, newValue.qtype, newValue.qclass, newValue.tcp, newValue.dnssecOK, newValue.subnet)) {
+ if (!wasExpired && !cachedValueMatches(value, newValue.queryFlags, newValue.qname, newValue.qtype, newValue.qclass, newValue.receivedOverUDP, newValue.dnssecOK, newValue.subnet)) {
d_insertCollisions++;
return;
}
value = newValue;
}
-void DNSDistPacketCache::insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL)
+void DNSDistPacketCache::insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool receivedOverUDP, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL)
{
if (response.size() < sizeof(dnsheader)) {
return;
newValue.len = response.size();
newValue.validity = newValidity;
newValue.added = now;
- newValue.tcp = tcp;
+ newValue.receivedOverUDP = receivedOverUDP;
newValue.dnssecOK = dnssecOK;
newValue.value = std::string(response.begin(), response.end());
newValue.subnet = subnet;
}
}
-bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional<Netmask>& subnet, bool dnssecOK, uint32_t allowExpired, bool skipAging)
+bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional<Netmask>& subnet, bool dnssecOK, bool receivedOverUDP, uint32_t allowExpired, bool skipAging)
{
const auto& dnsQName = dq.qname->getStorage();
- uint32_t key = getKey(dnsQName, dq.qname->wirelength(), dq.getData(), dq.tcp);
+ uint32_t key = getKey(dnsQName, dq.qname->wirelength(), dq.getData(), receivedOverUDP);
if (keyOut) {
*keyOut = key;
}
/* check for collision */
- if (!cachedValueMatches(value, *(getFlagsFromDNSHeader(dq.getHeader())), *dq.qname, dq.qtype, dq.qclass, dq.tcp, dnssecOK, subnet)) {
+ if (!cachedValueMatches(value, *(getFlagsFromDNSHeader(dq.getHeader())), *dq.qname, dq.qtype, dq.qclass, receivedOverUDP, dnssecOK, subnet)) {
d_lookupCollisions++;
return false;
}
return getDNSPacketMinTTL(packet, length, seenNoDataSOA);
}
-uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool tcp)
+uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool receivedOverUDP)
{
uint32_t result = 0;
/* skip the query ID */
result = burtle(&packet.at(sizeof(dnsheader) + qnameWireLength), packet.size() - (sizeof(dnsheader) + qnameWireLength), result);
}
}
- result = burtle((const unsigned char*) &tcp, sizeof(tcp), result);
+ result = burtle((const unsigned char*) &receivedOverUDP, sizeof(receivedOverUDP), result);
return result;
}
rcode = dh.rcode;
}
- fprintf(fp.get(), "%s %" PRId64 " %s ; rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", tcp %d, added %" PRId64 "\n", value.qname.toString().c_str(), static_cast<int64_t>(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.tcp, static_cast<int64_t>(value.added));
+ fprintf(fp.get(), "%s %" PRId64 " %s ; rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 "\n", value.qname.toString().c_str(), static_cast<int64_t>(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.receivedOverUDP, static_cast<int64_t>(value.added));
}
catch(...) {
fprintf(fp.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str());
DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t maxNegativeTTL=3600, uint32_t staleTTL=60, bool dontAge=false, uint32_t shards=1, bool deferrableInsertLock=true, bool parseECS=false);
~DNSDistPacketCache();
- void insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL);
- bool get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional<Netmask>& subnet, bool dnssecOK, uint32_t allowExpired = 0, bool skipAging = false);
+ void insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool receivedOverUDP, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL);
+ bool get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional<Netmask>& subnet, bool dnssecOK, bool receivedOverUDP, uint32_t allowExpired = 0, bool skipAging = false);
size_t purgeExpired(size_t upTo, const time_t now);
size_t expunge(size_t upTo=0);
size_t expungeByName(const DNSName& name, uint16_t qtype=QType::ANY, bool suffixMatch=false);
d_parseECS = enabled;
}
- uint32_t getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool tcp);
+ uint32_t getKey(const DNSName::string_t& qname, size_t qnameWireLength, const PacketBuffer& packet, bool receivedOverUDP);
static uint32_t getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA);
static bool getClientSubnet(const PacketBuffer& packet, size_t qnameWireLength, boost::optional<Netmask>& subnet);
time_t added{0};
time_t validity{0};
uint16_t len{0};
- bool tcp{false};
+ bool receivedOverUDP{false};
bool dnssecOK{false};
};
std::atomic<uint64_t> d_entriesCount{0};
};
- bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, bool dnssecOK, const boost::optional<Netmask>& subnet) const;
+ bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool receivedOverUDP, bool dnssecOK, const boost::optional<Netmask>& subnet) const;
uint32_t getShardIndex(uint32_t key) const;
void insertLocked(CacheShard& shard, uint32_t key, CacheValue& newValue);
DNSAction::Action TeeAction::operator()(DNSQuestion* dq, std::string* ruleresult) const
{
- if (dq->tcp) {
+ if (dq->overTCP()) {
d_tcpdrops++;
}
else {
static thread_local std::string data;
data.clear();
- DnstapMessage message(data, !dq->getHeader()->qr ? DnstapMessage::MessageType::client_query : DnstapMessage::MessageType::client_response, d_identity, dq->remote, dq->local, dq->tcp, reinterpret_cast<const char*>(dq->getData().data()), dq->getData().size(), dq->queryTime, nullptr);
+ DnstapMessage message(data, !dq->getHeader()->qr ? DnstapMessage::MessageType::client_query : DnstapMessage::MessageType::client_response, d_identity, dq->remote, dq->local, dq->overTCP(), reinterpret_cast<const char*>(dq->getData().data()), dq->getData().size(), dq->queryTime, nullptr);
{
if (d_alterFunc) {
std::lock_guard<std::mutex> lock(g_luamutex);
gettime(&now, true);
data.clear();
- DnstapMessage message(data, DnstapMessage::MessageType::client_response, d_identity, dr->remote, dr->local, dr->tcp, reinterpret_cast<const char*>(dr->getData().data()), dr->getData().size(), dr->queryTime, &now);
+ DnstapMessage message(data, DnstapMessage::MessageType::client_response, d_identity, dr->remote, dr->local, dr->overTCP(), reinterpret_cast<const char*>(dr->getData().data()), dr->getData().size(), dr->queryTime, &now);
{
if (d_alterFunc) {
std::lock_guard<std::mutex> lock(g_luamutex);
luaCtx.registerMember<dnsheader* (DNSQuestion::*)>("dh", [](const DNSQuestion& dq) -> dnsheader* { return const_cast<DNSQuestion&>(dq).getHeader(); }, [](DNSQuestion& dq, const dnsheader* dh) { *(dq.getHeader()) = *dh; });
luaCtx.registerMember<uint16_t (DNSQuestion::*)>("len", [](const DNSQuestion& dq) -> uint16_t { return dq.getData().size(); }, [](DNSQuestion& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); });
luaCtx.registerMember<uint8_t (DNSQuestion::*)>("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; });
- luaCtx.registerMember<bool (DNSQuestion::*)>("tcp", [](const DNSQuestion& dq) -> bool { return dq.tcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; });
+ luaCtx.registerMember<bool (DNSQuestion::*)>("tcp", [](const DNSQuestion& dq) -> bool { return dq.overTCP(); }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; });
luaCtx.registerMember<bool (DNSQuestion::*)>("skipCache", [](const DNSQuestion& dq) -> bool { return dq.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.skipCache = newSkipCache; });
luaCtx.registerMember<bool (DNSQuestion::*)>("useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; });
luaCtx.registerMember<bool (DNSQuestion::*)>("ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; });
luaCtx.registerMember<dnsheader* (DNSResponse::*)>("dh", [](const DNSResponse& dr) -> dnsheader* { return const_cast<DNSResponse&>(dr).getHeader(); }, [](DNSResponse& dr, const dnsheader* dh) { *(dr.getHeader()) = *dh; });
luaCtx.registerMember<uint16_t (DNSResponse::*)>("len", [](const DNSResponse& dq) -> uint16_t { return dq.getData().size(); }, [](DNSResponse& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); });
luaCtx.registerMember<uint8_t (DNSResponse::*)>("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; });
- luaCtx.registerMember<bool (DNSResponse::*)>("tcp", [](const DNSResponse& dq) -> bool { return dq.tcp; }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; });
+ luaCtx.registerMember<bool (DNSResponse::*)>("tcp", [](const DNSResponse& dq) -> bool { return dq.overTCP(); }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; });
luaCtx.registerMember<bool (DNSResponse::*)>("skipCache", [](const DNSResponse& dq) -> bool { return dq.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.skipCache = newSkipCache; });
luaCtx.registerFunction<void(DNSResponse::*)(std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)> editFunc)>("editTTLs", [](DNSResponse& dr, std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)> editFunc) {
editDNSPacketTTL(reinterpret_cast<char *>(dr.getMutableData().data()), dr.getData().size(), editFunc);
sw.start();
for(int n=0; n < times; ++n) {
item& i = items[n % items.size()];
- DNSQuestion dq(&i.qname, i.qtype, i.qclass, &i.rem, &i.rem, i.packet, false, &sw.d_start);
+ DNSQuestion dq(&i.qname, i.qtype, i.qclass, &i.rem, &i.rem, i.packet, DNSQuestion::Protocol::DoUDP, &sw.d_start);
if (rule->matches(&dq)) {
matches++;
}
m.setTime(ts.tv_sec, ts.tv_nsec / 1000);
}
- m.setRequest(d_dq.uniqueId ? *d_dq.uniqueId : getUniqueID(), d_requestor ? *d_requestor : *d_dq.remote, d_responder ? *d_responder : *d_dq.local, d_question ? d_question->d_name : *d_dq.qname, d_question ? d_question->d_type : d_dq.qtype, d_question ? d_question->d_class : d_dq.qclass, d_dq.getHeader()->id, d_dq.tcp, d_bytes ? *d_bytes : d_dq.getData().size());
+ m.setRequest(d_dq.uniqueId ? *d_dq.uniqueId : getUniqueID(), d_requestor ? *d_requestor : *d_dq.remote, d_responder ? *d_responder : *d_dq.local, d_question ? d_question->d_name : *d_dq.qname, d_question ? d_question->d_type : d_dq.qtype, d_question ? d_question->d_class : d_dq.qclass, d_dq.getHeader()->id, d_dq.overTCP(), d_bytes ? *d_bytes : d_dq.getData().size());
if (d_serverIdentity) {
m.setServerIdentity(*d_serverIdentity);
std::string remote = dq.remote->toString();
std::string qname = dq.qname->toStringNoDot();
const uint32_t socketFamily = dq.remote->isIPv4() ? 1 : 2;
- const uint32_t socketProtocol = dq.tcp ? 2 : 1;
+ const uint32_t socketProtocol = dq.overTCP() ? 2 : 1;
const uint32_t queryType = dq.getHeader()->qr ? 2 : 1;
const uint32_t querySize = (uint32_t) dq.getData().size();
const uint32_t queryID = (uint32_t) ntohs(dq.getHeader()->id);
const auto& ids = currentResponse.d_idstate;
double udiff = ids.sentTime.udiff();
g_rings.insertResponse(answertime, state->d_ci.remote, ids.qname, ids.qtype, static_cast<unsigned int>(udiff), static_cast<unsigned int>(currentResponse.d_buffer.size()), currentResponse.d_cleartextDH, ds->remote);
- vinfolog("Got answer from %s, relayed to %s (%s, %d bytes), took %f usec", ds->remote.toStringWithPort(), ids.origRemote.toStringWithPort(), (state->d_ci.cs->tlsFrontend ? "DoT" : "TCP"), currentResponse.d_buffer.size(), udiff);
+ vinfolog("Got answer from %s, relayed to %s (%s, %d bytes), took %f usec", ds->remote.toStringWithPort(), ids.origRemote.toStringWithPort(), (state->d_handler.isTLS() ? "DoT" : "TCP"), currentResponse.d_buffer.size(), udiff);
}
switch (currentResponse.d_cleartextDH.rcode) {
return;
}
- DNSResponse dr = makeDNSResponseFromIDState(ids, response.d_buffer, true);
+ DNSResponse dr = makeDNSResponseFromIDState(ids, response.d_buffer, state->d_handler.isTLS() ? DNSQuestion::Protocol::DoT : DNSQuestion::Protocol::DoTCP);
memcpy(&response.d_cleartextDH, dr.getHeader(), sizeof(response.d_cleartextDH));
- if (!processResponse(response.d_buffer, state->d_threadData.localRespRuleActions, dr, false)) {
+ if (!processResponse(response.d_buffer, state->d_threadData.localRespRuleActions, dr, false, false)) {
state->terminateClientConnection();
return;
}
uint16_t qtype, qclass;
unsigned int qnameWireLength = 0;
DNSName qname(reinterpret_cast<const char*>(state->d_buffer.data()), state->d_buffer.size(), sizeof(dnsheader), false, &qtype, &qclass, &qnameWireLength);
- DNSQuestion dq(&qname, qtype, qclass, &state->d_proxiedDestination, &state->d_proxiedRemote, state->d_buffer, true, &queryRealTime);
+ DNSQuestion::Protocol protocol = DNSQuestion::Protocol::DoTCP;
+ if (dnsCryptQuery) {
+ protocol = DNSQuestion::Protocol::DNSCryptTCP;
+ }
+ else if (state->d_handler.isTLS()) {
+ protocol = DNSQuestion::Protocol::DoT;
+ }
+
+ DNSQuestion dq(&qname, qtype, qclass, &state->d_proxiedDestination, &state->d_proxiedRemote, state->d_buffer, protocol, &queryRealTime);
dq.dnsCryptQuery = std::move(dnsCryptQuery);
dq.sni = state->d_handler.getServerNameIndication();
if (state->d_proxyProtocolValues) {
}
++state->d_currentQueriesCount;
- vinfolog("Got query for %s|%s from %s (%s, %d bytes), relayed to %s", query.d_idstate.qname.toLogString(), QType(query.d_idstate.qtype).toString(), state->d_proxiedRemote.toStringWithPort(), (state->d_ci.cs->tlsFrontend ? "DoT" : "TCP"), query.d_buffer.size(), ds->getName());
+ vinfolog("Got query for %s|%s from %s (%s, %d bytes), relayed to %s", query.d_idstate.qname.toLogString(), QType(query.d_idstate.qtype).toString(), state->d_proxiedRemote.toStringWithPort(), (state->d_handler.isTLS() ? "DoT" : "TCP"), query.d_buffer.size(), ds->getName());
downstreamConnection->queueQuery(std::move(query), downstreamConnection);
}
bool addXPF(DNSQuestion& dq, uint16_t optionCode)
{
- std::string payload = generateXPFPayload(dq.tcp, *dq.remote, *dq.local);
+ std::string payload = generateXPFPayload(dq.overTCP(), *dq.remote, *dq.local);
uint8_t root = '\0';
dnsrecordheader drh;
drh.d_type = htons(optionCode);
return true;
}
-bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted)
+// whether the query was received over TCP or not (for rules, dnstap, protobuf, ...) will be taken from the DNSResponse, but receivedOverUDP is used to insert into the cache,
+// so that answers received over UDP for DoH are still cached with UDP answers.
+bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted, bool receivedOverUDP)
{
if (!applyRulesToResponse(localRespRuleActions, dr)) {
return false;
zeroScope = false;
}
// if zeroScope, pass the pre-ECS hash-key and do not pass the subnet to the cache
- dr.packetCache->insert(zeroScope ? dr.cacheKeyNoECS : dr.cacheKey, zeroScope ? boost::none : dr.subnet, dr.origFlags, dr.dnssecOK, *dr.qname, dr.qtype, dr.qclass, response, dr.tcp, dr.getHeader()->rcode, dr.tempFailureTTL);
+ dr.packetCache->insert(zeroScope ? dr.cacheKeyNoECS : dr.cacheKey, zeroScope ? boost::none : dr.subnet, dr.origFlags, dr.dnssecOK, *dr.qname, dr.qtype, dr.qclass, response, receivedOverUDP, dr.getHeader()->rcode, dr.tempFailureTTL);
}
#ifdef HAVE_DNSCRYPT
if (!muted) {
- if (!encryptResponse(response, dr.getMaximumSize(), dr.tcp, dr.dnsCryptQuery)) {
+ if (!encryptResponse(response, dr.getMaximumSize(), dr.overTCP(), dr.dnsCryptQuery)) {
return false;
}
}
dh->id = ids->origID;
- DNSResponse dr = makeDNSResponseFromIDState(*ids, response, false);
+ DNSResponse dr = makeDNSResponseFromIDState(*ids, response, DNSQuestion::Protocol::DoUDP);
if (dh->tc && g_truncateTC) {
truncateTC(response, dr.getMaximumSize(), qnameWireLength);
}
memcpy(&cleartextDH, dr.getHeader(), sizeof(cleartextDH));
- if (!processResponse(response, localRespRuleActions, dr, ids->cs && ids->cs->muted)) {
+ if (!processResponse(response, localRespRuleActions, dr, ids->cs && ids->cs->muted, true)) {
continue;
}
return true;
case DNSAction::Action::Truncate:
- if(!dq.tcp) {
+ if (!dq.overTCP()) {
updateBlockStats();
vinfolog("Query from %s truncated because of dynamic block", dq.remote->toStringWithPort());
dq.getHeader()->tc = true;
dq.getHeader()->qr=true;
return true;
case DNSAction::Action::Truncate:
- if(!dq.tcp) {
+ if (!dq.overTCP()) {
updateBlockStats();
vinfolog("Query from %s for %s truncated because of dynamic block", dq.remote->toStringWithPort(), dq.qname->toLogString());
/* self-generated responses or cache hits */
static bool prepareOutgoingResponse(LocalHolders& holders, ClientState& cs, DNSQuestion& dq, bool cacheHit)
{
- DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, dq.getMutableData(), dq.tcp, dq.queryTime);
+ DNSResponse dr(dq.qname, dq.qtype, dq.qclass, dq.local, dq.remote, dq.getMutableData(), dq.protocol, dq.queryTime);
dr.uniqueId = dq.uniqueId;
dr.qTag = dq.qTag;
#ifdef HAVE_DNSCRYPT
if (!cs.muted) {
- if (!encryptResponse(dq.getMutableData(), dq.getMaximumSize(), dq.tcp, dq.dnsCryptQuery)) {
+ if (!encryptResponse(dq.getMutableData(), dq.getMaximumSize(), dq.overTCP(), dq.dnsCryptQuery)) {
return false;
}
}
// we need ECS parsing (parseECS) to be true so we can be sure that the initial incoming query did not have an existing
// ECS option, which would make it unsuitable for the zero-scope feature.
if (dq.packetCache && !dq.skipCache && (!selectedBackend || !selectedBackend->disableZeroScope) && dq.packetCache->isECSParsingEnabled()) {
- if (dq.packetCache->get(dq, dq.getHeader()->id, &dq.cacheKeyNoECS, dq.subnet, dq.dnssecOK, allowExpired)) {
+ if (dq.packetCache->get(dq, dq.getHeader()->id, &dq.cacheKeyNoECS, dq.subnet, dq.dnssecOK, !dq.overTCP() || dq.getProtocol() == DNSQuestion::Protocol::DoH, allowExpired)) {
if (!prepareOutgoingResponse(holders, cs, dq, true)) {
return ProcessQueryResult::Drop;
}
if (dq.packetCache && !dq.skipCache) {
- if (dq.packetCache->get(dq, dq.getHeader()->id, &dq.cacheKey, dq.subnet, dq.dnssecOK, allowExpired)) {
+ if (dq.packetCache->get(dq, dq.getHeader()->id, &dq.cacheKey, dq.subnet, dq.dnssecOK, !dq.overTCP() || dq.getProtocol() == DNSQuestion::Protocol::DoH, allowExpired)) {
if (!prepareOutgoingResponse(holders, cs, dq, true)) {
return ProcessQueryResult::Drop;
return ProcessQueryResult::PassToBackend;
}
catch (const std::exception& e){
- vinfolog("Got an error while parsing a %s query from %s, id %d: %s", (dq.tcp ? "TCP" : "UDP"), dq.remote->toStringWithPort(), queryId, e.what());
+ vinfolog("Got an error while parsing a %s query from %s, id %d: %s", (dq.overTCP() ? "TCP" : "UDP"), dq.remote->toStringWithPort(), queryId, e.what());
}
return ProcessQueryResult::Drop;
}
uint16_t qtype, qclass;
unsigned int qnameWireLength = 0;
DNSName qname(reinterpret_cast<const char*>(query.data()), query.size(), sizeof(dnsheader), false, &qtype, &qclass, &qnameWireLength);
- DNSQuestion dq(&qname, qtype, qclass, proxiedDestination.sin4.sin_family != 0 ? &proxiedDestination : &cs.local, &proxiedRemote, query, false, &queryRealTime);
+ DNSQuestion dq(&qname, qtype, qclass, proxiedDestination.sin4.sin_family != 0 ? &proxiedDestination : &cs.local, &proxiedRemote, query, dnsCryptQuery ? DNSQuestion::Protocol::DNSCryptUDP : DNSQuestion::Protocol::DoUDP, &queryRealTime);
dq.dnsCryptQuery = std::move(dnsCryptQuery);
if (!proxyProtocolValues.empty()) {
dq.proxyProtocolValues = make_unique<std::vector<ProxyProtocolValue>>(std::move(proxyProtocolValues));
struct DNSQuestion
{
- DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
- data(data_), qname(name), local(lc), remote(rem), queryTime(queryTime_), tempFailureTTL(boost::none), qtype(type), qclass(class_), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), tcp(isTcp), ecsOverride(g_ECSOverride) {
+ enum class Protocol : uint8_t { DoUDP, DoTCP, DNSCryptUDP, DNSCryptTCP, DoT, DoH };
+
+ DNSQuestion(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, Protocol proto, const struct timespec* queryTime_):
+ data(data_), qname(name), local(lc), remote(rem), queryTime(queryTime_), tempFailureTTL(boost::none), qtype(type), qclass(class_), ecsPrefixLength(rem->sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), protocol(proto), ecsOverride(g_ECSOverride) {
const uint16_t* flags = getFlagsFromDNSHeader(getHeader());
origFlags = *flags;
}
size_t getMaximumSize() const
{
- if (tcp) {
+ if (overTCP()) {
return std::numeric_limits<uint16_t>::max();
}
return 4096;
}
+ Protocol getProtocol() const
+ {
+ return protocol;
+ }
+
+ bool overTCP() const
+ {
+ const std::set<Protocol> tcpProto = { Protocol::DoTCP, Protocol::DNSCryptTCP, Protocol::DoT, Protocol::DoH };
+ return tcpProto.count(protocol);
+ }
+
protected:
- PacketBuffer& data;
+ PacketBuffer& data;
public:
boost::optional<boost::uuids::uuid> uniqueId;
const uint16_t qclass;
uint16_t ecsPrefixLength;
uint16_t origFlags;
+ Protocol protocol;
uint8_t ednsRCode{0};
- const bool tcp;
bool skipCache{false};
bool ecsOverride;
bool useECS{true};
struct DNSResponse : DNSQuestion
{
- DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, bool isTcp, const struct timespec* queryTime_):
- DNSQuestion(name, type, class_, lc, rem, data_, isTcp, queryTime_) { }
+ DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, const ComboAddress* lc, const ComboAddress* rem, PacketBuffer& data_, DNSQuestion::Protocol proto, const struct timespec* queryTime_):
+ DNSQuestion(name, type, class_, lc, rem, data_, proto, queryTime_) { }
DNSResponse(const DNSResponse&) = delete;
DNSResponse& operator=(const DNSResponse&) = delete;
DNSResponse(DNSResponse&&) = default;
void resetLuaSideEffect(); // reset to indeterminate state
bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& remote, unsigned int& qnameWireLength);
-bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted);
+bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted, bool receivedOverUDP);
bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::string& ruleresult, bool& drop);
bool checkQueryHeaders(const struct dnsheader* dh);
enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };
ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& holders, std::shared_ptr<DownstreamState>& selectedBackend);
-DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP);
+DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, DNSQuestion::Protocol proto);
void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname);
int pickBackendSocketForSending(std::shared_ptr<DownstreamState>& state);
#include "dnsdist.hh"
-DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, bool isTCP)
+DNSResponse makeDNSResponseFromIDState(IDState& ids, PacketBuffer& data, DNSQuestion::Protocol proto)
{
- DNSResponse dr(&ids.qname, ids.qtype, ids.qclass, &ids.origDest, &ids.origRemote, data, isTCP, &ids.sentTime.d_start);
+ DNSResponse dr(&ids.qname, ids.qtype, ids.qclass, &ids.origDest, &ids.origRemote, data, proto, &ids.sentTime.d_start);
dr.origFlags = ids.origFlags;
dr.ecsAdded = ids.ecsAdded;
dr.ednsAdded = ids.ednsAdded;
bool dnsdist_ffi_dnsquestion_get_tcp(const dnsdist_ffi_dnsquestion_t* dq)
{
- return dq->dq->tcp;
+ return dq->dq->overTCP();
}
bool dnsdist_ffi_dnsquestion_get_skip_cache(const dnsdist_ffi_dnsquestion_t* dq)
std::string getProxyProtocolPayload(const DNSQuestion& dq)
{
- return makeProxyHeader(dq.tcp, *dq.remote, *dq.local, dq.proxyProtocolValues ? *dq.proxyProtocolValues : std::vector<ProxyProtocolValue>());
+ return makeProxyHeader(dq.overTCP(), *dq.remote, *dq.local, dq.proxyProtocolValues ? *dq.proxyProtocolValues : std::vector<ProxyProtocolValue>());
}
bool addProxyProtocol(DNSQuestion& dq, const std::string& payload)
}
bool matches(const DNSQuestion* dq) const override
{
- return dq->tcp == d_tcp;
+ return dq->overTCP() == d_tcp;
}
string toString() const override
{
uint16_t qtype, qclass;
unsigned int qnameWireLength = 0;
DNSName qname(reinterpret_cast<const char*>(du->query.data()), du->query.size(), sizeof(dnsheader), false, &qtype, &qclass, &qnameWireLength);
- DNSQuestion dq(&qname, qtype, qclass, &du->dest, &du->remote, du->query, false, &queryRealTime);
+ DNSQuestion dq(&qname, qtype, qclass, &du->dest, &du->remote, du->query, DNSQuestion::Protocol::DoH, &queryRealTime);
dq.ednsAdded = du->ednsAdded;
dq.du = du;
dq.sni = std::move(du->sni);
ComboAddress lc("192.0.2.1:53");
ComboAddress rem("192.0.2.128:42");
PacketBuffer packet(sizeof(dnsheader));
- bool isTcp = false;
+ auto proto = DNSQuestion::Protocol::DoUDP;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
struct timespec expiredTime;
/* the internal QPS limiter does not use the real time */
gettime(&expiredTime);
- DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, isTcp, &queryRealTime);
+ DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, proto, &queryRealTime);
ComboAddress v4Masked(v4ToMask);
ComboAddress v6Masked(v6ToMask);
v4Masked.truncate(25);
ComboAddress lc("192.0.2.1:53");
ComboAddress rem("192.0.2.128:42");
PacketBuffer packet(sizeof(dnsheader));
- bool isTcp = false;
+ auto proto = DNSQuestion::Protocol::DoUDP;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
struct timespec expiredTime;
/* the internal QPS limiter does not use the real time */
gettime(&expiredTime);
- DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, isTcp, &queryRealTime);
+ DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, proto, &queryRealTime);
ComboAddress v4Masked(v4ToMask);
ComboAddress v6Masked(v6ToMask);
v4Masked.truncate(25);
uint16_t qtype = QType::A;
uint16_t qclass = QClass::IN;
- bool isTcp = false;
+ auto proto = DNSQuestion::Protocol::DoUDP;
gettime(&queryRealTime, true);
- DNSQuestion dq(providedName ? providedName : &qname, qtype, qclass, &lc, &rem, packet, isTcp, &queryRealTime);
+ DNSQuestion dq(providedName ? providedName : &qname, qtype, qclass, &lc, &rem, packet, proto, &queryRealTime);
return dq;
}
ComboAddress lc("127.0.0.1:53");
ComboAddress rem("192.0.2.1:42");
PacketBuffer packet(sizeof(dnsheader));
- bool isTcp = false;
+ auto proto = DNSQuestion::Protocol::DoUDP;
struct timespec queryRealTime;
gettime(&queryRealTime, true);
struct timespec expiredTime;
/* the internal QPS limiter does not use the real time */
gettime(&expiredTime);
- DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, isTcp, &queryRealTime);
+ DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, proto, &queryRealTime);
for (size_t idx = 0; idx < maxQPS; idx++) {
/* let's use different source ports, it shouldn't matter */
static std::function<bool(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted)> s_processResponse;
-bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted)
+bool processResponse(PacketBuffer& response, LocalStateHolder<vector<DNSDistResponseRuleAction> >& localRespRuleActions, DNSResponse& dr, bool muted, bool receivedOverUDP)
{
if (s_processResponse) {
return s_processResponse(response, localRespRuleActions, dr, muted);
uint16_t qtype;
uint16_t qclass;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, &qclass, &consumed);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &rem, const_cast<PacketBuffer&>(packet), false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &rem, const_cast<PacketBuffer&>(packet), DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(parseEDNSOptions(dq));
BOOST_REQUIRE(dq.ednsOptions != nullptr);
BOOST_CHECK_EQUAL(dq.ednsOptions->size(), 1U);
BOOST_CHECK_EQUAL(qname, name);
BOOST_CHECK(qtype == QType::A);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_CHECK(addXPF(dq, xpfOptionCode));
BOOST_CHECK(packet.size() > query.size());
BOOST_CHECK_EQUAL(qname, name);
BOOST_CHECK(qtype == QType::A);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_REQUIRE(!addXPF(dq, xpfOptionCode));
BOOST_CHECK_EQUAL(packet.size(), 4096U);
BOOST_CHECK_EQUAL(qname, name);
BOOST_CHECK(qtype == QType::A);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
/* add trailing data */
const size_t trailingDataSize = 10;
BOOST_CHECK(qtype == QType::A);
BOOST_CHECK(qclass == QClass::IN);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
/* Parse the options before handling ECS, simulating a Lua rule asking for EDNS Options */
BOOST_CHECK(!parseEDNSOptions(dq));
BOOST_CHECK_EQUAL(qname, name);
BOOST_CHECK(qtype == QType::A);
BOOST_CHECK(qclass == QClass::IN);
- DNSQuestion dq2(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq2(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(handleEDNSClientSubnet(dq2, ednsAdded, ecsAdded));
BOOST_CHECK_GT(packet.size(), query.size());
BOOST_CHECK(qtype == QType::A);
BOOST_CHECK(qclass == QClass::IN);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
/* Parse the options before handling ECS, simulating a Lua rule asking for EDNS Options */
BOOST_CHECK(parseEDNSOptions(dq));
BOOST_CHECK_EQUAL(qname, name);
BOOST_CHECK(qtype == QType::A);
BOOST_CHECK(qclass == QClass::IN);
- DNSQuestion dq2(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq2(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(handleEDNSClientSubnet(dq2, ednsAdded, ecsAdded));
BOOST_CHECK_GT(packet.size(), query.size());
BOOST_CHECK(qtype == QType::A);
BOOST_CHECK(qclass == QClass::IN);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
dq.ecsOverride = true;
/* Parse the options before handling ECS, simulating a Lua rule asking for EDNS Options */
static DNSQuestion getDNSQuestion(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& realTime, PacketBuffer& query)
{
- return DNSQuestion(&qname, qtype, qclass, &lc, &rem, query, false, &realTime);
+ return DNSQuestion(&qname, qtype, qclass, &lc, &rem, query, DNSQuestion::Protocol::DoUDP, &realTime);
}
static DNSQuestion turnIntoResponse(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& queryRealTime, PacketBuffer& query, bool resizeBuffer=true)
unsigned int consumed = 0;
uint16_t qtype;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
BOOST_CHECK(packet.size() > query.size());
unsigned int consumed = 0;
uint16_t qtype;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
BOOST_CHECK(packet.size() > queryWithEDNS.size());
unsigned int consumed = 0;
uint16_t qtype;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
BOOST_CHECK(packet.size() > query.size());
unsigned int consumed = 0;
uint16_t qtype;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
- DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, false, &queryTime);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, DNSQuestion::Protocol::DoUDP, &queryTime);
BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
BOOST_CHECK(packet.size() > queryWithEDNS.size());
uint16_t qtype;
uint16_t qclass;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, &qclass, &consumed);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(!parseEDNSOptions(dq));
}
uint16_t qtype;
uint16_t qclass;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, &qclass, &consumed);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(!parseEDNSOptions(dq));
}
uint16_t qtype;
uint16_t qclass;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, &qclass, &consumed);
- DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, false, nullptr);
+ DNSQuestion dq(&qname, qtype, qclass, nullptr, &remote, packet, DNSQuestion::Protocol::DoUDP, nullptr);
BOOST_CHECK(!parseEDNSOptions(dq));
}
BOOST_AUTO_TEST_SUITE(test_dnsdistpacketcache_cc)
+static bool receivedOverUDP = true;
+
BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) {
const size_t maxEntries = 150000;
DNSDistPacketCache PC(maxEntries, 86400, 1);
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, false, 0, boost::none);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
if (found == true) {
BOOST_CHECK_EQUAL(dq.getData().size(), response.size());
int match = memcmp(dq.getData().data(), response.data(), dq.getData().size());
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
if (found == true) {
auto removed = PC.expungeByName(a);
BOOST_CHECK_EQUAL(removed, 1U);
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- if (PC.get(dq, pwQ.getHeader()->id, &key, subnet, dnssecOK)) {
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ if (PC.get(dq, pwQ.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP)) {
matches++;
}
}
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::AAAA, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::AAAA, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::AAAA, QClass::IN, response, false, 0, boost::none);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::AAAA, QClass::IN, response, receivedOverUDP, 0, boost::none);
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
if (found == true) {
BOOST_CHECK_EQUAL(dq.getData().size(), response.size());
int match = memcmp(dq.getData().data(), response.data(), dq.getData().size());
pwQ.getHeader()->rd = 1;
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::AAAA, QClass::IN, &remote, &remote, query, false, &queryTime);
- if (PC.get(dq, pwQ.getHeader()->id, &key, subnet, dnssecOK)) {
+ DNSQuestion dq(&a, QType::AAAA, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ if (PC.get(dq, pwQ.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP)) {
matches++;
}
}
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
// Insert with failure-TTL of 0 (-> should not enter cache).
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, false, RCode::ServFail, boost::optional<uint32_t>(0));
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(0));
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
// Insert with failure-TTL non-zero (-> should enter cache).
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, false, RCode::ServFail, boost::optional<uint32_t>(300));
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(300));
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, true);
BOOST_CHECK(!subnet);
}
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&name, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&name, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, false, RCode::NoError, boost::none);
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, true);
BOOST_CHECK(!subnet);
sleep(2);
/* it should have expired by now */
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
}
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&name, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&name, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
- PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, false, RCode::NXDomain, boost::none);
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NXDomain, boost::none);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, true);
BOOST_CHECK(!subnet);
sleep(2);
/* it should have expired by now */
- found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, 0, true);
+ found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK(!subnet);
}
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- g_PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ g_PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
- g_PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, false, 0, boost::none);
+ g_PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
}
}
catch(PDNSException& e) {
uint32_t key = 0;
boost::optional<Netmask> subnet;
- DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = g_PC.get(dq, 0, &key, subnet, dnssecOK);
+ DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = g_PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
if (!found) {
g_missing++;
}
ComboAddress remote("192.0.2.1");
struct timespec queryTime;
gettime(&queryTime);
- DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnetOut, dnssecOK);
+ DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnetOut, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_REQUIRE(subnetOut);
BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
pwR.addOpt(512, 0, 0, ednsOptions);
pwR.commit();
- PC.insert(key, subnetOut, *(getFlagsFromDNSHeader(pwR.getHeader())), dnssecOK, qname, qtype, QClass::IN, response, false, RCode::NoError, boost::none);
+ PC.insert(key, subnetOut, *(getFlagsFromDNSHeader(pwR.getHeader())), dnssecOK, qname, qtype, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
BOOST_CHECK_EQUAL(PC.getSize(), 1U);
- found = PC.get(dq, 0, &key, subnetOut, dnssecOK);
+ found = PC.get(dq, 0, &key, subnetOut, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, true);
BOOST_REQUIRE(subnetOut);
BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
ComboAddress remote("192.0.2.1");
struct timespec queryTime;
gettime(&queryTime);
- DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &secondKey, subnetOut, dnssecOK);
+ DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &secondKey, subnetOut, dnssecOK, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
BOOST_CHECK_EQUAL(secondKey, key);
BOOST_REQUIRE(subnetOut);
ComboAddress remote("192.0.2.1");
struct timespec queryTime;
gettime(&queryTime);
- DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, false, &queryTime);
- bool found = PC.get(dq, 0, &key, subnetOut, true);
+ DNSQuestion dq(&qname, QType::AAAA, QClass::IN, &remote, &remote, query, DNSQuestion::Protocol::DoUDP, &queryTime);
+ bool found = PC.get(dq, 0, &key, subnetOut, true, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
PacketBuffer response;
pwR.addOpt(512, 0, EDNS_HEADER_FLAG_DO);
pwR.commit();
- PC.insert(key, subnetOut, *(getFlagsFromDNSHeader(pwR.getHeader())), /* DNSSEC OK is set */ true, qname, qtype, QClass::IN, response, false, RCode::NoError, boost::none);
+ PC.insert(key, subnetOut, *(getFlagsFromDNSHeader(pwR.getHeader())), /* DNSSEC OK is set */ true, qname, qtype, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
BOOST_CHECK_EQUAL(PC.getSize(), 1U);
- found = PC.get(dq, 0, &key, subnetOut, false);
+ found = PC.get(dq, 0, &key, subnetOut, false, receivedOverUDP);
BOOST_CHECK_EQUAL(found, false);
- found = PC.get(dq, 0, &key, subnetOut, true);
+ found = PC.get(dq, 0, &key, subnetOut, true, receivedOverUDP);
BOOST_CHECK_EQUAL(found, true);
}