nc_test_utils.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. // Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <d2/d2_cfg_mgr.h>
  8. #include <dns/opcode.h>
  9. #include <dns/messagerenderer.h>
  10. #include <nc_test_utils.h>
  11. #include <boost/asio.hpp>
  12. #include <asiolink/udp_endpoint.h>
  13. #include <util/encode/base64.h>
  14. #include <gtest/gtest.h>
  15. using namespace std;
  16. using namespace isc;
  17. using namespace isc::d2;
  18. namespace isc {
  19. namespace d2 {
  20. const char* TEST_DNS_SERVER_IP = "127.0.0.1";
  21. size_t TEST_DNS_SERVER_PORT = 5301;
  22. //const bool HAS_RDATA = true;
  23. const bool NO_RDATA = false;
  24. //*************************** FauxServer class ***********************
  25. FauxServer::FauxServer(asiolink::IOService& io_service,
  26. asiolink::IOAddress& address, size_t port)
  27. :io_service_(io_service), address_(address), port_(port),
  28. server_socket_(), receive_pending_(false), perpetual_receive_(true),
  29. tsig_key_() {
  30. server_socket_.reset(new boost::asio::ip::udp::socket(io_service_.get_io_service(),
  31. boost::asio::ip::udp::v4()));
  32. server_socket_->set_option(boost::asio::socket_base::reuse_address(true));
  33. isc::asiolink::UDPEndpoint endpoint(address_, port_);
  34. server_socket_->bind(endpoint.getASIOEndpoint());
  35. }
  36. FauxServer::FauxServer(asiolink::IOService& io_service,
  37. DnsServerInfo& server)
  38. :io_service_(io_service), address_(server.getIpAddress()),
  39. port_(server.getPort()), server_socket_(), receive_pending_(false),
  40. perpetual_receive_(true), tsig_key_() {
  41. server_socket_.reset(new boost::asio::ip::udp::socket(io_service_.get_io_service(),
  42. boost::asio::ip::udp::v4()));
  43. server_socket_->set_option(boost::asio::socket_base::reuse_address(true));
  44. isc::asiolink::UDPEndpoint endpoint(address_, port_);
  45. server_socket_->bind(endpoint.getASIOEndpoint());
  46. }
  47. FauxServer::~FauxServer() {
  48. }
  49. void
  50. FauxServer::receive (const ResponseMode& response_mode,
  51. const dns::Rcode& response_rcode) {
  52. if (receive_pending_) {
  53. return;
  54. }
  55. receive_pending_ = true;
  56. server_socket_->async_receive_from(boost::asio::buffer(receive_buffer_,
  57. sizeof(receive_buffer_)),
  58. remote_,
  59. boost::bind(&FauxServer::requestHandler,
  60. this, _1, _2,
  61. response_mode,
  62. response_rcode));
  63. }
  64. void
  65. FauxServer::requestHandler(const boost::system::error_code& error,
  66. std::size_t bytes_recvd,
  67. const ResponseMode& response_mode,
  68. const dns::Rcode& response_rcode) {
  69. receive_pending_ = false;
  70. // If we encountered an error or received no data then fail.
  71. // We expect the client to send good requests.
  72. if (error.value() != 0 || bytes_recvd < 1) {
  73. ADD_FAILURE() << "FauxServer receive failed: " << error.message();
  74. return;
  75. }
  76. // If TSIG key isn't NULL, create a context and use to verify the
  77. // request and sign the response.
  78. dns::TSIGContextPtr context;
  79. if (tsig_key_) {
  80. context.reset(new dns::TSIGContext(*tsig_key_));
  81. }
  82. // We have a successfully received data. We need to turn it into
  83. // a request in order to build a proper response.
  84. // Note D2UpdateMessage is geared towards making requests and
  85. // reading responses. This is the opposite perspective so we have
  86. // to a bit of roll-your-own here.
  87. dns::Message request(dns::Message::PARSE);
  88. util::InputBuffer request_buf(receive_buffer_, bytes_recvd);
  89. try {
  90. request.fromWire(request_buf);
  91. // If contex is not NULL, then we need to verify the message.
  92. if (context) {
  93. dns::TSIGError error = context->verify(request.getTSIGRecord(),
  94. receive_buffer_,
  95. bytes_recvd);
  96. if (error != dns::TSIGError::NOERROR()) {
  97. isc_throw(TSIGVerifyError, "TSIG verification failed: "
  98. << error.toText());
  99. }
  100. }
  101. } catch (const std::exception& ex) {
  102. // If the request cannot be parsed, then fail the test.
  103. // We expect the client to send good requests.
  104. ADD_FAILURE() << "FauxServer request is corrupt:" << ex.what();
  105. return;
  106. }
  107. // The request parsed OK, so let's build a response.
  108. // We must use the QID we received in the response or IOFetch will
  109. // toss the response out, resulting in eventual timeout.
  110. // We fill in the zone with data we know is from the "server".
  111. dns::Message response(dns::Message::RENDER);
  112. response.setQid(request.getQid());
  113. dns::Question question(dns::Name("response.example.com"),
  114. dns::RRClass::ANY(), dns::RRType::SOA());
  115. response.addQuestion(question);
  116. response.setOpcode(dns::Opcode(dns::Opcode::UPDATE_CODE));
  117. response.setHeaderFlag(dns::Message::HEADERFLAG_QR, true);
  118. // Set the response Rcode to value passed in, default is NOERROR.
  119. response.setRcode(response_rcode);
  120. // Render the response to a buffer.
  121. dns::MessageRenderer renderer;
  122. util::OutputBuffer response_buf(TEST_MSG_MAX);
  123. renderer.setBuffer(&response_buf);
  124. if (response_mode == INVALID_TSIG) {
  125. // Create a different key to sign the response.
  126. std::string secret ("key that doesn't match");
  127. dns::TSIGKeyPtr key;
  128. ASSERT_NO_THROW(key.reset(new
  129. dns::TSIGKey(dns::Name("badkey"),
  130. dns::TSIGKey::HMACMD5_NAME(),
  131. secret.c_str(), secret.size())));
  132. context.reset(new dns::TSIGContext(*key));
  133. }
  134. response.toWire(renderer, context.get());
  135. // If mode is to ship garbage, then stomp on part of the rendered
  136. // message.
  137. if (response_mode == CORRUPT_RESP) {
  138. response_buf.writeUint16At(0xFFFF, 2);
  139. }
  140. // Ship the response via synchronous send.
  141. try {
  142. int cnt = server_socket_->send_to(boost::asio::
  143. buffer(response_buf.getData(),
  144. response_buf.getLength()),
  145. remote_);
  146. // Make sure we sent what we expect to send.
  147. if (cnt != response_buf.getLength()) {
  148. ADD_FAILURE() << "FauxServer sent: " << cnt << " expected: "
  149. << response_buf.getLength();
  150. }
  151. } catch (const std::exception& ex) {
  152. ADD_FAILURE() << "FauxServer send failed: " << ex.what();
  153. }
  154. if (perpetual_receive_) {
  155. // Schedule the next receive
  156. receive (response_mode, response_rcode);
  157. }
  158. }
  159. //********************** TimedIO class ***********************
  160. TimedIO::TimedIO()
  161. : io_service_(new isc::asiolink::IOService()),
  162. timer_(*io_service_), run_time_(0) {
  163. }
  164. TimedIO::~TimedIO() {
  165. }
  166. int
  167. TimedIO::runTimedIO(int run_time) {
  168. run_time_ = run_time;
  169. int cnt = io_service_->get_io_service().poll();
  170. if (cnt == 0) {
  171. timer_.setup(boost::bind(&TimedIO::timesUp, this), run_time_);
  172. cnt = io_service_->get_io_service().run_one();
  173. timer_.cancel();
  174. }
  175. return (cnt);
  176. }
  177. void
  178. TimedIO::timesUp() {
  179. io_service_->stop();
  180. FAIL() << "Test Time: " << run_time_ << " expired";
  181. }
  182. //********************** TransactionTest class ***********************
  183. const unsigned int TransactionTest::FORWARD_CHG = 0x01;
  184. const unsigned int TransactionTest::REVERSE_CHG = 0x02;
  185. const unsigned int TransactionTest::FWD_AND_REV_CHG = REVERSE_CHG | FORWARD_CHG;
  186. TransactionTest::TransactionTest() : ncr_(), cfg_mgr_(new D2CfgMgr()) {
  187. }
  188. TransactionTest::~TransactionTest() {
  189. }
  190. void
  191. TransactionTest::setupForIPv4Transaction(dhcp_ddns::NameChangeType chg_type,
  192. int change_mask,
  193. const TSIGKeyInfoPtr& tsig_key_info) {
  194. const char* msg_str =
  195. "{"
  196. " \"change-type\" : 0 , "
  197. " \"forward-change\" : true , "
  198. " \"reverse-change\" : true , "
  199. " \"fqdn\" : \"my.forward.example.com.\" , "
  200. " \"ip-address\" : \"192.168.2.1\" , "
  201. " \"dhcid\" : \"0102030405060708\" , "
  202. " \"lease-expires-on\" : \"20130121132405\" , "
  203. " \"lease-length\" : 1300 "
  204. "}";
  205. // Create NameChangeRequest from JSON string.
  206. ncr_ = dhcp_ddns::NameChangeRequest::fromJSON(msg_str);
  207. // Set the change type.
  208. ncr_->setChangeType(chg_type);
  209. // If the change mask does not include a forward change clear the
  210. // forward domain; otherwise create the domain and its servers.
  211. if (!(change_mask & FORWARD_CHG)) {
  212. ncr_->setForwardChange(false);
  213. forward_domain_.reset();
  214. } else {
  215. // Create the forward domain and then its servers.
  216. forward_domain_ = makeDomain("example.com.", tsig_key_info);
  217. addDomainServer(forward_domain_, "forward.example.com",
  218. "127.0.0.1", 5301);
  219. addDomainServer(forward_domain_, "forward2.example.com",
  220. "127.0.0.1", 5302);
  221. }
  222. // If the change mask does not include a reverse change clear the
  223. // reverse domain; otherwise create the domain and its servers.
  224. if (!(change_mask & REVERSE_CHG)) {
  225. ncr_->setReverseChange(false);
  226. reverse_domain_.reset();
  227. } else {
  228. // Create the reverse domain and its server.
  229. reverse_domain_ = makeDomain("2.168.192.in.addr.arpa.", tsig_key_info);
  230. addDomainServer(reverse_domain_, "reverse.example.com",
  231. "127.0.0.1", 5301);
  232. addDomainServer(reverse_domain_, "reverse2.example.com",
  233. "127.0.0.1", 5302);
  234. }
  235. }
  236. void
  237. TransactionTest::setupForIPv4Transaction(dhcp_ddns::NameChangeType chg_type,
  238. int change_mask,
  239. const std::string& key_name) {
  240. setupForIPv4Transaction(chg_type, change_mask, makeTSIGKeyInfo(key_name));
  241. }
  242. void
  243. TransactionTest::setupForIPv6Transaction(dhcp_ddns::NameChangeType chg_type,
  244. int change_mask,
  245. const TSIGKeyInfoPtr& tsig_key_info) {
  246. const char* msg_str =
  247. "{"
  248. " \"change-type\" : 0 , "
  249. " \"forward-change\" : true , "
  250. " \"reverse-change\" : true , "
  251. " \"fqdn\" : \"my6.forward.example.com.\" , "
  252. " \"ip-address\" : \"2001:1::100\" , "
  253. " \"dhcid\" : \"0102030405060708\" , "
  254. " \"lease-expires-on\" : \"20130121132405\" , "
  255. " \"lease-length\" : 1300 "
  256. "}";
  257. // Create NameChangeRequest from JSON string.
  258. ncr_ = makeNcrFromString(msg_str);
  259. // Set the change type.
  260. ncr_->setChangeType(chg_type);
  261. // If the change mask does not include a forward change clear the
  262. // forward domain; otherwise create the domain and its servers.
  263. if (!(change_mask & FORWARD_CHG)) {
  264. ncr_->setForwardChange(false);
  265. forward_domain_.reset();
  266. } else {
  267. // Create the forward domain and then its servers.
  268. forward_domain_ = makeDomain("example.com.", tsig_key_info);
  269. addDomainServer(forward_domain_, "fwd6-server.example.com",
  270. "::1", 5301);
  271. addDomainServer(forward_domain_, "fwd6-server2.example.com",
  272. "::1", 5302);
  273. }
  274. // If the change mask does not include a reverse change clear the
  275. // reverse domain; otherwise create the domain and its servers.
  276. if (!(change_mask & REVERSE_CHG)) {
  277. ncr_->setReverseChange(false);
  278. reverse_domain_.reset();
  279. } else {
  280. // Create the reverse domain and its server.
  281. reverse_domain_ = makeDomain("1.2001.ip6.arpa.", tsig_key_info);
  282. addDomainServer(reverse_domain_, "rev6-server.example.com",
  283. "::1", 5301);
  284. addDomainServer(reverse_domain_, "rev6-server2.example.com",
  285. "::1", 5302);
  286. }
  287. }
  288. void
  289. TransactionTest::setupForIPv6Transaction(dhcp_ddns::NameChangeType chg_type,
  290. int change_mask,
  291. const std::string& key_name) {
  292. setupForIPv6Transaction(chg_type, change_mask, makeTSIGKeyInfo(key_name));
  293. }
  294. //********************** Functions ****************************
  295. void
  296. checkRRCount(const D2UpdateMessagePtr& request,
  297. D2UpdateMessage::UpdateMsgSection section, int count) {
  298. dns::RRsetIterator rrset_it = request->beginSection(section);
  299. dns::RRsetIterator rrset_end = request->endSection(section);
  300. ASSERT_EQ(count, std::distance(rrset_it, rrset_end));
  301. }
  302. void
  303. checkZone(const D2UpdateMessagePtr& request, const std::string& exp_zone_name) {
  304. // Verify the zone section info.
  305. D2ZonePtr zone = request->getZone();
  306. EXPECT_TRUE(zone);
  307. EXPECT_EQ(exp_zone_name, zone->getName().toText());
  308. EXPECT_EQ(dns::RRClass::IN().getCode(), zone->getClass().getCode());
  309. }
  310. void
  311. checkRR(dns::RRsetPtr rrset, const std::string& exp_name,
  312. const dns::RRClass& exp_class, const dns::RRType& exp_type,
  313. unsigned int exp_ttl, dhcp_ddns::NameChangeRequestPtr ncr,
  314. bool has_rdata) {
  315. // Verify the FQDN/DHCID RR fields.
  316. EXPECT_EQ(exp_name, rrset->getName().toText());
  317. EXPECT_EQ(exp_class.getCode(), rrset->getClass().getCode());
  318. EXPECT_EQ(exp_type.getCode(), rrset->getType().getCode());
  319. EXPECT_EQ(exp_ttl, rrset->getTTL().getValue());
  320. if ((!has_rdata) ||
  321. (exp_type == dns::RRType::ANY() || exp_class == dns::RRClass::ANY())) {
  322. // ANY types do not have RData
  323. ASSERT_EQ(0, rrset->getRdataCount());
  324. return;
  325. }
  326. ASSERT_EQ(1, rrset->getRdataCount());
  327. dns::RdataIteratorPtr rdata_it = rrset->getRdataIterator();
  328. ASSERT_TRUE(rdata_it);
  329. if ((exp_type == dns::RRType::A()) ||
  330. (exp_type == dns::RRType::AAAA())) {
  331. // should have lease rdata
  332. EXPECT_EQ(ncr->getIpAddress(), rdata_it->getCurrent().toText());
  333. } else if (exp_type == dns::RRType::PTR()) {
  334. // should have PTR rdata
  335. EXPECT_EQ(ncr->getFqdn(), rdata_it->getCurrent().toText());
  336. } else if (exp_type == dns::RRType::DHCID()) {
  337. // should have DHCID rdata
  338. const std::vector<uint8_t>& ncr_dhcid = ncr->getDhcid().getBytes();
  339. util::InputBuffer buffer(ncr_dhcid.data(), ncr_dhcid.size());
  340. dns::rdata::in::DHCID rdata_ref(buffer, ncr_dhcid.size());
  341. EXPECT_EQ(0, rdata_ref.compare(rdata_it->getCurrent()));
  342. } else {
  343. // we got a problem
  344. FAIL();
  345. }
  346. }
  347. dns::RRsetPtr
  348. getRRFromSection(const D2UpdateMessagePtr& request,
  349. D2UpdateMessage::UpdateMsgSection section, int index) {
  350. dns::RRsetIterator rrset_it = request->beginSection(section);
  351. dns::RRsetIterator rrset_end = request->endSection(section);
  352. if (std::distance(rrset_it, rrset_end) <= index) {
  353. // Return an empty pointer if index is out of range.
  354. return (dns::RRsetPtr());
  355. }
  356. std::advance(rrset_it, index);
  357. return (*rrset_it);
  358. }
  359. dhcp_ddns::NameChangeRequestPtr makeNcrFromString(const std::string& ncr_str) {
  360. return (dhcp_ddns::NameChangeRequest::fromJSON(ncr_str));
  361. }
  362. DdnsDomainPtr makeDomain(const std::string& zone_name,
  363. const std::string& key_name) {
  364. DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
  365. DdnsDomainPtr domain(new DdnsDomain(zone_name, servers,
  366. makeTSIGKeyInfo(key_name)));
  367. return (domain);
  368. }
  369. DdnsDomainPtr makeDomain(const std::string& zone_name,
  370. const TSIGKeyInfoPtr &tsig_key_info) {
  371. DdnsDomainPtr domain;
  372. DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
  373. domain.reset(new DdnsDomain(zone_name, servers, tsig_key_info));
  374. return (domain);
  375. }
  376. TSIGKeyInfoPtr makeTSIGKeyInfo(const std::string& key_name,
  377. const std::string& secret,
  378. const std::string& algorithm) {
  379. TSIGKeyInfoPtr key_info;
  380. if (!key_name.empty()) {
  381. if (!secret.empty()) {
  382. key_info.reset(new TSIGKeyInfo(key_name, algorithm, secret));
  383. } else {
  384. // Since secret was left blank, we'll convert key_name into a
  385. // base64 encoded string and use that.
  386. const uint8_t* bytes = reinterpret_cast<const uint8_t*>
  387. (key_name.c_str());
  388. size_t len = key_name.size();
  389. const vector<uint8_t> key_name_v(bytes, bytes + len);
  390. std::string key_name64
  391. = isc::util::encode::encodeBase64(key_name_v);
  392. // Now, make the TSIGKeyInfo with a real base64 secret.
  393. key_info.reset(new TSIGKeyInfo(key_name, algorithm, key_name64));
  394. }
  395. }
  396. return (key_info);
  397. }
  398. void addDomainServer(DdnsDomainPtr& domain, const std::string& name,
  399. const std::string& ip, const size_t port) {
  400. DnsServerInfoPtr server(new DnsServerInfo(name, asiolink::IOAddress(ip),
  401. port));
  402. domain->getServers()->push_back(server);
  403. }
  404. // Verifies that the contents of the given transaction's DNS update request
  405. // is correct for adding a forward DNS entry
  406. void checkAddFwdAddressRequest(NameChangeTransaction& tran) {
  407. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  408. ASSERT_TRUE(request);
  409. // Safety check.
  410. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  411. ASSERT_TRUE(ncr);
  412. std::string exp_zone_name = tran.getForwardDomain()->getName();
  413. std::string exp_fqdn = ncr->getFqdn();
  414. const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
  415. // Verify the zone section.
  416. checkZone(request, exp_zone_name);
  417. // Verify the PREREQUISITE SECTION
  418. // Should be 1 which tests for FQDN does not exist.
  419. dns::RRsetPtr rrset;
  420. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
  421. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  422. SECTION_PREREQUISITE, 0));
  423. checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::ANY(), 0, ncr);
  424. // Verify the UPDATE SECTION
  425. // Should be 2 RRs: 1 to add the FQDN/IP and one to add the DHCID RR
  426. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2);
  427. // Fetch ttl.
  428. uint32_t ttl = ncr->getLeaseLength();
  429. // First, Verify the FQDN/IP add RR.
  430. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  431. SECTION_UPDATE, 0));
  432. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
  433. // Now, verify the DHCID add RR.
  434. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  435. SECTION_UPDATE, 1));
  436. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
  437. ttl, ncr);
  438. // Verify there are no RRs in the ADDITIONAL Section.
  439. checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0);
  440. // Verify that it will render toWire without throwing.
  441. dns::MessageRenderer renderer;
  442. ASSERT_NO_THROW(request->toWire(renderer));
  443. }
  444. // Verifies that the contents of the given transaction's DNS update request
  445. // is correct for replacing a forward DNS entry
  446. void checkReplaceFwdAddressRequest(NameChangeTransaction& tran) {
  447. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  448. ASSERT_TRUE(request);
  449. // Safety check.
  450. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  451. ASSERT_TRUE(ncr);
  452. std::string exp_zone_name = tran.getForwardDomain()->getName();
  453. std::string exp_fqdn = ncr->getFqdn();
  454. const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
  455. // Verify the zone section.
  456. checkZone(request, exp_zone_name);
  457. // Verify the PREREQUISITE SECTION
  458. // Should be 2, 1 which tests for FQDN does exist and the other
  459. // checks for a matching DHCID.
  460. dns::RRsetPtr rrset;
  461. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 2);
  462. // Verify the FQDN test RR.
  463. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  464. SECTION_PREREQUISITE, 0));
  465. checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(), 0, ncr);
  466. // Verify the DHCID test RR.
  467. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  468. SECTION_PREREQUISITE, 1));
  469. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(), 0, ncr);
  470. // Verify the UPDATE SECTION
  471. // Should be 2, 1 which deletes the existing FQDN/IP and one that
  472. // adds the new one.
  473. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 2);
  474. // Fetch ttl.
  475. uint32_t ttl = ncr->getLeaseLength();
  476. // Verify the FQDN delete RR.
  477. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  478. SECTION_UPDATE, 0));
  479. checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), exp_ip_rr_type, 0, ncr);
  480. // Verify the FQDN/IP add RR.
  481. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  482. SECTION_UPDATE, 1));
  483. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), exp_ip_rr_type, ttl, ncr);
  484. // Verify there are no RRs in the ADDITIONAL Section.
  485. checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0);
  486. // Verify that it will render toWire without throwing.
  487. dns::MessageRenderer renderer;
  488. ASSERT_NO_THROW(request->toWire(renderer));
  489. }
  490. // Verifies that the contents of the given transaction's DNS update request
  491. // is correct for replacing a reverse DNS entry
  492. void checkReplaceRevPtrsRequest(NameChangeTransaction& tran) {
  493. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  494. ASSERT_TRUE(request);
  495. // Safety check.
  496. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  497. ASSERT_TRUE(ncr);
  498. std::string exp_zone_name = tran.getReverseDomain()->getName();
  499. std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress());
  500. // Verify the zone section.
  501. checkZone(request, exp_zone_name);
  502. // Verify there are no RRs in the PREREQUISITE Section.
  503. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 0);
  504. // Fetch ttl.
  505. uint32_t ttl = ncr->getLeaseLength();
  506. // Verify the UPDATE Section.
  507. // It should contain 4 RRs:
  508. // 1. A delete all PTR RRs for the given IP
  509. // 2. A delete of all DHCID RRs for the given IP
  510. // 3. An add of the new PTR RR
  511. // 4. An add of the new DHCID RR
  512. dns::RRsetPtr rrset;
  513. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 4);
  514. // Verify the PTR delete RR.
  515. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  516. SECTION_UPDATE, 0));
  517. checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::PTR(),
  518. 0, ncr);
  519. // Verify the DHCID delete RR.
  520. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  521. SECTION_UPDATE, 1));
  522. checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::DHCID(),
  523. 0, ncr);
  524. // Verify the PTR add RR.
  525. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  526. SECTION_UPDATE, 2));
  527. checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
  528. ttl, ncr);
  529. // Verify the DHCID add RR.
  530. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  531. SECTION_UPDATE, 3));
  532. checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::DHCID(),
  533. ttl, ncr);
  534. // Verify there are no RRs in the ADDITIONAL Section.
  535. checkRRCount(request, D2UpdateMessage::SECTION_ADDITIONAL, 0);
  536. // Verify that it will render toWire without throwing.
  537. dns::MessageRenderer renderer;
  538. ASSERT_NO_THROW(request->toWire(renderer));
  539. }
  540. void checkRemoveFwdAddressRequest(NameChangeTransaction& tran) {
  541. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  542. ASSERT_TRUE(request);
  543. // Safety check.
  544. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  545. ASSERT_TRUE(ncr);
  546. std::string exp_zone_name = tran.getForwardDomain()->getName();
  547. std::string exp_fqdn = ncr->getFqdn();
  548. // Verify the zone section.
  549. checkZone(request, exp_zone_name);
  550. // Verify there is 1 RR in the PREREQUISITE Section.
  551. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
  552. // Verify the DHCID matching assertion RR.
  553. dns::RRsetPtr rrset;
  554. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  555. SECTION_PREREQUISITE, 0));
  556. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
  557. 0, ncr);
  558. // Verify there is 1 RR in the UPDATE Section.
  559. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
  560. // Verify the FQDN/IP delete RR.
  561. const dns::RRType& exp_ip_rr_type = tran.getAddressRRType();
  562. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  563. SECTION_UPDATE, 0));
  564. checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), exp_ip_rr_type,
  565. 0, ncr);
  566. // Verify that it will render toWire without throwing.
  567. dns::MessageRenderer renderer;
  568. ASSERT_NO_THROW(request->toWire(renderer));
  569. }
  570. void checkRemoveFwdRRsRequest(NameChangeTransaction& tran) {
  571. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  572. ASSERT_TRUE(request);
  573. // Safety check.
  574. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  575. ASSERT_TRUE(ncr);
  576. std::string exp_zone_name = tran.getForwardDomain()->getName();
  577. std::string exp_fqdn = ncr->getFqdn();
  578. // Verify the zone section.
  579. checkZone(request, exp_zone_name);
  580. // Verify there is 1 RR in the PREREQUISITE Section.
  581. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 3);
  582. // Verify the DHCID matches assertion.
  583. dns::RRsetPtr rrset;
  584. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  585. SECTION_PREREQUISITE, 0));
  586. checkRR(rrset, exp_fqdn, dns::RRClass::IN(), dns::RRType::DHCID(),
  587. 0, ncr);
  588. // Verify the NO A RRs assertion.
  589. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  590. SECTION_PREREQUISITE, 1));
  591. checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::A(),
  592. 0, ncr, NO_RDATA);
  593. // Verify the NO AAAA RRs assertion.
  594. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  595. SECTION_PREREQUISITE, 2));
  596. checkRR(rrset, exp_fqdn, dns::RRClass::NONE(), dns::RRType::AAAA(),
  597. 0, ncr, NO_RDATA);
  598. // Verify there is 1 RR in the UPDATE Section.
  599. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
  600. // Verify the delete all for the FQDN RR.
  601. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  602. SECTION_UPDATE, 0));
  603. checkRR(rrset, exp_fqdn, dns::RRClass::ANY(), dns::RRType::ANY(),
  604. 0, ncr);
  605. // Verify that it will render toWire without throwing.
  606. dns::MessageRenderer renderer;
  607. ASSERT_NO_THROW(request->toWire(renderer));
  608. }
  609. void checkRemoveRevPtrsRequest(NameChangeTransaction& tran) {
  610. const D2UpdateMessagePtr& request = tran.getDnsUpdateRequest();
  611. ASSERT_TRUE(request);
  612. // Safety check.
  613. dhcp_ddns::NameChangeRequestPtr ncr = tran.getNcr();
  614. ASSERT_TRUE(ncr);
  615. std::string exp_zone_name = tran.getReverseDomain()->getName();
  616. std::string exp_rev_addr = D2CfgMgr::reverseIpAddress(ncr->getIpAddress());
  617. // Verify the zone section.
  618. checkZone(request, exp_zone_name);
  619. // Verify there is 1 RR in the PREREQUISITE Section.
  620. checkRRCount(request, D2UpdateMessage::SECTION_PREREQUISITE, 1);
  621. // Verify the FQDN-PTRNAME assertion RR.
  622. dns::RRsetPtr rrset;
  623. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  624. SECTION_PREREQUISITE, 0));
  625. checkRR(rrset, exp_rev_addr, dns::RRClass::IN(), dns::RRType::PTR(),
  626. 0, ncr);
  627. // Verify there is 1 RR in the UPDATE Section.
  628. checkRRCount(request, D2UpdateMessage::SECTION_UPDATE, 1);
  629. // Verify the delete all for the FQDN RR.
  630. ASSERT_TRUE(rrset = getRRFromSection(request, D2UpdateMessage::
  631. SECTION_UPDATE, 0));
  632. checkRR(rrset, exp_rev_addr, dns::RRClass::ANY(), dns::RRType::ANY(),
  633. 0, ncr);
  634. // Verify that it will render toWire without throwing.
  635. dns::MessageRenderer renderer;
  636. ASSERT_NO_THROW(request->toWire(renderer));
  637. }
  638. std::string toHexText(const uint8_t* data, size_t len) {
  639. std::ostringstream stream;
  640. stream << "Data length is: " << len << std::endl;
  641. for (int i = 0; i < len; ++i) {
  642. if (i > 0 && ((i % 16) == 0)) {
  643. stream << std::endl;
  644. }
  645. stream << setfill('0') << setw(2) << setbase(16)
  646. << static_cast<unsigned int>(data[i]) << " ";
  647. }
  648. return (stream.str());
  649. }
  650. }; // namespace isc::d2
  651. }; // namespace isc