d2_update_message_unittests.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <d2/d2_update_message.h>
  16. #include <d2/d2_zone.h>
  17. #include <dns/messagerenderer.h>
  18. #include <dns/rdataclass.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rrttl.h>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <gtest/gtest.h>
  23. using namespace std;
  24. using namespace isc;
  25. using namespace isc::d2;
  26. using namespace isc::dns;
  27. using namespace isc::dns::rdata;
  28. using namespace isc::util;
  29. namespace {
  30. // @brief Test fixture class for testing D2UpdateMessage object.
  31. class D2UpdateMessageTest : public ::testing::Test {
  32. public:
  33. // @brief Constructor.
  34. //
  35. // Does nothing.
  36. D2UpdateMessageTest() { }
  37. // @brief Destructor.
  38. //
  39. // Does nothing.
  40. ~D2UpdateMessageTest() { };
  41. // @brief Return string representation of the name encoded in wire format.
  42. //
  43. // This function reads the number of bytes specified in the second
  44. // argument from the buffer. It doesn't check if buffer has sufficient
  45. // length for reading given number of bytes. Caller should verify it
  46. // prior to calling this function.
  47. //
  48. // @param buf input buffer, its internal pointer will be moved to
  49. // the position after a name being read from it.
  50. // @param name_length length of the name stored in the buffer
  51. // @param no_zero_byte if true it indicates that the given buffer does not
  52. // comprise the zero byte, which signals end of the name. This is
  53. // the case, when dealing with compressed messages which don't have
  54. // this byte.
  55. //
  56. // @return string representation of the name.
  57. std::string readNameFromWire(InputBuffer& buf, size_t name_length,
  58. const bool no_zero_byte = false) {
  59. std::vector<uint8_t> name_data;
  60. // Create another InputBuffer which holds only the name in the wire
  61. // format.
  62. buf.readVector(name_data, name_length);
  63. if (no_zero_byte) {
  64. ++name_length;
  65. name_data.push_back(0);
  66. }
  67. InputBuffer name_buf(&name_data[0], name_length);
  68. // Parse the name and return its textual representation.
  69. Name name(name_buf);
  70. return (name.toText());
  71. }
  72. };
  73. // This test verifies that DNS Update message ID can be set using
  74. // setId function.
  75. TEST_F(D2UpdateMessageTest, setId) {
  76. // Message ID is initialized to 0.
  77. D2UpdateMessage msg;
  78. EXPECT_EQ(0, msg.getId());
  79. // Override the default value and verify that it has been set.
  80. msg.setId(0x1234);
  81. EXPECT_EQ(0x1234, msg.getId());
  82. }
  83. // This test verifies that the DNS Update message RCODE can be set
  84. // using setRcode function.
  85. TEST_F(D2UpdateMessageTest, setRcode) {
  86. D2UpdateMessage msg;
  87. // Rcode must be explicitly set before it is accessed.
  88. msg.setRcode(Rcode::NOERROR());
  89. EXPECT_EQ(Rcode::NOERROR().getCode(), msg.getRcode().getCode());
  90. // Let's override current value to make sure that getter does
  91. // not return fixed value.
  92. msg.setRcode(Rcode::NOTIMP());
  93. EXPECT_EQ(Rcode::NOTIMP().getCode(), msg.getRcode().getCode());
  94. }
  95. // This test verifies that the Zone section in the DNS Update message
  96. // can be set.
  97. TEST_F(D2UpdateMessageTest, setZone) {
  98. D2UpdateMessage msg;
  99. // The zone pointer is initialized to NULL.
  100. D2ZonePtr zone = msg.getZone();
  101. EXPECT_FALSE(zone);
  102. // Let's create a new Zone and check that it is returned
  103. // via getter.
  104. msg.setZone(Name("example.com"), RRClass::ANY());
  105. zone = msg.getZone();
  106. EXPECT_TRUE(zone);
  107. EXPECT_EQ("example.com.", zone->getName().toText());
  108. EXPECT_EQ(RRClass::ANY().getCode(), zone->getClass().getCode());
  109. // Now, let's check that the existing Zone object can be
  110. // overriden with a new one.
  111. msg.setZone(Name("foo.example.com"), RRClass::NONE());
  112. zone = msg.getZone();
  113. EXPECT_TRUE(zone);
  114. EXPECT_EQ("foo.example.com.", zone->getName().toText());
  115. EXPECT_EQ(RRClass::NONE().getCode(), zone->getClass().getCode());
  116. }
  117. // This test verifies that the DNS message is properly decoded from the
  118. // wire format.
  119. TEST_F(D2UpdateMessageTest, fromWire) {
  120. // The following table holds the DNS response in on-wire format.
  121. // This message comprises the following sections:
  122. // - HEADER
  123. // - PREREQUISITE section with one RR
  124. // - UPDATE section with 1 RR.
  125. // Such a response may be generated by the DNS server as a result
  126. // of copying the contents of the REQUEST message sent by DDNS client.
  127. const uint8_t bin_msg[] = {
  128. // HEADER section starts here (see RFC 2136, section 2).
  129. 0x05, 0xAF, // ID=0x05AF
  130. 0xA8, 0x6, // QR=1, Opcode=6, RCODE=YXDOMAIN
  131. 0x0, 0x1, // ZOCOUNT=1
  132. 0x0, 0x2, // PRCOUNT=2
  133. 0x0, 0x1, // UPCOUNT=1
  134. 0x0, 0x0, // ADCOUNT=0
  135. // Zone section starts here. The The first field comprises
  136. // the Zone name encoded as a set of labels, each preceded
  137. // by a length of the following label. The whole Zone name is
  138. // terminated with a NULL char.
  139. // For Zone section format see (RFC 2136, section 2.3).
  140. 0x7, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example (7 is length)
  141. 0x3, 0x63, 0x6F, 0x6D, //.com. (0x3 is a length)
  142. 0x0, // NULL character terminates the Zone name.
  143. 0x0, 0x6, // ZTYPE='SOA'
  144. 0x0, 0x1, // ZCLASS='IN'
  145. // Prerequisite section starts here. This section comprises two
  146. // prerequisites:
  147. // - 'Name is not in use'
  148. // - 'Name is in use'
  149. // See RFC 2136, section 2.4 for the format of Prerequisite section.
  150. // Each prerequisite RR starts with its name. It is expressed in the
  151. // compressed format as described in RFC 1035, section 4.1.4. The first
  152. // label is expressed as in case of non-compressed name. It is preceded
  153. // by the length value. The following two bytes are the pointer to the
  154. // offset in the message where 'example.com' was used. That is, in the
  155. // Zone name at offset 12. Pointer starts with two bits set - they
  156. // mark start of the pointer.
  157. // First prerequisite. NONE class indicates that the update requires
  158. // that the name 'foo.example.com' is not use/
  159. 0x03, 0x66, 0x6F, 0x6F, // foo.
  160. 0xC0, 0x0C, // pointer to example.com.
  161. 0x0, 0x1C, // TYPE=AAAA
  162. 0x0, 0xFE, // CLASS=NONE
  163. 0x0, 0x0, 0x0, 0x0, // TTL=0
  164. 0x0, 0x0, // RDLENGTH=0
  165. // Second prerequisite. ANY class indicates tha the update requires
  166. // that the name 'bar.example.com' exists.
  167. 0x03, 0x62, 0x61, 0x72, // bar.
  168. 0xC0, 0x0C, // pointer to example.com.
  169. 0x0, 0x1C, // TYPE=AAAA
  170. 0x0, 0xFF, // CLASS=ANY
  171. 0x0, 0x0, 0x0, 0x0, // TTL=0
  172. 0x0, 0x0, // RDLENGTH=0
  173. // Update section starts here. The format of this section conforms to
  174. // RFC 2136, section 2.5. The name of the RR is again expressed in
  175. // compressed format. The two pointer bytes point to the offset in the
  176. // message where 'foo.example.com' was used already - 29.
  177. 0xC0, 0x1D, // pointer to foo.example.com.
  178. 0x0, 0x1C, // TYPE=AAAA
  179. 0x0, 0x1, // CLASS=IN
  180. 0xAA, 0xBB, 0xCC, 0xDD, // TTL=0xAABBCCDD
  181. 0x0, 0x10, // RDLENGTH=16
  182. // The following 16 bytes of RDATA hold IPv6 address: 2001:db8:1::1.
  183. 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x01, 0x00, 0x00,
  184. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
  185. };
  186. InputBuffer buf(bin_msg, sizeof(bin_msg));
  187. // Create an object to be used to decode the message from the wire format.
  188. D2UpdateMessage msg(D2UpdateMessage::INBOUND);
  189. // Decode the message.
  190. ASSERT_NO_THROW(msg.fromWire(buf));
  191. // Check that the message header is valid.
  192. EXPECT_EQ(0x05AF, msg.getId());
  193. EXPECT_EQ(D2UpdateMessage::RESPONSE, msg.getQRFlag());
  194. EXPECT_EQ(Rcode::YXDOMAIN_CODE, msg.getRcode().getCode());
  195. // The ZOCOUNT must contain exactly one zone. If it does, we should get
  196. // the name, class and type of the zone and verify they are valid.
  197. ASSERT_EQ(1, msg.getRRCount(D2UpdateMessage::SECTION_ZONE));
  198. D2ZonePtr zone = msg.getZone();
  199. ASSERT_TRUE(zone);
  200. EXPECT_EQ("example.com.", zone->getName().toText());
  201. EXPECT_EQ(RRClass::IN().getCode(), zone->getClass().getCode());
  202. // Check the Prerequisite section. It should contain two records.
  203. ASSERT_EQ(2, msg.getRRCount(D2UpdateMessage::SECTION_PREREQUISITE));
  204. // Proceed to the first prerequisite.
  205. RRsetIterator rrset_it =
  206. msg.beginSection(D2UpdateMessage::SECTION_PREREQUISITE);
  207. RRsetPtr prereq1 = *rrset_it;
  208. ASSERT_TRUE(prereq1);
  209. // Check record fields.
  210. EXPECT_EQ("foo.example.com.", prereq1->getName().toText()); // NAME
  211. EXPECT_EQ(RRType::AAAA().getCode(), prereq1->getType().getCode()); // TYPE
  212. EXPECT_EQ(RRClass::NONE().getCode(),
  213. prereq1->getClass().getCode()); // CLASS
  214. EXPECT_EQ(0, prereq1->getTTL().getValue()); // TTL
  215. EXPECT_EQ(0, prereq1->getRdataCount()); // RDLENGTH
  216. // Move to next prerequisite section.
  217. ++rrset_it;
  218. RRsetPtr prereq2 = *rrset_it;
  219. ASSERT_TRUE(prereq2);
  220. // Check record fields.
  221. EXPECT_EQ("bar.example.com.", prereq2->getName().toText()); // NAME
  222. EXPECT_EQ(RRType::AAAA().getCode(), prereq2->getType().getCode()); // TYPE
  223. EXPECT_EQ(RRClass::ANY().getCode(), prereq2->getClass().getCode()); // CLASS
  224. EXPECT_EQ(0, prereq2->getTTL().getValue()); // TTL
  225. EXPECT_EQ(0, prereq2->getRdataCount()); // RDLENGTH
  226. // Check the Update section. There is only one record, so beginSection()
  227. // should return the pointer to this sole record.
  228. ASSERT_EQ(1, msg.getRRCount(D2UpdateMessage::SECTION_UPDATE));
  229. rrset_it = msg.beginSection(D2UpdateMessage::SECTION_UPDATE);
  230. RRsetPtr update = *rrset_it;
  231. ASSERT_TRUE(update);
  232. // Check the record fields.
  233. EXPECT_EQ("foo.example.com.", update->getName().toText()); // NAME
  234. EXPECT_EQ(RRType::AAAA().getCode(), update->getType().getCode()); // TYPE
  235. EXPECT_EQ(RRClass::IN().getCode(), update->getClass().getCode()); // CLASS
  236. EXPECT_EQ(0xAABBCCDD, update->getTTL().getValue()); // TTL
  237. // There should be exactly one record holding the IPv6 address.
  238. // This record can be accessed using RdataIterator. This record
  239. // can be compared with the reference record, holding expected IPv6
  240. // address using compare function.
  241. ASSERT_EQ(1, update->getRdataCount());
  242. RdataIteratorPtr rdata_it = update->getRdataIterator();
  243. ASSERT_TRUE(rdata_it);
  244. in::AAAA rdata_ref("2001:db8:1::1");
  245. EXPECT_EQ(0, rdata_ref.compare(rdata_it->getCurrent()));
  246. // @todo: at this point we don't test Additional Data records. We may
  247. // consider implementing tests for it in the future.
  248. }
  249. // This test verifies that the fromWire function throws appropriate exception
  250. // if the message being parsed comprises invalid Opcode (is not a DNS Update).
  251. TEST_F(D2UpdateMessageTest, fromWireInvalidOpcode) {
  252. // This is a binary representation of the DNS message.
  253. // It comprises invalid Opcode=3, expected value is 6
  254. // (Update).
  255. const uint8_t bin_msg[] = {
  256. 0x05, 0xAF, // ID=0x05AF
  257. 0x98, 0x6, // QR=1, Opcode=3, RCODE=YXDOMAIN
  258. 0x0, 0x0, // ZOCOUNT=0
  259. 0x0, 0x0, // PRCOUNT=0
  260. 0x0, 0x0, // UPCOUNT=0
  261. 0x0, 0x0 // ADCOUNT=0
  262. };
  263. InputBuffer buf(bin_msg, sizeof(bin_msg));
  264. // The 'true' argument passed to the constructor turns the
  265. // message into the parse mode in which the fromWire function
  266. // can be used to decode the binary mesasage data.
  267. D2UpdateMessage msg(D2UpdateMessage::INBOUND);
  268. // When using invalid Opcode, the fromWire function should
  269. // throw NotUpdateMessage exception.
  270. EXPECT_THROW(msg.fromWire(buf), isc::d2::NotUpdateMessage);
  271. }
  272. // This test verifies that the fromWire function throws appropriate exception
  273. // if the message being parsed comprises invalid QR flag. The QR bit is
  274. // expected to be set to indicate that the message is a RESPONSE.
  275. TEST_F(D2UpdateMessageTest, fromWireInvalidQRFlag) {
  276. // This is a binary representation of the DNS message.
  277. // It comprises invalid QR flag = 0.
  278. const uint8_t bin_msg[] = {
  279. 0x05, 0xAF, // ID=0x05AF
  280. 0x28, 0x6, // QR=0, Opcode=6, RCODE=YXDOMAIN
  281. 0x0, 0x0, // ZOCOUNT=0
  282. 0x0, 0x0, // PRCOUNT=0
  283. 0x0, 0x0, // UPCOUNT=0
  284. 0x0, 0x0 // ADCOUNT=0
  285. };
  286. InputBuffer buf(bin_msg, sizeof(bin_msg));
  287. // The 'true' argument passed to the constructor turns the
  288. // message into the parse mode in which the fromWire function
  289. // can be used to decode the binary mesasage data.
  290. D2UpdateMessage msg(D2UpdateMessage::INBOUND);
  291. // When using invalid QR flag, the fromWire function should
  292. // throw InvalidQRFlag exception.
  293. EXPECT_THROW(msg.fromWire(buf), isc::d2::InvalidQRFlag);
  294. }
  295. // This test verifies that the fromWire function throws appropriate exception
  296. // if the message being parsed comprises more than one (two in this case)
  297. // Zone records.
  298. TEST_F(D2UpdateMessageTest, fromWireTooManyZones) {
  299. // This is a binary representation of the DNS message. This message
  300. // comprises two Zone records.
  301. const uint8_t bin_msg[] = {
  302. 0x05, 0xAF, // ID=0x05AF
  303. 0xA8, 0x6, // QR=1, Opcode=6, RCODE=YXDOMAIN
  304. 0x0, 0x2, // ZOCOUNT=2
  305. 0x0, 0x0, // PRCOUNT=0
  306. 0x0, 0x0, // UPCOUNT=0
  307. 0x0, 0x0, // ADCOUNT=0
  308. // Start first Zone record.
  309. 0x7, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example (7 is length)
  310. 0x3, 0x63, 0x6F, 0x6D, //.com. (0x3 is a length)
  311. 0x0, // NULL character terminates the Zone name.
  312. 0x0, 0x6, // ZTYPE='SOA'
  313. 0x0, 0x1, // ZCLASS='IN'
  314. // Start second Zone record. Presence of this record should result
  315. // in error when parsing this message.
  316. 0x3, 0x63, 0x6F, 0x6D, // com. (0x3 is a length)
  317. 0x0, // NULL character terminates the Zone name.
  318. 0x0, 0x6, // ZTYPE='SOA'
  319. 0x0, 0x1 // ZCLASS='IN'
  320. };
  321. InputBuffer buf(bin_msg, sizeof(bin_msg));
  322. // The 'true' argument passed to the constructor turns the
  323. // message into the parse mode in which the fromWire function
  324. // can be used to decode the binary mesasage data.
  325. D2UpdateMessage msg(D2UpdateMessage::INBOUND);
  326. // When parsing a message with more than one Zone record,
  327. // exception should be thrown.
  328. EXPECT_THROW(msg.fromWire(buf), isc::d2::InvalidZoneSection);
  329. }
  330. // This test verifies that the wire format of the message is produced
  331. // in the render mode.
  332. TEST_F(D2UpdateMessageTest, toWire) {
  333. D2UpdateMessage msg;
  334. // Set message ID.
  335. msg.setId(0x1234);
  336. // Rcode to NOERROR.
  337. msg.setRcode(Rcode(Rcode::NOERROR_CODE));
  338. // Set Zone section. This section must comprise exactly
  339. // one Zone. toWire function would fail if Zone is not set.
  340. msg.setZone(Name("example.com"), RRClass::IN());
  341. // Set prerequisities.
  342. // 'Name Is Not In Use' prerequisite (RFC 2136, section 2.4.5)
  343. RRsetPtr prereq1(new RRset(Name("foo.example.com"), RRClass::NONE(),
  344. RRType::ANY(), RRTTL(0)));
  345. msg.addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq1);
  346. // 'Name is In Use' prerequisite (RFC 2136, section 2.4.4)
  347. RRsetPtr prereq2(new RRset(Name("bar.example.com"), RRClass::ANY(),
  348. RRType::ANY(), RRTTL(0)));
  349. msg.addRRset(D2UpdateMessage::SECTION_PREREQUISITE, prereq2);
  350. // Set Update Section.
  351. // Create RR holding a name being added. This RR is constructed
  352. // in conformance to RFC 2136, section 2.5.1.
  353. RRsetPtr updaterr1(new RRset(Name("foo.example.com"), RRClass::IN(),
  354. RRType::A(), RRTTL(10)));
  355. // RR record is of the type A, thus RDATA holds 4 octet Internet
  356. // address. This address is 10.10.1.1.
  357. char rdata1[] = {
  358. 0xA, 0xA , 0x1, 0x1
  359. };
  360. InputBuffer buf_rdata1(rdata1, 4);
  361. updaterr1->addRdata(createRdata(RRType::A(), RRClass::IN(), buf_rdata1,
  362. buf_rdata1.getLength()));
  363. // Add the RR to the message.
  364. msg.addRRset(D2UpdateMessage::SECTION_UPDATE, updaterr1);
  365. // Render message into the wire format.
  366. MessageRenderer renderer;
  367. ASSERT_NO_THROW(msg.toWire(renderer));
  368. // Make sure that created packet is not truncated.
  369. ASSERT_EQ(77, renderer.getLength());
  370. // Create input buffer from the rendered data. InputBuffer
  371. // is handy to validate the byte contents of the rendered
  372. // message.
  373. InputBuffer buf(renderer.getData(), renderer.getLength());
  374. // Start validating the message header.
  375. // Verify message ID.
  376. EXPECT_EQ(0x1234, buf.readUint16());
  377. // The 2-bytes following message ID comprise the following fields:
  378. // - QR - 1 bit indicating that it is REQUEST. Should be 0.
  379. // - Opcode - 4 bits which should hold value of 5 indicating this is
  380. // an Update message. Binary form is "0101".
  381. // - Z - These bits are unused for Update Message and should be 0.
  382. // - RCODE - Response code, set to NOERROR for REQUEST. It is 0.
  383. //8706391835
  384. // The binary value is:
  385. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  386. // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  387. // | QR| Opcode | Z | RCODE |
  388. // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  389. // | 0 | 0 1 0 1 | 0 0 0 0 0 0 0 | 0 0 0 0 |
  390. // +---+---+---+-------+---+---+---+---+---+---+---+---+---+---+---+
  391. // and the hexadecimal representation is 0x2800.
  392. EXPECT_EQ(0x2800, buf.readUint16());
  393. // ZOCOUNT - holds the number of zones for the update. For Request
  394. // message it must be exactly one record (RFC2136, section 2.3).
  395. EXPECT_EQ(1, buf.readUint16());
  396. // PRCOUNT - holds the number of prerequisites. Earlier we have added
  397. // two prerequisites. Thus, expect that this conter is 2.
  398. EXPECT_EQ(2, buf.readUint16());
  399. // UPCOUNT - holds the number of RRs in the Update Section. We have
  400. // added 1 RR, which adds the name foo.example.com to the Zone.
  401. EXPECT_EQ(1, buf.readUint16());
  402. // ADCOUNT - holds the number of RRs in the Additional Data Section.
  403. EXPECT_EQ(0, buf.readUint16());
  404. // Start validating the Zone section. This section comprises the
  405. // following data:
  406. // - ZNAME
  407. // - ZTYPE
  408. // - ZCLASS
  409. // ZNAME holds 'example.com.' encoded as set of labels. Each label
  410. // is preceded by its length. The name is ended with the byte holding
  411. // zero value. This yields the total size of the name in wire format
  412. // of 13 bytes.
  413. // The simplest way to convert the name from wire format to a string
  414. // is to use dns::Name class. It should be ok to rely on the Name class
  415. // to decode the name, because it is unit tested elswhere.
  416. std::string zone_name = readNameFromWire(buf, 13);
  417. EXPECT_EQ("example.com.", zone_name);
  418. // ZTYPE of the Zone section must be SOA according to RFC 2136,
  419. // section 2.3.
  420. EXPECT_EQ(RRType::SOA().getCode(), buf.readUint16());
  421. // ZCLASS of the Zone section is IN.
  422. EXPECT_EQ(RRClass::IN().getCode(), buf.readUint16());
  423. // Start checks on Prerequisite section. Each prerequisite comprises
  424. // the following fields:
  425. // - NAME - name of the RR in wire format
  426. // - TYPE - two octets with one of the RR TYPE codes
  427. // - CLASS - two octets with one of the RR CLASS codes
  428. // - TTL - a 32-bit signed integer specifying Time-To-Live
  429. // - RDLENGTH - length of the RDATA field
  430. // - RDATA - a variable length string of octets containing
  431. // resource data.
  432. // In case of this message, we expect to have two prerequisite RRs.
  433. // Their structure is checked below.
  434. // First prerequisite should comprise the 'Name is not in use prerequisite'
  435. // for 'foo.example.com'.
  436. // Check the name first. Message renderer is using compression for domain
  437. // names as described in RFC 1035, section 4.1.4. The name in this RR is
  438. // foo.example.com. The name of the zone is example.com and it has occured
  439. // in this message already at offset 12 (the size of the header is 12).
  440. // Therefore, name of this RR is encoded as 'foo', followed by a pointer
  441. // to offset in this message where the remainder of this name was used.
  442. // This pointer has the following format:
  443. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  444. // | 1 1| OFFSET |
  445. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  446. // | 1 1| 0 0 0 0 0 0 0 0 0 0 1 1 0 0|
  447. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  448. // which has a following hexadecimal representation: 0xC00C
  449. // Let's read the non-compressed part first - 'foo.'
  450. std::string name_prereq1 = readNameFromWire(buf, 4, true);
  451. EXPECT_EQ("foo.", name_prereq1);
  452. // The remaining two bytes hold the pointer to 'example.com'.
  453. EXPECT_EQ(0xC00C, buf.readUint16());
  454. // TYPE is ANY
  455. EXPECT_EQ(RRType::ANY().getCode(), buf.readUint16());
  456. // CLASS is NONE
  457. EXPECT_EQ(RRClass::NONE().getCode(), buf.readUint16());
  458. // TTL is a 32-but value, expecting 0
  459. EXPECT_EQ(0, buf.readUint32());
  460. // There is no RDATA, so RDLENGTH is 0
  461. EXPECT_EQ(0, buf.readUint16());
  462. // Start checking second prerequisite.
  463. std::string name_prereq2 = readNameFromWire(buf, 4, true);
  464. EXPECT_EQ("bar.", name_prereq2);
  465. // The remaining two bytes hold the pointer to 'example.com'.
  466. EXPECT_EQ(0xC00C, buf.readUint16());
  467. // TYPE is ANY
  468. EXPECT_EQ(RRType::ANY().getCode(), buf.readUint16());
  469. // CLASS is ANY
  470. EXPECT_EQ(RRClass::ANY().getCode(), buf.readUint16());
  471. // TTL is a 32-but value, expecting 0
  472. EXPECT_EQ(0, buf.readUint32());
  473. // There is no RDATA, so RDLENGTH is 0
  474. EXPECT_EQ(0, buf.readUint16());
  475. // Start checking Update section. This section contains RRset with
  476. // one A RR.
  477. // The name of the RR is 'foo.example.com'. It is encoded in the
  478. // compressed format - as a pointer to the name of prerequisite 1.
  479. // This name is in offset 0x1D in this message.
  480. EXPECT_EQ(0xC01D, buf.readUint16());
  481. // TYPE is A
  482. EXPECT_EQ(RRType::A().getCode(), buf.readUint16());
  483. // CLASS is IN (same as zone class)
  484. EXPECT_EQ(RRClass::IN().getCode(), buf.readUint16());
  485. // TTL is a 32-but value, set here to 10.
  486. EXPECT_EQ(10, buf.readUint32());
  487. // For A records, the RDATA comprises the 4-byte Internet address.
  488. // So, RDLENGTH is 4.
  489. EXPECT_EQ(4, buf.readUint16());
  490. // We have stored the following address in RDATA field: 10.10.1.1
  491. // (which is 0A 0A 01 01) in hexadecimal format.
  492. EXPECT_EQ(0x0A0A0101, buf.readUint32());
  493. // @todo: consider extending this test to verify Additional Data
  494. // section.
  495. }
  496. // This test verifies that an attempt to call toWire function on the
  497. // received message will result in an exception.
  498. TEST_F(D2UpdateMessageTest, toWireInvalidQRFlag) {
  499. // This is a binary representation of the DNS message.
  500. // This message is valid and should be parsed with no
  501. // error.
  502. const uint8_t bin_msg[] = {
  503. 0x05, 0xAF, // ID=0x05AF
  504. 0xA8, 0x6, // QR=1, Opcode=6, RCODE=YXDOMAIN
  505. 0x0, 0x0, // ZOCOUNT=0
  506. 0x0, 0x0, // PRCOUNT=0
  507. 0x0, 0x0, // UPCOUNT=0
  508. 0x0, 0x0 // ADCOUNT=0
  509. };
  510. InputBuffer buf(bin_msg, sizeof(bin_msg));
  511. // The 'true' argument passed to the constructor turns the
  512. // message into the parse mode in which the fromWire function
  513. // can be used to decode the binary mesasage data.
  514. D2UpdateMessage msg(D2UpdateMessage::INBOUND);
  515. ASSERT_NO_THROW(msg.fromWire(buf));
  516. // The message is parsed. The QR Flag should now indicate that
  517. // it is a Response message.
  518. ASSERT_EQ(D2UpdateMessage::RESPONSE, msg.getQRFlag());
  519. // An attempt to call toWire on the Response message should
  520. // result in the InvalidQRFlag exception.
  521. MessageRenderer renderer;
  522. EXPECT_THROW(msg.toWire(renderer), isc::d2::InvalidQRFlag);
  523. }
  524. } // End of anonymous namespace