getPool("poolname"):getCache()
```
+And removed with:
+
+```
+getPool("poolname"):unsetCache()
+```
+
Cache usage stats (hits, misses, deferred inserts and lookups, collisions)
can be displayed by using the `printStats()` method:
* ServerPool related:
* `getCache()`: return the current packet cache, if any
* `setCache(PacketCache)`: set the cache for this pool
+ * `unsetCache()`: remove the packet cache from this pool
* PacketCache related:
* `expunge(n)`: remove entries from the cache, leaving at most `n` entries
* `expungeByName(DNSName [, qtype=ANY])`: remove entries matching the supplied DNSName and type from the cache
void DNSDistPacketCache::insert(uint32_t key, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, bool servFail)
{
- if (responseLen == 0)
+ if (responseLen < sizeof(dnsheader))
return;
uint32_t minTTL;
}
string dnsQName(dq.qname->toDNSString());
+ const size_t dnsQNameLen = dnsQName.length();
+ if (value.len < (sizeof(dnsheader) + dnsQNameLen)) {
+ return false;
+ }
+
memcpy(response, &queryId, sizeof(queryId));
memcpy(response + sizeof(queryId), value.value.c_str() + sizeof(queryId), sizeof(dnsheader) - sizeof(queryId));
- memcpy(response + sizeof(dnsheader), dnsQName.c_str(), dnsQName.length());
- memcpy(response + sizeof(dnsheader) + dnsQName.length(), value.value.c_str() + sizeof(dnsheader) + dnsQName.length(), value.value.length() - (sizeof(dnsheader) + dnsQName.length()));
+ memcpy(response + sizeof(dnsheader), dnsQName.c_str(), dnsQNameLen);
+ if (value.len > (sizeof(dnsheader) + dnsQNameLen)) {
+ memcpy(response + sizeof(dnsheader) + dnsQNameLen, value.value.c_str() + sizeof(dnsheader) + dnsQNameLen, value.len - (sizeof(dnsheader) + dnsQNameLen));
+ }
*responseLen = value.len;
if (!stale) {
age = now - value.added;
pool->packetCache = cache;
});
g_lua.registerFunction("getCache", &ServerPool::getCache);
+ g_lua.registerFunction<void(std::shared_ptr<ServerPool>::*)()>("unsetCache", [](std::shared_ptr<ServerPool> pool) {
+ pool->packetCache = nullptr;
+ });
g_lua.writeFunction("newPacketCache", [client](size_t maxEntries, boost::optional<uint32_t> maxTTL, boost::optional<uint32_t> minTTL, boost::optional<uint32_t> servFailTTL, boost::optional<uint32_t> staleTTL) {
return std::make_shared<DNSDistPacketCache>(maxEntries, maxTTL ? *maxTTL : 86400, minTTL ? *minTTL : 60, servFailTTL ? *servFailTTL : 60, staleTTL ? *staleTTL : 60);
--ds->outstanding;
outstanding = false;
+ if (rlen < sizeof(dnsheader)) {
+ break;
+ }
+
+ dh = (struct dnsheader*) response;
+ DNSName rqname;
+ uint16_t rqtype, rqclass;
+ try {
+ rqname=DNSName(response, responseLen, sizeof(dnsheader), false, &rqtype, &rqclass, &consumed);
+ }
+ catch(std::exception& e) {
+ if(rlen > (ssize_t)sizeof(dnsheader))
+ infolog("Backend %s sent us a response with id %d that did not parse: %s", ds->remote.toStringWithPort(), ntohs(dh->id), e.what());
+ g_stats.nonCompliantResponses++;
+ break;
+ }
+
+ if (rqtype != qtype || rqclass != qclass || rqname != qname) {
+ break;
+ }
+
if (ednsAdded) {
const char * optStart = NULL;
size_t optLen = 0;
if(g_fixupCase) {
string realname = qname.toDNSString();
- memcpy(response + sizeof(dnsheader), realname.c_str(), realname.length());
+ if (responseLen >= (sizeof(dnsheader) + realname.length())) {
+ memcpy(response + sizeof(dnsheader), realname.c_str(), realname.length());
+ }
}
if (packetCache && !dq.skipCache) {
if(g_fixupCase) {
string realname = ids->qname.toDNSString();
- memcpy(packet+12, realname.c_str(), realname.length());
+ if (responseLen >= (sizeof(dnsheader) + realname.length())) {
+ memcpy(packet+12, realname.c_str(), realname.length());
+ }
}
if(dh->tc && g_truncateTC) {
receivedQuery.id = query.id
self.assertEquals(query, receivedQuery)
+ (receivedQuery, receivedResponse) = self.sendTCPQuery(query, unrelatedResponse)
+ self.assertTrue(receivedQuery)
+ self.assertEquals(receivedResponse, None)
+ receivedQuery.id = query.id
+ self.assertEquals(query, receivedQuery)
+
if __name__ == '__main__':
unittest.main()