1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#include <iostream>
#include <boost/foreach.hpp>
#include "recpacketcache.hh"
#include "cachecleaner.hh"
#include "dns.hh"
#include "namespaces.hh"
#include "lock.hh"
#include "dnswriter.hh"
RecursorPacketCache::RecursorPacketCache()
{
d_hits = d_misses = 0;
}
int RecursorPacketCache::doWipePacketCache(const string& name, uint16_t qtype)
{
vector<uint8_t> packet;
DNSPacketWriter pw(packet, toLower(name), 0);
pw.getHeader()->rd=1;
Entry e;
e.d_packet.assign((const char*)&*packet.begin(), packet.size());
// so the idea is, we search for a packet with qtype=0, which is ahead of anything with that name
int count=0;
for(packetCache_t::iterator iter = d_packetCache.lower_bound(e); iter != d_packetCache.end(); ) {
const struct dnsheader* packet = reinterpret_cast<const struct dnsheader*>((*iter).d_packet.c_str());
if(packet->qdcount==0)
break;
uint16_t t;
string found=questionExpand(iter->d_packet.c_str(), iter->d_packet.length(), t);
if(!pdns_iequals(found, name)) {
break;
}
if(t==qtype || qtype==0xffff) {
iter=d_packetCache.erase(iter);
count++;
}
else
++iter;
}
return count;
}
bool RecursorPacketCache::getResponsePacket(const std::string& queryPacket, time_t now,
std::string* responsePacket, uint32_t* age)
{
struct Entry e;
e.d_packet=queryPacket;
packetCache_t::const_iterator iter = d_packetCache.find(e);
if(iter == d_packetCache.end()) {
d_misses++;
return false;
}
if((uint32_t)now < iter->d_ttd) { // it is fresh!
// cerr<<"Fresh for another "<<iter->d_ttd - now<<" seconds!"<<endl;
*age = now - iter->d_creation;
uint16_t id;
memcpy(&id, queryPacket.c_str(), 2);
*responsePacket = iter->d_packet;
responsePacket->replace(0, 2, (char*)&id, 2);
string::size_type i=sizeof(dnsheader);
for(;;) {
int labellen = (unsigned char)queryPacket[i];
if(!labellen || i + labellen > responsePacket->size()) break;
i++;
responsePacket->replace(i, labellen, queryPacket, i, labellen);
i = i + labellen;
}
d_hits++;
moveCacheItemToBack(d_packetCache, iter);
return true;
}
moveCacheItemToFront(d_packetCache, iter);
d_misses++;
return false;
}
void RecursorPacketCache::insertResponsePacket(const std::string& responsePacket, time_t now, uint32_t ttl)
{
struct Entry e;
e.d_packet = responsePacket;
e.d_ttd = now+ttl;
e.d_creation = now;
packetCache_t::iterator iter = d_packetCache.find(e);
if(iter != d_packetCache.end()) {
iter->d_packet = responsePacket;
iter->d_ttd = now + ttl;
iter->d_creation = now;
}
else
d_packetCache.insert(e);
}
uint64_t RecursorPacketCache::size()
{
return d_packetCache.size();
}
uint64_t RecursorPacketCache::bytes()
{
uint64_t sum=0;
BOOST_FOREACH(const struct Entry& e, d_packetCache) {
sum += sizeof(e) + e.d_packet.length() + 4;
}
return sum;
}
void RecursorPacketCache::doPruneTo(unsigned int maxCached)
{
pruneCollection(d_packetCache, maxCached);
}
|