|
@@ -16,6 +16,7 @@
|
|
|
|
|
|
#include <d2/d2_update_message.h>
|
|
|
#include <dns/messagerenderer.h>
|
|
|
+#include <dns/rdataclass.h>
|
|
|
#include <dns/rdata.h>
|
|
|
#include <dns/rrttl.h>
|
|
|
|
|
@@ -74,6 +75,128 @@ public:
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// This test verifies that the DNS message is properly decoded from the
|
|
|
+// wire format.
|
|
|
+TEST_F(D2UpdateMessageTest, fromWire) {
|
|
|
+ // The following table holds the DNS response in on-wire format.
|
|
|
+ // This message comprises the following sections:
|
|
|
+ // - HEADER
|
|
|
+ // - PREREQUISITE section with one RR
|
|
|
+ // - UPDATE section with 1 RR.
|
|
|
+ // Such a response may be generated by the DNS server as a result
|
|
|
+ // of copying the contents of the REQUEST message sent by DDNS client.
|
|
|
+ const uint8_t bin_msg[] = {
|
|
|
+ // HEADER section starts here (see RFC 2136, section 2).
|
|
|
+ 0x05, 0xAF, // ID=0x05AF
|
|
|
+ 0xA8, 0x6, // QR=1, Opcode=6, RCODE=YXDOMAIN
|
|
|
+ 0x0, 0x1, // ZOCOUNT=1
|
|
|
+ 0x0, 0x2, // PRCOUNT=2
|
|
|
+ 0x0, 0x1, // UPCOUNT=1
|
|
|
+ 0x0, 0x0, // ADCOUNT=0
|
|
|
+
|
|
|
+ // Zone section starts here. The The first field comprises
|
|
|
+ // the Zone name encoded as a set of labels, each preceded
|
|
|
+ // by a length of the following label. The whole Zone name is
|
|
|
+ // terminated with a NULL char.
|
|
|
+ // For Zone section format see (RFC 2136, section 2.3).
|
|
|
+ 0x7, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example (0x7 is a length)
|
|
|
+ 0x3, 0x63, 0x6F, 0x6D, //.com. (0x3 is a length)
|
|
|
+ 0x0, // NULL character terminates the Zone name.
|
|
|
+ 0x0, 0x6, // ZTYPE='SOA'
|
|
|
+ 0x0, 0x1, // ZCLASS='IN'
|
|
|
+
|
|
|
+ // Prerequisite section starts here. This section comprises two
|
|
|
+ // prerequisites:
|
|
|
+ // - 'Name is not in use'
|
|
|
+ // - 'Name is in use'
|
|
|
+ // See RFC 2136, section 2.4 for the format of Prerequisite section.
|
|
|
+ // Each prerequisite RR starts with its name. It is expressed in the
|
|
|
+ // compressed format as described in RFC 1035, section 4.1.4. The first
|
|
|
+ // label is expressed as in case of non-compressed name. It is preceded
|
|
|
+ // by the length value. The following two bytes are the pointer to the
|
|
|
+ // offset in the message where 'example.com' was used. That is, in the
|
|
|
+ // Zone name at offset 12. Pointer starts with two bits set - they
|
|
|
+ // mark start of the pointer.
|
|
|
+
|
|
|
+ // First prerequisite. NONE class indicates that the update requires
|
|
|
+ // that the name 'foo.example.com' is not use/
|
|
|
+ 0x03, 0x66, 0x6F, 0x6F, // foo.
|
|
|
+ 0xC0, 0x0C, // pointer to example.com.
|
|
|
+ 0x0, 0x1C, // TYPE=AAAA
|
|
|
+ 0x0, 0xFE, // CLASS=NONE
|
|
|
+ 0x0, 0x0, 0x0, 0x0, // TTL=0
|
|
|
+ 0x0, 0x0, // RDLENGTH=0
|
|
|
+
|
|
|
+ // Second prerequisite. ANY class indicates tha the update requires
|
|
|
+ // that the name 'bar.example.com' exists.
|
|
|
+ 0x03, 0x62, 0x61, 0x72, // bar.
|
|
|
+ 0xC0, 0x0C, // pointer to example.com.
|
|
|
+ 0x0, 0x1C, // TYPE=AAAA
|
|
|
+ 0x0, 0xFF, // CLASS=ANY
|
|
|
+ 0x0, 0x0, 0x0, 0x0, // TTL=0
|
|
|
+ 0x0, 0x0, // RDLENGTH=0
|
|
|
+
|
|
|
+ // Update section starts here. The format of this section conforms to
|
|
|
+ // RFC 2136, section 2.5. The name of the RR is again expressed in
|
|
|
+ // compressed format. The two pointer bytes point to the offset in the
|
|
|
+ // message where 'foo.example.com' was used already - 29.
|
|
|
+ 0xC0, 0x1D, // pointer to foo.example.com.
|
|
|
+ 0x0, 0x1C, // TYPE=AAAA
|
|
|
+ 0x0, 0x1, // CLASS=IN
|
|
|
+ 0xAA, 0xBB, 0xCC, 0xDD, // TTL=0xAABBCCDD
|
|
|
+ 0x0, 0x10, // RDLENGTH=16
|
|
|
+ // The following 16 bytes of RDATA hold IPv6 address: 2001:db8:1::1.
|
|
|
+ 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x01, 0x00, 0x00,
|
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
|
|
+ };
|
|
|
+ InputBuffer buf(bin_msg, sizeof(bin_msg));
|
|
|
+
|
|
|
+ D2UpdateMessage msg(true);
|
|
|
+
|
|
|
+ ASSERT_NO_THROW(msg.fromWire(buf));
|
|
|
+
|
|
|
+ EXPECT_EQ(0x05AF, msg.getQid());
|
|
|
+ EXPECT_EQ(D2UpdateMessage::RESPONSE, msg.getQRFlag());
|
|
|
+ EXPECT_EQ(Rcode::YXDOMAIN_CODE, msg.getRcode().getCode());
|
|
|
+ ASSERT_EQ(1, msg.getRRCount(D2UpdateMessage::SECTION_ZONE));
|
|
|
+ // Zone section is TBD
|
|
|
+
|
|
|
+ ASSERT_EQ(2, msg.getRRCount(D2UpdateMessage::SECTION_PREREQUISITE));
|
|
|
+ RRsetIterator rrset_it = msg.beginSection(D2UpdateMessage::SECTION_PREREQUISITE);
|
|
|
+ RRsetPtr prereq1 = *rrset_it;
|
|
|
+ ASSERT_TRUE(prereq1);
|
|
|
+ EXPECT_EQ("foo.example.com.", prereq1->getName().toText());
|
|
|
+ EXPECT_EQ(RRType::AAAA().getCode(), prereq1->getType().getCode());
|
|
|
+ EXPECT_EQ(RRClass::NONE().getCode(), prereq1->getClass().getCode());
|
|
|
+ EXPECT_EQ(0, prereq1->getTTL().getValue());
|
|
|
+ EXPECT_EQ(0, prereq1->getRdataCount());
|
|
|
+
|
|
|
+ // Move to next prerequisite section.
|
|
|
+ ++rrset_it;
|
|
|
+
|
|
|
+ RRsetPtr prereq2 = *rrset_it;
|
|
|
+ ASSERT_TRUE(prereq2);
|
|
|
+ EXPECT_EQ("bar.example.com.", prereq2->getName().toText());
|
|
|
+ EXPECT_EQ(RRType::AAAA().getCode(), prereq2->getType().getCode());
|
|
|
+ EXPECT_EQ(RRClass::ANY().getCode(), prereq2->getClass().getCode());
|
|
|
+ EXPECT_EQ(0, prereq2->getTTL().getValue());
|
|
|
+ EXPECT_EQ(0, prereq2->getRdataCount());
|
|
|
+
|
|
|
+ ASSERT_EQ(1, msg.getRRCount(D2UpdateMessage::SECTION_UPDATE));
|
|
|
+ rrset_it = msg.beginSection(D2UpdateMessage::SECTION_UPDATE);
|
|
|
+ RRsetPtr update = *rrset_it;
|
|
|
+ ASSERT_TRUE(update);
|
|
|
+ EXPECT_EQ("foo.example.com.", update->getName().toText());
|
|
|
+ EXPECT_EQ(RRType::AAAA().getCode(), update->getType().getCode());
|
|
|
+ EXPECT_EQ(RRClass::IN().getCode(), update->getClass().getCode());
|
|
|
+ EXPECT_EQ(0xAABBCCDD, update->getTTL().getValue());
|
|
|
+ ASSERT_EQ(1, update->getRdataCount());
|
|
|
+ RdataIteratorPtr rdata_it = update->getRdataIterator();
|
|
|
+ ASSERT_TRUE(rdata_it);
|
|
|
+ in::AAAA rdata_ref("2001:db8:1::1");
|
|
|
+ EXPECT_EQ(0, rdata_ref.compare(rdata_it->getCurrent()));
|
|
|
+}
|
|
|
+
|
|
|
// This test verifies that the wire format of the message is produced
|
|
|
// in the render mode.
|
|
|
TEST_F(D2UpdateMessageTest, toWire) {
|