|
@@ -38,6 +38,7 @@
|
|
|
#include <datasrc/sqlite3_datasrc.h>
|
|
|
#include <datasrc/static_datasrc.h>
|
|
|
|
|
|
+#include <testutils/dnsmessage_test.h>
|
|
|
#include <dns/tests/unittest_util.h>
|
|
|
#include <datasrc/tests/test_datasrc.h>
|
|
|
|
|
@@ -47,6 +48,7 @@ using namespace isc::dns;
|
|
|
using namespace isc::dns::rdata;
|
|
|
using namespace isc::datasrc;
|
|
|
using namespace isc::data;
|
|
|
+using namespace isc::testutils;
|
|
|
|
|
|
namespace {
|
|
|
ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
|
|
@@ -54,7 +56,9 @@ ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
|
|
|
|
|
|
class DataSrcTest : public ::testing::Test {
|
|
|
protected:
|
|
|
- DataSrcTest() : obuffer(0), renderer(obuffer), msg(Message::PARSE) {
|
|
|
+ DataSrcTest() : obuffer(0), renderer(obuffer), msg(Message::PARSE),
|
|
|
+ opcodeval(Opcode::QUERY().getCode()), qid(0)
|
|
|
+ {
|
|
|
DataSrcPtr sql3_source = DataSrcPtr(new Sqlite3DataSrc);
|
|
|
sql3_source->init(SQLITE_DBFILE_EXAMPLE);
|
|
|
DataSrcPtr test_source = DataSrcPtr(new TestDataSrc);
|
|
@@ -66,54 +70,46 @@ protected:
|
|
|
}
|
|
|
void QueryCommon(const RRClass& qclass);
|
|
|
void createAndProcessQuery(const Name& qname, const RRClass& qclass,
|
|
|
- const RRType& qtype);
|
|
|
+ const RRType& qtype, bool need_dnssec);
|
|
|
|
|
|
HotCache cache;
|
|
|
MetaDataSrc meta_source;
|
|
|
OutputBuffer obuffer;
|
|
|
MessageRenderer renderer;
|
|
|
Message msg;
|
|
|
+ const uint16_t opcodeval;
|
|
|
+ qid_t qid;
|
|
|
};
|
|
|
|
|
|
void
|
|
|
-performQuery(DataSrc& data_source, HotCache& cache, Message& message) {
|
|
|
+performQuery(DataSrc& data_source, HotCache& cache, Message& message,
|
|
|
+ bool need_dnssec = true)
|
|
|
+{
|
|
|
message.setHeaderFlag(Message::HEADERFLAG_AA);
|
|
|
message.setRcode(Rcode::NOERROR());
|
|
|
- Query q(message, cache, true);
|
|
|
+ Query q(message, cache, need_dnssec);
|
|
|
data_source.doQuery(q);
|
|
|
}
|
|
|
|
|
|
void
|
|
|
DataSrcTest::createAndProcessQuery(const Name& qname, const RRClass& qclass,
|
|
|
- const RRType& qtype)
|
|
|
+ const RRType& qtype,
|
|
|
+ bool need_dnssec = true)
|
|
|
{
|
|
|
msg.makeResponse();
|
|
|
msg.setOpcode(Opcode::QUERY());
|
|
|
msg.addQuestion(Question(qname, qclass, qtype));
|
|
|
msg.setHeaderFlag(Message::HEADERFLAG_RD);
|
|
|
- performQuery(meta_source, cache, msg);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-headerCheck(const Message& message, const Rcode& rcode, const bool qrflag,
|
|
|
- const bool aaflag, const bool rdflag, const unsigned int ancount,
|
|
|
- const unsigned int nscount, const unsigned int arcount)
|
|
|
-{
|
|
|
- EXPECT_EQ(rcode, message.getRcode());
|
|
|
- EXPECT_EQ(qrflag, message.getHeaderFlag(Message::HEADERFLAG_QR));
|
|
|
- EXPECT_EQ(aaflag, message.getHeaderFlag(Message::HEADERFLAG_AA));
|
|
|
- EXPECT_EQ(rdflag, message.getHeaderFlag(Message::HEADERFLAG_RD));
|
|
|
-
|
|
|
- EXPECT_EQ(ancount, message.getRRCount(Message::SECTION_ANSWER));
|
|
|
- EXPECT_EQ(nscount, message.getRRCount(Message::SECTION_AUTHORITY));
|
|
|
- EXPECT_EQ(arcount, message.getRRCount(Message::SECTION_ADDITIONAL));
|
|
|
+ qid = msg.getQid();
|
|
|
+ performQuery(meta_source, cache, msg, need_dnssec);
|
|
|
}
|
|
|
|
|
|
void
|
|
|
DataSrcTest::QueryCommon(const RRClass& qclass) {
|
|
|
createAndProcessQuery(Name("www.example.com"), qclass, RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -163,12 +159,8 @@ TEST_F(DataSrcTest, Query) {
|
|
|
// should be the same as "NxZone".
|
|
|
TEST_F(DataSrcTest, QueryClassMismatch) {
|
|
|
createAndProcessQuery(Name("www.example.com"), RRClass::CH(), RRType::A());
|
|
|
- headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
|
|
|
-
|
|
|
- EXPECT_EQ(Rcode::REFUSED(), msg.getRcode());
|
|
|
- EXPECT_TRUE(msg.getHeaderFlag(Message::HEADERFLAG_QR));
|
|
|
- EXPECT_FALSE(msg.getHeaderFlag(Message::HEADERFLAG_AA));
|
|
|
- EXPECT_TRUE(msg.getHeaderFlag(Message::HEADERFLAG_RD));
|
|
|
+ headerCheck(msg, qid, Rcode::REFUSED(), opcodeval, QR_FLAG | RD_FLAG,
|
|
|
+ 1, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
// Query class of any should match the first data source.
|
|
@@ -176,10 +168,64 @@ TEST_F(DataSrcTest, QueryClassAny) {
|
|
|
QueryCommon(RRClass::ANY());
|
|
|
}
|
|
|
|
|
|
+TEST_F(DataSrcTest, queryClassAnyNegative) {
|
|
|
+ // There was a bug where Class ANY query triggered a crash due to NULL
|
|
|
+ // pointer dereference. This test checks that condition.
|
|
|
+
|
|
|
+ // NXDOMAIN case
|
|
|
+ createAndProcessQuery(Name("notexistent.example.com"), RRClass::ANY(),
|
|
|
+ RRType::A());
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 6, 0);
|
|
|
+
|
|
|
+ // NXRRSET case
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+ createAndProcessQuery(Name("www.example.com"), RRClass::ANY(),
|
|
|
+ RRType::TXT());
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 4, 0);
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(DataSrcTest, queryClassAnyDNAME) {
|
|
|
+ // Class ANY query that would match a DNAME. Everything including the
|
|
|
+ // synthesized CNAME should be the same as the response to class IN query.
|
|
|
+ createAndProcessQuery(Name("www.dname.example.com"), RRClass::ANY(),
|
|
|
+ RRType::A(), false);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 3, 3, 3);
|
|
|
+ rrsetsCheck("dname.example.com. 3600 IN DNAME sql1.example.com.\n"
|
|
|
+ "www.dname.example.com. 3600 IN CNAME www.sql1.example.com.\n"
|
|
|
+ "www.sql1.example.com. 3600 IN A 192.0.2.2\n",
|
|
|
+ msg.beginSection(Message::SECTION_ANSWER),
|
|
|
+ msg.endSection(Message::SECTION_ANSWER));
|
|
|
+
|
|
|
+ // Also check the case of explicit DNAME query.
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+ createAndProcessQuery(Name("dname.example.com"), RRClass::ANY(),
|
|
|
+ RRType::DNAME(), false);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 1, 3, 3);
|
|
|
+ rrsetsCheck("dname.example.com. 3600 IN DNAME sql1.example.com.\n",
|
|
|
+ msg.beginSection(Message::SECTION_ANSWER),
|
|
|
+ msg.endSection(Message::SECTION_ANSWER));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(DataSrcTest, queryClassAnyCNAME) {
|
|
|
+ // Similar test for CNAME
|
|
|
+ createAndProcessQuery(Name("foo.example.com"), RRClass::ANY(),
|
|
|
+ RRType::A(), false);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 1, 0, 0);
|
|
|
+ rrsetsCheck("foo.example.com. 3600 IN CNAME cnametest.example.net.\n",
|
|
|
+ msg.beginSection(Message::SECTION_ANSWER),
|
|
|
+ msg.endSection(Message::SECTION_ANSWER));
|
|
|
+}
|
|
|
+
|
|
|
TEST_F(DataSrcTest, NSQuery) {
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::NS());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 0, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -201,7 +247,8 @@ TEST_F(DataSrcTest, NSQuery) {
|
|
|
TEST_F(DataSrcTest, DuplicateQuery) {
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::NS());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 0, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -221,7 +268,8 @@ TEST_F(DataSrcTest, DuplicateQuery) {
|
|
|
msg.clear(Message::PARSE);
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::NS());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 0, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 0, 6);
|
|
|
|
|
|
rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
rrset = *rit;
|
|
@@ -242,7 +290,8 @@ TEST_F(DataSrcTest, DuplicateQuery) {
|
|
|
TEST_F(DataSrcTest, DNSKEYQuery) {
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::DNSKEY());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -257,7 +306,8 @@ TEST_F(DataSrcTest, DNSKEYQuery) {
|
|
|
TEST_F(DataSrcTest, DNSKEYDuplicateQuery) {
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::DNSKEY());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -279,7 +329,8 @@ TEST_F(DataSrcTest, NxRRset) {
|
|
|
createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
RRType::PTR());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 4, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 4, 0);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -291,7 +342,8 @@ TEST_F(DataSrcTest, Nxdomain) {
|
|
|
createAndProcessQuery(Name("glork.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 6, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 6, 0);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -301,11 +353,46 @@ TEST_F(DataSrcTest, Nxdomain) {
|
|
|
// XXX: check for other authority section answers
|
|
|
}
|
|
|
|
|
|
+TEST_F(DataSrcTest, NxdomainAfterSOAQuery) {
|
|
|
+ // There was a bug where once SOA RR is stored in the hot spot cache
|
|
|
+ // subsequent negative search fails due to "missing SOA". This test
|
|
|
+ // checks that situation.
|
|
|
+
|
|
|
+ // First, run the scenario with disabling the cache.
|
|
|
+ cache.setEnabled(false);
|
|
|
+ createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
+ RRType::SOA());
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+ createAndProcessQuery(Name("notexistent.example.com"), RRClass::IN(),
|
|
|
+ RRType::A());
|
|
|
+ {
|
|
|
+ SCOPED_TRACE("NXDOMAIN after SOA, without hot spot cache");
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 6, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Then enable the cache and perform the same queries. This should
|
|
|
+ // produce the same result.
|
|
|
+ cache.setEnabled(true);
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+ createAndProcessQuery(Name("example.com"), RRClass::IN(),
|
|
|
+ RRType::SOA());
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+ createAndProcessQuery(Name("notexistent.example.com"), RRClass::IN(),
|
|
|
+ RRType::A());
|
|
|
+ {
|
|
|
+ SCOPED_TRACE("NXDOMAIN after SOA, without hot spot cache");
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 6, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
TEST_F(DataSrcTest, NxZone) {
|
|
|
createAndProcessQuery(Name("spork.example"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::REFUSED(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 0, 0);
|
|
|
|
|
|
EXPECT_EQ(Rcode::REFUSED(), msg.getRcode());
|
|
|
EXPECT_TRUE(msg.getHeaderFlag(Message::HEADERFLAG_QR));
|
|
@@ -317,7 +404,8 @@ TEST_F(DataSrcTest, Wildcard) {
|
|
|
createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 6, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -369,7 +457,8 @@ TEST_F(DataSrcTest, WildcardNodata) {
|
|
|
// returns NOERROR
|
|
|
createAndProcessQuery(Name("www.wild.example.com"), RRClass::IN(),
|
|
|
RRType::AAAA());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 2, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 2, 0);
|
|
|
}
|
|
|
|
|
|
TEST_F(DataSrcTest, DISABLED_WildcardAgainstMultiLabel) {
|
|
@@ -377,72 +466,42 @@ TEST_F(DataSrcTest, DISABLED_WildcardAgainstMultiLabel) {
|
|
|
// a single label), and it should result in NXDOMAIN.
|
|
|
createAndProcessQuery(Name("www.xxx.wild.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
- headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 1, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 1, 0);
|
|
|
}
|
|
|
|
|
|
TEST_F(DataSrcTest, WildcardCname) {
|
|
|
// Check that wildcard answers containing CNAMES are followed
|
|
|
- // correctly
|
|
|
- createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
|
|
|
- RRType::A());
|
|
|
-
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 6, 6);
|
|
|
-
|
|
|
- RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
- RRsetPtr rrset = *rit;
|
|
|
- EXPECT_EQ(Name("www.wild2.example.com"), rrset->getName());
|
|
|
- EXPECT_EQ(RRType::CNAME(), rrset->getType());
|
|
|
- EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
-
|
|
|
- RdataIteratorPtr it = rrset->getRdataIterator();
|
|
|
- EXPECT_EQ("www.example.com.", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_TRUE(it->isLast());
|
|
|
-
|
|
|
- ++rit;
|
|
|
- ++rit;
|
|
|
- rrset = *rit;
|
|
|
- EXPECT_EQ(Name("www.example.com"), rrset->getName());
|
|
|
- EXPECT_EQ(RRType::A(), rrset->getType());
|
|
|
- EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
-
|
|
|
- it = rrset->getRdataIterator();
|
|
|
- EXPECT_EQ("192.0.2.1", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_TRUE(it->isLast());
|
|
|
-
|
|
|
- rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
- rrset = *rit;
|
|
|
- EXPECT_EQ(Name("*.wild2.example.com"), rrset->getName());
|
|
|
- EXPECT_EQ(RRType::NSEC(), rrset->getType());
|
|
|
- EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
- ++rit;
|
|
|
- ++rit;
|
|
|
-
|
|
|
- rrset = *rit;
|
|
|
- EXPECT_EQ(Name("example.com"), rrset->getName());
|
|
|
- EXPECT_EQ(RRType::NS(), rrset->getType());
|
|
|
- EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
-
|
|
|
- it = rrset->getRdataIterator();
|
|
|
- EXPECT_EQ("dns01.example.com.", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_EQ("dns02.example.com.", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_EQ("dns03.example.com.", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_TRUE(it->isLast());
|
|
|
-
|
|
|
- rit = msg.beginSection(Message::SECTION_ADDITIONAL);
|
|
|
- rrset = *rit;
|
|
|
- EXPECT_EQ(Name("dns01.example.com"), rrset->getName());
|
|
|
- EXPECT_EQ(RRType::A(), rrset->getType());
|
|
|
- EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
-
|
|
|
- it = rrset->getRdataIterator();
|
|
|
- EXPECT_EQ("192.0.2.1", it->getCurrent().toText());
|
|
|
- it->next();
|
|
|
- EXPECT_TRUE(it->isLast());
|
|
|
+ // correctly. It should result in the same response for both
|
|
|
+ // class IN and ANY queries.
|
|
|
+ const RRClass classes[2] = { RRClass::IN(), RRClass::ANY() };
|
|
|
+
|
|
|
+ for (int i = 0; i < sizeof(classes) / sizeof(classes[0]); ++i) {
|
|
|
+ SCOPED_TRACE("Wildcard + CNAME test for class " + classes[i].toText());
|
|
|
+
|
|
|
+ msg.clear(Message::PARSE);
|
|
|
+
|
|
|
+ createAndProcessQuery(Name("www.wild2.example.com"), classes[i],
|
|
|
+ RRType::A(), false);
|
|
|
+
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 3, 3);
|
|
|
+
|
|
|
+ rrsetsCheck("www.wild2.example.com. 3600 IN CNAME www.example.com\n"
|
|
|
+ "www.example.com. 3600 IN A 192.0.2.1\n",
|
|
|
+ msg.beginSection(Message::SECTION_ANSWER),
|
|
|
+ msg.endSection(Message::SECTION_ANSWER));
|
|
|
+ rrsetsCheck("example.com. 3600 IN NS dns01.example.com.\n"
|
|
|
+ "example.com. 3600 IN NS dns02.example.com.\n"
|
|
|
+ "example.com. 3600 IN NS dns03.example.com.",
|
|
|
+ msg.beginSection(Message::SECTION_AUTHORITY),
|
|
|
+ msg.endSection(Message::SECTION_AUTHORITY));
|
|
|
+ rrsetsCheck("dns01.example.com. 3600 IN A 192.0.2.1\n"
|
|
|
+ "dns02.example.com. 3600 IN A 192.0.2.2\n"
|
|
|
+ "dns03.example.com. 3600 IN A 192.0.2.3",
|
|
|
+ msg.beginSection(Message::SECTION_ADDITIONAL),
|
|
|
+ msg.endSection(Message::SECTION_ADDITIONAL));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
TEST_F(DataSrcTest, WildcardCnameNodata) {
|
|
@@ -450,7 +509,8 @@ TEST_F(DataSrcTest, WildcardCnameNodata) {
|
|
|
// data of this type.
|
|
|
createAndProcessQuery(Name("www.wild2.example.com"), RRClass::IN(),
|
|
|
RRType::AAAA());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 4, 0);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -481,7 +541,8 @@ TEST_F(DataSrcTest, WildcardCnameNxdomain) {
|
|
|
// A wildcard containing a CNAME whose target does not exist
|
|
|
createAndProcessQuery(Name("www.wild3.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 6, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 6, 0);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -518,7 +579,8 @@ TEST_F(DataSrcTest, AuthDelegation) {
|
|
|
createAndProcessQuery(Name("www.sql1.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -562,7 +624,8 @@ TEST_F(DataSrcTest, Dname) {
|
|
|
createAndProcessQuery(Name("www.dname.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 5, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 5, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -610,14 +673,16 @@ TEST_F(DataSrcTest, DnameExact) {
|
|
|
// confuse delegation processing.
|
|
|
createAndProcessQuery(Name("dname2.foo.example.org"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 1, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 1, 0);
|
|
|
}
|
|
|
|
|
|
TEST_F(DataSrcTest, Cname) {
|
|
|
createAndProcessQuery(Name("foo.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 0, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 0, 0);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -626,7 +691,7 @@ TEST_F(DataSrcTest, Cname) {
|
|
|
EXPECT_EQ(RRClass::IN(), rrset->getClass());
|
|
|
|
|
|
RdataIteratorPtr it = rrset->getRdataIterator();
|
|
|
- EXPECT_EQ("cnametest.flame.org.", it->getCurrent().toText());
|
|
|
+ EXPECT_EQ("cnametest.example.net.", it->getCurrent().toText());
|
|
|
it->next();
|
|
|
EXPECT_TRUE(it->isLast());
|
|
|
}
|
|
@@ -635,7 +700,8 @@ TEST_F(DataSrcTest, CnameInt) {
|
|
|
createAndProcessQuery(Name("cname-int.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -661,7 +727,8 @@ TEST_F(DataSrcTest, CnameExt) {
|
|
|
createAndProcessQuery(Name("cname-ext.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 4, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 4, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -685,7 +752,8 @@ TEST_F(DataSrcTest, Delegation) {
|
|
|
createAndProcessQuery(Name("www.subzone.example.com"), RRClass::IN(),
|
|
|
RRType::A());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 5, 2);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -714,7 +782,8 @@ TEST_F(DataSrcTest, NSDelegation) {
|
|
|
createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
|
|
|
RRType::NS());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 5, 2);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -750,7 +819,8 @@ TEST_F(DataSrcTest, NSECZonecut) {
|
|
|
createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
|
|
|
RRType::NSEC());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 2, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 2, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -778,7 +848,8 @@ TEST_F(DataSrcTest, DNAMEZonecut) {
|
|
|
createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
|
|
|
RRType::DNAME());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 5, 2);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 5, 2);
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
|
EXPECT_EQ(Name("subzone.example.com."), rrset->getName());
|
|
@@ -806,7 +877,8 @@ TEST_F(DataSrcTest, DS) {
|
|
|
createAndProcessQuery(Name("subzone.example.com"), RRClass::IN(),
|
|
|
RRType::DS());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 3, 4, 6);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 3, 4, 6);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_ANSWER);
|
|
|
RRsetPtr rrset = *rit;
|
|
@@ -847,7 +919,8 @@ TEST_F(DataSrcTest, NSECZonecutOfNonsecureZone) {
|
|
|
createAndProcessQuery(Name("sub.example.org"), RRClass::IN(),
|
|
|
RRType::NSEC());
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, false, true, 0, 1, 1);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 1, 1);
|
|
|
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
ConstRRsetPtr rrset = *rit;
|
|
@@ -879,7 +952,8 @@ TEST_F(DataSrcTest, NSECZonecutOfNonsecureZone) {
|
|
|
TEST_F(DataSrcTest, RootDSQuery1) {
|
|
|
EXPECT_NO_THROW(createAndProcessQuery(Name("."), RRClass::IN(),
|
|
|
RRType::DS()));
|
|
|
- headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::REFUSED(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
// The same, but when we have the root zone
|
|
@@ -898,7 +972,8 @@ TEST_F(DataSrcTest, RootDSQuery2) {
|
|
|
// Make the query
|
|
|
EXPECT_NO_THROW(performQuery(*sql3_source, cache, msg));
|
|
|
|
|
|
- headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 1, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 1, 0);
|
|
|
}
|
|
|
|
|
|
TEST_F(DataSrcTest, DSQueryFromCache) {
|
|
@@ -916,7 +991,8 @@ TEST_F(DataSrcTest, DSQueryFromCache) {
|
|
|
|
|
|
// returning refused is probably a bad behavior, but it's a different
|
|
|
// issue -- see Trac Ticket #306.
|
|
|
- headerCheck(msg, Rcode::REFUSED(), true, false, true, 0, 0, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::REFUSED(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
// Non-existent name in the "static" data source. The purpose of this test
|
|
@@ -925,7 +1001,8 @@ TEST_F(DataSrcTest, DSQueryFromCache) {
|
|
|
TEST_F(DataSrcTest, StaticNxDomain) {
|
|
|
createAndProcessQuery(Name("www.version.bind"), RRClass::CH(),
|
|
|
RRType::TXT());
|
|
|
- headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 1, 0);
|
|
|
+ headerCheck(msg, qid, Rcode::NXDOMAIN(), opcodeval,
|
|
|
+ QR_FLAG | AA_FLAG | RD_FLAG, 1, 0, 1, 0);
|
|
|
RRsetIterator rit = msg.beginSection(Message::SECTION_AUTHORITY);
|
|
|
RRsetPtr rrset = *rit;
|
|
|
EXPECT_EQ(Name("version.bind"), rrset->getName());
|
|
@@ -973,6 +1050,34 @@ TEST_F(DataSrcTest, noSOAZone) {
|
|
|
DataSourceError);
|
|
|
}
|
|
|
|
|
|
+TEST_F(DataSrcTest, apexCNAMEZone) {
|
|
|
+ // The query name doesn't exist in the best matching zone,
|
|
|
+ // and there's a CNAME at the apex (which is bogus), so query handling
|
|
|
+ // will fail due to missing SOA.
|
|
|
+ EXPECT_THROW(createAndProcessQuery(Name("notexist.apexcname.example"),
|
|
|
+ RRClass::IN(), RRType::A()),
|
|
|
+ DataSourceError);
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(DataSrcTest, incompleteGlue) {
|
|
|
+ // One of the NS names belong to a different zone (which is still
|
|
|
+ // authoritative), and the glue is missing in that zone. We should
|
|
|
+ // still return the existent glue.
|
|
|
+ // (nons.example is also broken in that it doesn't have apex NS, but
|
|
|
+ // that doesn't matter for this test)
|
|
|
+ createAndProcessQuery(Name("www.incompletechild.nons.example"),
|
|
|
+ RRClass::IN(), RRType::A());
|
|
|
+ headerCheck(msg, qid, Rcode::NOERROR(), opcodeval,
|
|
|
+ QR_FLAG | RD_FLAG, 1, 0, 2, 1);
|
|
|
+ rrsetsCheck("incompletechild.nons.example. 3600 IN NS ns.incompletechild.nons.example.\n"
|
|
|
+ "incompletechild.nons.example. 3600 IN NS nx.nosoa.example.",
|
|
|
+ msg.beginSection(Message::SECTION_AUTHORITY),
|
|
|
+ msg.endSection(Message::SECTION_AUTHORITY));
|
|
|
+ rrsetsCheck("ns.incompletechild.nons.example. 3600 IN A 192.0.2.1",
|
|
|
+ msg.beginSection(Message::SECTION_ADDITIONAL),
|
|
|
+ msg.endSection(Message::SECTION_ADDITIONAL));
|
|
|
+}
|
|
|
+
|
|
|
// currently fails
|
|
|
TEST_F(DataSrcTest, DISABLED_synthesizedCnameTooLong) {
|
|
|
// qname has the possible max length (255 octets). it matches a DNAME,
|