]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/test-recpacketcache_cc.cc
Merge pull request #7496 from rgacogne/auth-catch-invalid-slave-soa
[thirdparty/pdns.git] / pdns / test-recpacketcache_cc.cc
index 8d723253b0f8bebd688e16bf0313705b906cc922..5e856e1be4248a84ce5280789df96285e44aee99 100644 (file)
 #include <utility>
 
 
-BOOST_AUTO_TEST_SUITE(recpacketcache_cc)
+BOOST_AUTO_TEST_SUITE(test_recpacketcache_cc)
 
 BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple) {
   RecursorPacketCache rpc;
+  string fpacket;
+  unsigned int tag=0;
+  uint32_t age=0;
+  uint32_t qhash=0;
+  uint32_t ttd=3600;
   BOOST_CHECK_EQUAL(rpc.size(), 0);
 
   DNSName qname("www.powerdns.com");
@@ -26,27 +31,35 @@ BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple) {
   pw.getHeader()->qr=false;
   pw.getHeader()->id=random();
   string qpacket((const char*)&packet[0], packet.size());
-  pw.startRecord(qname, QType::A, 3600);
+  pw.startRecord(qname, QType::A, ttd);
+
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag, qpacket, time(nullptr), &fpacket, &age, &qhash), false);
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &qhash), false);
 
   ARecordContent ar("127.0.0.1");
   ar.toPacket(pw);
   pw.commit();
   string rpacket((const char*)&packet[0], packet.size());
 
-  rpc.insertResponsePacket(0,qname, QType::A, qpacket, rpacket, time(0), 3600);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, Indeterminate, 0, 0, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
   rpc.doPruneTo(0);
   BOOST_CHECK_EQUAL(rpc.size(), 0);
-  rpc.insertResponsePacket(0,qname, QType::A, qpacket, rpacket, time(0), 3600);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, Indeterminate, 0, 0, boost::none);
   BOOST_CHECK_EQUAL(rpc.size(), 1);
   rpc.doWipePacketCache(qname);
   BOOST_CHECK_EQUAL(rpc.size(), 0);
 
-  rpc.insertResponsePacket(0,qname, QType::A, qpacket, rpacket, time(0), 3600);
-  uint32_t age=0;
-  string fpacket;
-  bool found = rpc.getResponsePacket(0, qpacket, time(0), &fpacket, &age);
-  BOOST_CHECK_EQUAL(found, 1);
+  rpc.insertResponsePacket(tag, qhash, string(qpacket), qname, QType::A, QClass::IN, string(rpacket), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 1);
+  uint32_t qhash2 = 0;
+  bool found = rpc.getResponsePacket(tag, qpacket, time(nullptr), &fpacket, &age, &qhash2);
+  BOOST_CHECK_EQUAL(found, true);
+  BOOST_CHECK_EQUAL(qhash, qhash2);
+  BOOST_CHECK_EQUAL(fpacket, rpacket);
+  found = rpc.getResponsePacket(tag, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &qhash2);
+  BOOST_CHECK_EQUAL(found, true);
+  BOOST_CHECK_EQUAL(qhash, qhash2);
   BOOST_CHECK_EQUAL(fpacket, rpacket);
 
   packet.clear();
@@ -57,14 +70,131 @@ BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple) {
   pw2.getHeader()->qr=false;
   pw2.getHeader()->id=random();
   qpacket.assign((const char*)&packet[0], packet.size());
-  found = rpc.getResponsePacket(0, qpacket, time(0), &fpacket, &age);
-  BOOST_CHECK_EQUAL(found, 0);
+
+  found = rpc.getResponsePacket(tag, qpacket, time(nullptr), &fpacket, &age, &qhash);
+  BOOST_CHECK_EQUAL(found, false);
+  found = rpc.getResponsePacket(tag, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &qhash);
+  BOOST_CHECK_EQUAL(found, false);
 
   rpc.doWipePacketCache(DNSName("com"), 0xffff, true);
   BOOST_CHECK_EQUAL(rpc.size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags) {
+  /* Insert a response with tag1, the exact same query with a different tag
+     should lead to a miss. Inserting a different response with the second tag
+     should not override the first one, and we should get a hit for the
+     query with either tags, with the response matching the tag.
+  */
+  RecursorPacketCache rpc;
+  string fpacket;
+  const unsigned int tag1=0;
+  const unsigned int tag2=42;
+  uint32_t age=0;
+  uint32_t qhash=0;
+  uint32_t temphash=0;
+  uint32_t ttd=3600;
+  BOOST_CHECK_EQUAL(rpc.size(), 0);
+
+  DNSName qname("www.powerdns.com");
+  vector<uint8_t> packet;
+  DNSPacketWriter pw(packet, qname, QType::A);
+  pw.getHeader()->rd=true;
+  pw.getHeader()->qr=false;
+  pw.getHeader()->id=random();
+  string qpacket(reinterpret_cast<const char*>(&packet[0]), packet.size());
+  pw.startRecord(qname, QType::A, ttd);
+
+  /* Both interfaces (with and without the qname/qtype/qclass) should get the same hash */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, time(nullptr), &fpacket, &age, &qhash), false);
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), false);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+
+  /* Different tag, should still get get the same hash, for both interfaces */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag2, qpacket, time(nullptr), &fpacket, &age, &temphash), false);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag2, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), false);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+
+  {
+    ARecordContent ar("127.0.0.1");
+    ar.toPacket(pw);
+    pw.commit();
+  }
+  string r1packet(reinterpret_cast<const char*>(&packet[0]), packet.size());
+
+  {
+    ARecordContent ar("127.0.0.2");
+    ar.toPacket(pw);
+    pw.commit();
+  }
+  string r2packet(reinterpret_cast<const char*>(&packet[0]), packet.size());
+
+  BOOST_CHECK(r1packet != r2packet);
+
+  /* inserting a response for tag1 */
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 1);
+
+  /* inserting a different response for tag2, should not override the first one */
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 2);
+
+  /* remove all responses from the cache */
+  rpc.doPruneTo(0);
+  BOOST_CHECK_EQUAL(rpc.size(), 0);
+
+  /* reinsert both */
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 1);
+
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 2);
+
+  /* remove the responses by qname, should remove both */
+  rpc.doWipePacketCache(qname);
+  BOOST_CHECK_EQUAL(rpc.size(), 0);
+
+  /* insert the response for tag1 */
+  rpc.insertResponsePacket(tag1, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r1packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 1);
+
+  /* we can retrieve it */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r1packet);
+
+  /* with both interfaces */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r1packet);
+
+  /* but not with the second tag */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag2, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), false);
+  /* we should still get the same hash */
+  BOOST_CHECK_EQUAL(temphash, qhash);
+
+  /* adding a response for the second tag */
+  rpc.insertResponsePacket(tag2, qhash, string(qpacket), qname, QType::A, QClass::IN, string(r2packet), time(0), ttd, Indeterminate, 0, 0, boost::none);
+  BOOST_CHECK_EQUAL(rpc.size(), 2);
+
+  /* We still get the correct response for the first tag */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r1packet);
 
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag1, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r1packet);
 
+  /* and the correct response for the second tag */
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag2, qpacket, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r2packet);
 
-} 
+  BOOST_CHECK_EQUAL(rpc.getResponsePacket(tag2, qpacket, qname, QType::A, QClass::IN, time(nullptr), &fpacket, &age, &temphash), true);
+  BOOST_CHECK_EQUAL(qhash, temphash);
+  BOOST_CHECK_EQUAL(fpacket, r2packet);
+}
 
 BOOST_AUTO_TEST_SUITE_END()