g_lua.writeFunction("topClients", [](unsigned int top) {
map<ComboAddress, int,ComboAddress::addressOnlyLessThan > counts;
unsigned int total=0;
- for(const auto& c : g_rings.clientRing) {
- counts[c]++;
+ for(const auto& c : g_rings.queryRing) {
+ counts[c.requestor]++;
total++;
}
vector<pair<int, ComboAddress>> rcounts;
unsigned int total=0;
if(!labels) {
for(const auto& a : g_rings.queryRing) {
- counts[a]++;
+ counts[a.name]++;
total++;
}
}
else {
unsigned int lab = *labels;
for(auto a : g_rings.queryRing) {
- a.trimToLabels(lab);
- counts[a]++;
+ a.name.trimToLabels(lab);
+ counts[a.name]++;
total++;
}
return filterScore(counts, mintime, maxtime, rate);
}
+map<ComboAddress,int> exceedQueryGen(int rate, int seconds, std::function<void(counts_t&, const Rings::Query&)> T)
+{
+ counts_t counts;
+ struct timespec mintime, maxtime, cutoff;
+ clock_gettime(CLOCK_MONOTONIC, &maxtime);
+ mintime=cutoff=maxtime;
+ cutoff.tv_sec -= seconds;
+
+ for(const auto& c : g_rings.queryRing) {
+ if(seconds && c.when < cutoff)
+ continue;
+
+ T(counts, c);
+ if(c.when < mintime)
+ mintime = c.when;
+ }
+
+ return filterScore(counts, mintime, maxtime, rate);
+}
+
map<ComboAddress,int> exceedRCode(int rate, int seconds, int rcode)
{
g_lua.registerFunction<bool(NetmaskGroup::*)(const ComboAddress&)>("match",
[](NetmaskGroup& s, const ComboAddress& ca) { return s.match(ca); });
-
g_lua.writeFunction("exceedServfails", [](unsigned int rate, int seconds) {
return exceedRCode(rate, seconds, RCode::ServFail);
});
return exceedRCode(rate, seconds, RCode::NXDomain);
});
+
+
g_lua.writeFunction("exceedRespByterate", [](unsigned int rate, int seconds) {
return exceedRespByterate(rate, seconds);
});
+ g_lua.writeFunction("exceedQTypeRate", [](uint16_t type, unsigned int rate, int seconds) {
+ return exceedQueryGen(rate, seconds, [type](counts_t& counts, const Rings::Query& q) {
+ if(q.qtype==type)
+ counts[q.requestor]++;
+ });
+
+
+ });
+
}
for(;;) {
try {
len = recvmsg(cs->udpFD, &msgh, 0);
- g_rings.clientRing.push_back(remote);
+
if(len < (int)sizeof(struct dnsheader)) {
g_stats.nonCompliantQueries++;
continue;
const uint16_t * flags = getFlagsFromDNSHeader(dh);
const uint16_t origFlags = *flags;
DNSName qname(packet, len, 12, false, &qtype);
- g_rings.queryRing.push_back(qname);
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ g_rings.queryRing.push_back({now,remote,qname,qtype}); // XXX LOCK?!
if(blockFilter) {
std::lock_guard<std::mutex> lock(g_luamutex);
struct Rings {
Rings()
{
- clientRing.set_capacity(10000);
queryRing.set_capacity(10000);
respRing.set_capacity(10000);
}
- boost::circular_buffer<ComboAddress> clientRing;
- boost::circular_buffer<DNSName> queryRing;
+ struct Query
+ {
+ struct timespec when;
+ ComboAddress requestor;
+ DNSName name;
+ uint16_t qtype;
+ };
+ boost::circular_buffer<Query> queryRing;
struct Response
{
struct timespec when;