Coverage Report

Created: 2026-10-03 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pdns/pdns/dnsdistdist/dnsdist-dynbpf.cc
Line
Count
Source
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#include "dnsdist-dynbpf.hh"
23
24
std::vector<std::shared_ptr<DynBPFFilter>> g_dynBPFFilters;
25
26
bool DynBPFFilter::block(const ComboAddress& addr, const struct timespec& until)
27
0
{
28
0
  bool inserted = false;
29
0
  auto data = d_data.lock();
30
31
0
  if (data->d_excludedSubnets.match(addr)) {
32
    /* do not add a block for excluded subnets */
33
0
    return inserted;
34
0
  }
35
36
0
  auto entriesIt = data->d_entries.find(addr);
37
0
  if (entriesIt != data->d_entries.end()) {
38
0
    if (entriesIt->d_until < until) {
39
0
      data->d_entries.replace(entriesIt, BlockEntry(addr, until));
40
0
    }
41
0
  }
42
0
  else {
43
0
    data->d_bpf->block(addr, BPFFilter::MatchAction::Drop);
44
0
    data->d_entries.insert(BlockEntry(addr, until));
45
0
    inserted = true;
46
0
  }
47
0
  return inserted;
48
0
}
49
50
void DynBPFFilter::purgeExpired(const struct timespec& now)
51
0
{
52
0
  auto data = d_data.lock();
53
54
0
  using ordered_until = boost::multi_index::nth_index<container_t, 1>::type;
55
0
  ordered_until& orderedUntilIndex = boost::multi_index::get<1>(data->d_entries);
56
57
0
  for (auto orderedUntilIt = orderedUntilIndex.begin(); orderedUntilIt != orderedUntilIndex.end();) {
58
0
    if (orderedUntilIt->d_until < now) {
59
0
      ComboAddress addr = orderedUntilIt->d_addr;
60
0
      orderedUntilIt = orderedUntilIndex.erase(orderedUntilIt);
61
0
      data->d_bpf->unblock(addr);
62
0
    }
63
0
    else {
64
0
      break;
65
0
    }
66
0
  }
67
0
}
68
69
std::vector<std::tuple<ComboAddress, uint64_t, struct timespec>> DynBPFFilter::getAddrStats()
70
0
{
71
0
  std::vector<std::tuple<ComboAddress, uint64_t, struct timespec>> result;
72
0
  auto data = d_data.lock();
73
74
0
  if (!data->d_bpf) {
75
0
    return result;
76
0
  }
77
78
0
  const auto& stats = data->d_bpf->getAddrStats();
79
0
  result.reserve(stats.size());
80
0
  for (const auto& stat : stats) {
81
0
    const auto entriesIt = data->d_entries.find(stat.first);
82
0
    if (entriesIt != data->d_entries.end()) {
83
0
      result.emplace_back(stat.first, stat.second, entriesIt->d_until);
84
0
    }
85
0
  }
86
0
  return result;
87
0
}