]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix a bug not always displaying the first eBPF entry of a map
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 18 May 2026 10:30:00 +0000 (12:30 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 18 May 2026 10:30:00 +0000 (12:30 +0200)
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
pdns/dnsdistdist/bpf-filter.cc
regression-tests.dnsdist/test_EBPF.py

index 71a5be74525e274e68fd2b5cae2b53f7c5e2ff78..e93d0ce30fa40d048a7021055eee41e05ec817de 100644 (file)
@@ -733,7 +733,7 @@ void BPFFilter::block(const DNSName& qname, BPFFilter::MatchAction action, uint1
 
 void BPFFilter::unblock(const DNSName& qname, uint16_t qtype)
 {
-  QNameAndQTypeKey key;
+  QNameAndQTypeKey key{};
   memset(&key, 0, sizeof(key));
   std::string keyStr = qname.toDNSStringLC();
 
@@ -785,7 +785,7 @@ std::vector<std::pair<ComboAddress, uint64_t>> BPFFilter::getAddrStats()
 
   {
     auto& map = maps->d_v4;
-    int res = bpf_get_next_key(map.d_fd.getHandle(), &v4Key, &nextV4Key);
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, &nextV4Key);
 
     while (res == 0) {
       v4Key = nextV4Key;
@@ -800,7 +800,7 @@ std::vector<std::pair<ComboAddress, uint64_t>> BPFFilter::getAddrStats()
 
   {
     auto& map = maps->d_v6;
-    int res = bpf_get_next_key(map.d_fd.getHandle(), v6Key.data(), nextV6Key.data());
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, nextV6Key.data());
 
     while (res == 0) {
       if (bpf_lookup_elem(map.d_fd.getHandle(), nextV6Key.data(), &value) == 0) {
@@ -818,16 +818,16 @@ std::vector<std::pair<ComboAddress, uint64_t>> BPFFilter::getAddrStats()
 
 std::vector<std::pair<Netmask, CounterAndActionValue>> BPFFilter::getRangeRule()
 {
-  CIDR4 cidr4[2];
-  CIDR6 cidr6[2];
+  CIDR4 cidr4{};
+  CIDR6 cidr6{};
   std::vector<std::pair<Netmask, CounterAndActionValue>> result;
 
-  sockaddr_in v4Addr;
-  sockaddr_in6 v6Addr;
+  sockaddr_in v4Addr{};
+  sockaddr_in6 v6Addr{};
   CounterAndActionValue value;
 
-  memset(cidr4, 0, sizeof(cidr4));
-  memset(cidr6, 0, sizeof(cidr6));
+  memset(&cidr4, 0, sizeof(cidr4));
+  memset(&cidr6, 0, sizeof(cidr6));
   memset(&v4Addr, 0, sizeof(v4Addr));
   memset(&v6Addr, 0, sizeof(v6Addr));
   v4Addr.sin_family = AF_INET;
@@ -836,27 +836,27 @@ std::vector<std::pair<Netmask, CounterAndActionValue>> BPFFilter::getRangeRule()
   result.reserve(maps->d_cidr4.d_count + maps->d_cidr6.d_count);
   {
     auto& map = maps->d_cidr4;
-    int res = bpf_get_next_key(map.d_fd.getHandle(), &cidr4[0], &cidr4[1]);
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, &cidr4);
     while (res == 0) {
-      if (bpf_lookup_elem(map.d_fd.getHandle(), &cidr4[1], &value) == 0) {
-        v4Addr.sin_addr.s_addr = cidr4[1].addr.s_addr;
-        result.emplace_back(Netmask(&v4Addr, cidr4[1].cidr), value);
+      if (bpf_lookup_elem(map.d_fd.getHandle(), &cidr4, &value) == 0) {
+        v4Addr.sin_addr.s_addr = cidr4.addr.s_addr;
+        result.emplace_back(Netmask(&v4Addr, cidr4.cidr), value);
       }
 
-      res = bpf_get_next_key(map.d_fd.getHandle(), &cidr4[1], &cidr4[1]);
+      res = bpf_get_next_key(map.d_fd.getHandle(), &cidr4, &cidr4);
     }
   }
 
   {
     auto& map = maps->d_cidr6;
-    int res = bpf_get_next_key(map.d_fd.getHandle(), &cidr6[0], &cidr6[1]);
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, &cidr6);
     while (res == 0) {
-      if (bpf_lookup_elem(map.d_fd.getHandle(), &cidr6[1], &value) == 0) {
-        v6Addr.sin6_addr = cidr6[1].addr;
-        result.emplace_back(Netmask(&v6Addr, cidr6[1].cidr), value);
+      if (bpf_lookup_elem(map.d_fd.getHandle(), &cidr6, &value) == 0) {
+        v6Addr.sin6_addr = cidr6.addr;
+        result.emplace_back(Netmask(&v6Addr, cidr6.cidr), value);
       }
 
-      res = bpf_get_next_key(map.d_fd.getHandle(), &cidr6[1], &cidr6[1]);
+      res = bpf_get_next_key(map.d_fd.getHandle(), &cidr6, &cidr6);
     }
   }
   return result;
@@ -867,18 +867,18 @@ std::vector<std::tuple<DNSName, uint16_t, uint64_t>> BPFFilter::getQNameStats()
   std::vector<std::tuple<DNSName, uint16_t, uint64_t>> result;
 
   if (d_mapFormat == MapFormat::Legacy) {
-    QNameKey key = {{0}};
     QNameKey nextKey = {{0}};
     QNameValue value;
 
     auto maps = d_maps.lock();
     auto& map = maps->d_qnames;
     result.reserve(map.d_count);
-    int res = bpf_get_next_key(map.d_fd.getHandle(), &key, &nextKey);
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, &nextKey);
 
     while (res == 0) {
       if (bpf_lookup_elem(map.d_fd.getHandle(), &nextKey, &value) == 0) {
         nextKey.qname[sizeof(nextKey.qname) - 1] = '\0';
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
         result.emplace_back(DNSName(reinterpret_cast<const char*>(nextKey.qname), sizeof(nextKey.qname), 0, false), value.qtype, value.counter);
       }
 
@@ -886,21 +886,20 @@ std::vector<std::tuple<DNSName, uint16_t, uint64_t>> BPFFilter::getQNameStats()
     }
   }
   else {
-    QNameAndQTypeKey key;
-    QNameAndQTypeKey nextKey;
-    memset(&key, 0, sizeof(key));
+    QNameAndQTypeKey nextKey{};
     memset(&nextKey, 0, sizeof(nextKey));
     CounterAndActionValue value;
 
     auto maps = d_maps.lock();
     auto& map = maps->d_qnames;
     result.reserve(map.d_count);
-    int res = bpf_get_next_key(map.d_fd.getHandle(), &key, &nextKey);
+    int res = bpf_get_next_key(map.d_fd.getHandle(), nullptr, &nextKey);
 
     while (res == 0) {
       if (bpf_lookup_elem(map.d_fd.getHandle(), &nextKey, &value) == 0) {
         nextKey.qname[sizeof(nextKey.qname) - 1] = '\0';
-        result.emplace_back(DNSName(reinterpret_cast<const char*>(nextKey.qname), sizeof(nextKey.qname), 0, false), key.qtype, value.counter);
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+        result.emplace_back(DNSName(reinterpret_cast<const char*>(nextKey.qname), sizeof(nextKey.qname), 0, false), nextKey.qtype, value.counter);
       }
 
       res = bpf_get_next_key(map.d_fd.getHandle(), &nextKey, &nextKey);
index c4c6403239ed71762ae1c7f56823bf06bcb4089e..f5b4e4394d4d1b53018fc8c8267748e7b0fe3557 100644 (file)
@@ -145,6 +145,8 @@ class TestSimpleEBPF(DNSDistTest):
     def testClientIPBlocked(self):
         # block 127.0.0.1
         self.sendConsoleCommand('bpf:block(newCA("127.0.0.1"))')
+        stats = self.sendConsoleCommand('bpf:getStats()')
+        self.assertIn('127.0.0.1: 0', stats)
 
         name = "ip-blocked.ebpf.tests.powerdns.com."
         query = dns.message.make_query(name, "A", "IN", use_edns=False)
@@ -175,7 +177,14 @@ class TestSimpleEBPF(DNSDistTest):
 
         # unblock 127.0.0.1
         self.sendConsoleCommand('bpf:unblock(newCA("127.0.0.1"))')
-
+        stats = self.sendConsoleCommand('bpf:getStats()')
+        self.assertNotIn('127.0.0.1: 0', stats)
+
+        # block 0.0.0.0
+        self.sendConsoleCommand('bpf:block(newCA("0.0.0.0"))')
+        stats = self.sendConsoleCommand('bpf:getStats()')
+        print(stats)
+        self.assertIn('0.0.0.0: 0', stats)
 
 @unittest.skipUnless("ENABLE_SUDO_TESTS" in os.environ, "sudo is not available")
 class TestEBPFRange(DNSDistTest):