fqdn_unittest.cc 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. // Copyright (C) 2013-2014 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 <asiolink/io_address.h>
  16. #include <dhcp/option4_client_fqdn.h>
  17. #include <dhcp/option_int_array.h>
  18. #include <dhcp/tests/iface_mgr_test_config.h>
  19. #include <dhcp4/tests/dhcp4_test_utils.h>
  20. #include <dhcp_ddns/ncr_msg.h>
  21. #include <dhcpsrv/cfgmgr.h>
  22. #include <gtest/gtest.h>
  23. #include <boost/scoped_ptr.hpp>
  24. using namespace isc;
  25. using namespace isc::asiolink;
  26. using namespace isc::dhcp;
  27. using namespace isc::dhcp::test;
  28. using namespace isc::dhcp_ddns;
  29. namespace {
  30. class NameDhcpv4SrvTest : public Dhcpv4SrvTest {
  31. public:
  32. // Reference to D2ClientMgr singleton
  33. D2ClientMgr& d2_mgr_;
  34. // Bit Constants for turning on and off DDNS configuration options.
  35. static const uint16_t ALWAYS_INCLUDE_FQDN = 1;
  36. static const uint16_t OVERRIDE_NO_UPDATE = 2;
  37. static const uint16_t OVERRIDE_CLIENT_UPDATE = 4;
  38. static const uint16_t REPLACE_CLIENT_NAME = 8;
  39. NameDhcpv4SrvTest() : Dhcpv4SrvTest(),
  40. d2_mgr_(CfgMgr::instance().getD2ClientMgr()) {
  41. srv_ = new NakedDhcpv4Srv(0);
  42. // Config DDNS to be enabled, all controls off
  43. enableD2();
  44. }
  45. virtual ~NameDhcpv4SrvTest() {
  46. delete srv_;
  47. // CfgMgr singleton doesn't get wiped between tests, so we'll
  48. // disable D2 explictly between tests.
  49. disableD2();
  50. }
  51. /// @brief Sets the server's DDNS configuration to ddns updates disabled.
  52. void disableD2() {
  53. // Default constructor creates a config with DHCP-DDNS updates
  54. // disabled.
  55. D2ClientConfigPtr cfg(new D2ClientConfig());
  56. CfgMgr::instance().setD2ClientConfig(cfg);
  57. }
  58. /// @brief Enables DHCP-DDNS updates with the given options enabled.
  59. ///
  60. /// Replaces the current D2ClientConfiguration with a configuration
  61. /// which as updates enabled and the control options set based upon
  62. /// the bit mask of options.
  63. ///
  64. /// @param mask Bit mask of configuration options that should be enabled.
  65. void enableD2(const uint16_t mask = 0) {
  66. D2ClientConfigPtr cfg;
  67. ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
  68. isc::asiolink::IOAddress("127.0.0.1"), 53001,
  69. dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
  70. (mask & ALWAYS_INCLUDE_FQDN),
  71. (mask & OVERRIDE_NO_UPDATE),
  72. (mask & OVERRIDE_CLIENT_UPDATE),
  73. (mask & REPLACE_CLIENT_NAME),
  74. "myhost", "example.com")));
  75. ASSERT_NO_THROW(CfgMgr::instance().setD2ClientConfig(cfg));
  76. ASSERT_NO_THROW(srv_->startD2());
  77. }
  78. // Create a lease to be used by various tests.
  79. Lease4Ptr createLease(const isc::asiolink::IOAddress& addr,
  80. const std::string& hostname,
  81. const bool fqdn_fwd,
  82. const bool fqdn_rev) {
  83. const uint8_t hwaddr[] = { 0, 1, 2, 3, 4, 5, 6 };
  84. Lease4Ptr lease(new Lease4(addr, hwaddr, sizeof(hwaddr),
  85. &generateClientId()->getData()[0],
  86. generateClientId()->getData().size(),
  87. 100, 50, 75, time(NULL), subnet_->getID()));
  88. // @todo Set this through the Lease4 constructor.
  89. lease->hostname_ = hostname;
  90. lease->fqdn_fwd_ = fqdn_fwd;
  91. lease->fqdn_rev_ = fqdn_rev;
  92. return (lease);
  93. }
  94. // Create an instance of the DHCPv4 Client FQDN Option.
  95. Option4ClientFqdnPtr
  96. createClientFqdn(const uint8_t flags,
  97. const std::string& fqdn_name,
  98. Option4ClientFqdn::DomainNameType fqdn_type) {
  99. return (Option4ClientFqdnPtr(new Option4ClientFqdn(flags,
  100. Option4ClientFqdn::
  101. RCODE_CLIENT(),
  102. fqdn_name,
  103. fqdn_type)));
  104. }
  105. // Create an instance of the Hostname option.
  106. OptionCustomPtr
  107. createHostname(const std::string& hostname) {
  108. OptionDefinition def("hostname", DHO_HOST_NAME, "string");
  109. OptionCustomPtr opt_hostname(new OptionCustom(def, Option::V4));
  110. opt_hostname->writeString(hostname);
  111. return (opt_hostname);
  112. }
  113. /// @brief Convenience method for generating an FQDN from an IP address.
  114. ///
  115. /// This is just a wrapper method around the D2ClientMgr's method for
  116. /// generating domain names from the configured prefix, suffix, and a
  117. /// given IP address. This is useful for verifying that fully generated
  118. /// names are correct.
  119. ///
  120. /// @param addr IP address used in the lease.
  121. ///
  122. /// @return An std::string contained the generated FQDN.
  123. std::string generatedNameFromAddress(const IOAddress& addr) {
  124. return(CfgMgr::instance().getD2ClientMgr().generateFqdn(addr));
  125. }
  126. // Get the Client FQDN Option from the given message.
  127. Option4ClientFqdnPtr getClientFqdnOption(const Pkt4Ptr& pkt) {
  128. return (boost::dynamic_pointer_cast<
  129. Option4ClientFqdn>(pkt->getOption(DHO_FQDN)));
  130. }
  131. // get the Hostname option from the given message.
  132. OptionCustomPtr getHostnameOption(const Pkt4Ptr& pkt) {
  133. return (boost::dynamic_pointer_cast<
  134. OptionCustom>(pkt->getOption(DHO_HOST_NAME)));
  135. }
  136. // Create a message holding DHCPv4 Client FQDN Option.
  137. Pkt4Ptr generatePktWithFqdn(const uint8_t msg_type,
  138. const uint8_t fqdn_flags,
  139. const std::string& fqdn_domain_name,
  140. Option4ClientFqdn::DomainNameType fqdn_type,
  141. const bool include_prl,
  142. const bool include_clientid = true) {
  143. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(msg_type, 1234));
  144. pkt->setRemoteAddr(IOAddress("192.0.2.3"));
  145. pkt->setIface("eth1");
  146. // For DISCOVER we don't include server id, because client broadcasts
  147. // the message to all servers.
  148. if (msg_type != DHCPDISCOVER) {
  149. pkt->addOption(srv_->getServerID());
  150. }
  151. if (include_clientid) {
  152. pkt->addOption(generateClientId());
  153. }
  154. // Create Client FQDN Option with the specified flags and
  155. // domain-name.
  156. pkt->addOption(createClientFqdn(fqdn_flags, fqdn_domain_name,
  157. fqdn_type));
  158. // Control whether or not to request that server returns the FQDN
  159. // option. Server may be configured to always return it or return
  160. // only in case client requested it.
  161. if (include_prl) {
  162. OptionUint8ArrayPtr option_prl =
  163. OptionUint8ArrayPtr(new OptionUint8Array(Option::V4,
  164. DHO_DHCP_PARAMETER_REQUEST_LIST));
  165. option_prl->addValue(DHO_FQDN);
  166. }
  167. return (pkt);
  168. }
  169. // Create a message holding a Hostname option.
  170. Pkt4Ptr generatePktWithHostname(const uint8_t msg_type,
  171. const std::string& hostname) {
  172. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(msg_type, 1234));
  173. pkt->setRemoteAddr(IOAddress("192.0.2.3"));
  174. // For DISCOVER we don't include server id, because client broadcasts
  175. // the message to all servers.
  176. if (msg_type != DHCPDISCOVER) {
  177. pkt->addOption(srv_->getServerID());
  178. }
  179. pkt->addOption(generateClientId());
  180. // Create Client FQDN Option with the specified flags and
  181. // domain-name.
  182. pkt->addOption(createHostname(hostname));
  183. return (pkt);
  184. }
  185. // Test that server generates the appropriate FQDN option in response to
  186. // client's FQDN option.
  187. void testProcessFqdn(const Pkt4Ptr& query, const uint8_t exp_flags,
  188. const std::string& exp_domain_name,
  189. Option4ClientFqdn::DomainNameType
  190. exp_domain_type = Option4ClientFqdn::FULL) {
  191. ASSERT_TRUE(getClientFqdnOption(query));
  192. Pkt4Ptr answer;
  193. if (query->getType() == DHCPDISCOVER) {
  194. answer.reset(new Pkt4(DHCPOFFER, 1234));
  195. } else {
  196. answer.reset(new Pkt4(DHCPACK, 1234));
  197. }
  198. ASSERT_NO_THROW(srv_->processClientName(query, answer));
  199. Option4ClientFqdnPtr fqdn = getClientFqdnOption(answer);
  200. ASSERT_TRUE(fqdn);
  201. checkFqdnFlags(answer, exp_flags);
  202. EXPECT_EQ(exp_domain_name, fqdn->getDomainName());
  203. EXPECT_EQ(exp_domain_type, fqdn->getDomainNameType());
  204. }
  205. /// @brief Checks the packet's FQDN option flags against a given mask
  206. ///
  207. /// @param pkt IPv4 packet whose FQDN flags should be checked.
  208. /// @param exp_flags Bit mask of flags that are expected to be true.
  209. void checkFqdnFlags(const Pkt4Ptr& pkt, const uint8_t exp_flags) {
  210. Option4ClientFqdnPtr fqdn = getClientFqdnOption(pkt);
  211. ASSERT_TRUE(fqdn);
  212. const bool flag_n = (exp_flags & Option4ClientFqdn::FLAG_N) != 0;
  213. const bool flag_s = (exp_flags & Option4ClientFqdn::FLAG_S) != 0;
  214. const bool flag_o = (exp_flags & Option4ClientFqdn::FLAG_O) != 0;
  215. const bool flag_e = (exp_flags & Option4ClientFqdn::FLAG_E) != 0;
  216. EXPECT_EQ(flag_n, fqdn->getFlag(Option4ClientFqdn::FLAG_N));
  217. EXPECT_EQ(flag_s, fqdn->getFlag(Option4ClientFqdn::FLAG_S));
  218. EXPECT_EQ(flag_o, fqdn->getFlag(Option4ClientFqdn::FLAG_O));
  219. EXPECT_EQ(flag_e, fqdn->getFlag(Option4ClientFqdn::FLAG_E));
  220. }
  221. // Processes the Hostname option in the client's message and returns
  222. // the hostname option which would be sent to the client. It will
  223. // throw NULL pointer if the hostname option is not to be included
  224. // in the response.
  225. OptionCustomPtr processHostname(const Pkt4Ptr& query) {
  226. if (!getHostnameOption(query)) {
  227. ADD_FAILURE() << "Hostname option not carried in the query";
  228. }
  229. Pkt4Ptr answer;
  230. if (query->getType() == DHCPDISCOVER) {
  231. answer.reset(new Pkt4(DHCPOFFER, 1234));
  232. } else {
  233. answer.reset(new Pkt4(DHCPACK, 1234));
  234. }
  235. srv_->processClientName(query, answer);
  236. OptionCustomPtr hostname = getHostnameOption(answer);
  237. return (hostname);
  238. }
  239. // Test that the client message holding an FQDN is processed and
  240. // that the response packet is as expected.
  241. void testProcessMessageWithFqdn(const uint8_t msg_type,
  242. const std::string& hostname) {
  243. Pkt4Ptr req = generatePktWithFqdn(msg_type, Option4ClientFqdn::FLAG_S |
  244. Option4ClientFqdn::FLAG_E, hostname,
  245. Option4ClientFqdn::FULL, true);
  246. Pkt4Ptr reply;
  247. if (msg_type == DHCPDISCOVER) {
  248. ASSERT_NO_THROW(reply = srv_->processDiscover(req));
  249. } else if (msg_type == DHCPREQUEST) {
  250. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  251. } else if (msg_type == DHCPRELEASE) {
  252. ASSERT_NO_THROW(srv_->processRelease(req));
  253. return;
  254. } else {
  255. return;
  256. }
  257. if (msg_type == DHCPDISCOVER) {
  258. checkResponse(reply, DHCPOFFER, 1234);
  259. } else {
  260. checkResponse(reply, DHCPACK, 1234);
  261. }
  262. }
  263. // Verify that NameChangeRequest holds valid values.
  264. void verifyNameChangeRequest(const isc::dhcp_ddns::NameChangeType type,
  265. const bool reverse, const bool forward,
  266. const std::string& addr,
  267. const std::string& fqdn,
  268. const std::string& dhcid,
  269. const time_t cltt,
  270. const uint16_t len,
  271. const bool not_strict_expire_check = false) {
  272. NameChangeRequestPtr ncr;
  273. ASSERT_NO_THROW(ncr = d2_mgr_.peekAt(0));
  274. ASSERT_TRUE(ncr);
  275. EXPECT_EQ(type, ncr->getChangeType());
  276. EXPECT_EQ(forward, ncr->isForwardChange());
  277. EXPECT_EQ(reverse, ncr->isReverseChange());
  278. EXPECT_EQ(addr, ncr->getIpAddress());
  279. EXPECT_EQ(fqdn, ncr->getFqdn());
  280. // Compare dhcid if it is not empty. In some cases, the DHCID is
  281. // not known in advance and can't be compared.
  282. if (!dhcid.empty()) {
  283. EXPECT_EQ(dhcid, ncr->getDhcid().toStr());
  284. }
  285. // In some cases, the test doesn't have access to the last transmission
  286. // time for the particular client. In such cases, the test can use the
  287. // current time as cltt but the it may not check the lease expiration time
  288. // for equality but rather check that the lease expiration time is not
  289. // greater than the current time + lease lifetime.
  290. if (not_strict_expire_check) {
  291. EXPECT_GE(cltt + len, ncr->getLeaseExpiresOn());
  292. } else {
  293. EXPECT_EQ(cltt + len, ncr->getLeaseExpiresOn());
  294. }
  295. EXPECT_EQ(len, ncr->getLeaseLength());
  296. EXPECT_EQ(isc::dhcp_ddns::ST_NEW, ncr->getStatus());
  297. // Process the message off the queue
  298. ASSERT_NO_THROW(d2_mgr_.runReadyIO());
  299. }
  300. /// @brief Tests processing a request with the given client flags
  301. ///
  302. /// This method creates a request with its FQDN flags set to the given
  303. /// value and submits it to the server for processing. It then checks
  304. /// the following:
  305. /// 1. Did the server generate an ACK with the correct FQDN flags
  306. /// 2. If the server should have generated an NCR, did it? and If
  307. /// so was it correct?
  308. ///
  309. /// @param client_flags Mask of client FQDN flags which are true
  310. /// @param response_flags Mask of expected FQDN flags in the response
  311. void flagVsConfigScenario(const uint8_t client_flags,
  312. const uint8_t response_flags) {
  313. // Create fake interfaces and open fake sockets.
  314. IfaceMgrTestConfig iface_config(true);
  315. IfaceMgr::instance().openSockets4();
  316. Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, client_flags,
  317. "myhost.example.com.",
  318. Option4ClientFqdn::FULL, true);
  319. // Process the request.
  320. Pkt4Ptr reply;
  321. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  322. // Verify the response and flags.
  323. checkResponse(reply, DHCPACK, 1234);
  324. checkFqdnFlags(reply, response_flags);
  325. // NCRs cannot be sent to the d2_mgr unless updates are enabled.
  326. if (d2_mgr_.ddnsEnabled()) {
  327. // There should be an NCR only if response S flag is 1.
  328. /// @todo This logic will need to change if forward and reverse
  329. /// updates are ever controlled independently.
  330. if ((response_flags & Option4ClientFqdn::FLAG_S) == 0) {
  331. ASSERT_EQ(0, d2_mgr_.getQueueSize());
  332. } else {
  333. // Verify that there is one NameChangeRequest as expected.
  334. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  335. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  336. reply->getYiaddr().toText(),
  337. "myhost.example.com.",
  338. "", // empty DHCID means don't check it
  339. time(NULL) + subnet_->getValid(),
  340. subnet_->getValid(), true);
  341. }
  342. }
  343. }
  344. NakedDhcpv4Srv* srv_;
  345. };
  346. // Test that the exception is thrown if lease pointer specified as the argument
  347. // of computeDhcid function is NULL.
  348. TEST_F(NameDhcpv4SrvTest, dhcidNullLease) {
  349. Lease4Ptr lease;
  350. EXPECT_THROW(srv_->computeDhcid(lease), isc::dhcp::DhcidComputeError);
  351. }
  352. // Test that the appropriate exception is thrown if the lease object used
  353. // to compute DHCID comprises wrong hostname.
  354. TEST_F(NameDhcpv4SrvTest, dhcidWrongHostname) {
  355. // First, make sure that the lease with the correct hostname is accepted.
  356. Lease4Ptr lease = createLease(IOAddress("192.0.2.3"),
  357. "myhost.example.com.", true, true);
  358. ASSERT_NO_THROW(srv_->computeDhcid(lease));
  359. // Now, use the wrong hostname. It should result in the exception.
  360. lease->hostname_ = "myhost...example.com.";
  361. EXPECT_THROW(srv_->computeDhcid(lease), isc::dhcp::DhcidComputeError);
  362. // Also, empty hostname is wrong.
  363. lease->hostname_ = "";
  364. EXPECT_THROW(srv_->computeDhcid(lease), isc::dhcp::DhcidComputeError);
  365. }
  366. // Test that the DHCID is computed correctly, when the lease holds
  367. // correct hostname and non-NULL client id.
  368. TEST_F(NameDhcpv4SrvTest, dhcidComputeFromClientId) {
  369. Lease4Ptr lease = createLease(IOAddress("192.0.2.3"),
  370. "myhost.example.com.",
  371. true, true);
  372. isc::dhcp_ddns::D2Dhcid dhcid;
  373. ASSERT_NO_THROW(dhcid = srv_->computeDhcid(lease));
  374. // Make sure that the computed DHCID is valid.
  375. std::string dhcid_ref = "00010132E91AA355CFBB753C0F0497A5A9404"
  376. "36965B68B6D438D98E680BF10B09F3BCF";
  377. EXPECT_EQ(dhcid_ref, dhcid.toStr());
  378. }
  379. // Test that the DHCID is computed correctly, when the lease holds correct
  380. // hostname and NULL client id.
  381. TEST_F(NameDhcpv4SrvTest, dhcidComputeFromHWAddr) {
  382. Lease4Ptr lease = createLease(IOAddress("192.0.2.3"),
  383. "myhost.example.com.",
  384. true, true);
  385. lease->client_id_.reset();
  386. isc::dhcp_ddns::D2Dhcid dhcid;
  387. ASSERT_NO_THROW(dhcid = srv_->computeDhcid(lease));
  388. // Make sure that the computed DHCID is valid.
  389. std::string dhcid_ref = "0000012247F6DC4423C3E8627434A9D6868609"
  390. "D88948F78018B215EDCAA30C0C135035";
  391. EXPECT_EQ(dhcid_ref, dhcid.toStr());
  392. }
  393. // Tests the following scenario:
  394. // - Updates are enabled
  395. // - All overrides are off
  396. // - Client requests forward update (N = 0, S = 1)
  397. //
  398. // Server should perform the update:
  399. // - Reponse flags should N = 0, S = 1, O = 0
  400. // - Should queue an NCR
  401. TEST_F(NameDhcpv4SrvTest, updatesEnabled) {
  402. flagVsConfigScenario((Option4ClientFqdn::FLAG_E |
  403. Option4ClientFqdn::FLAG_S),
  404. (Option4ClientFqdn::FLAG_E |
  405. Option4ClientFqdn::FLAG_S));
  406. }
  407. // Tests the following scenario
  408. // - Updates are disabled
  409. // - Client requests forward update (N = 0, S = 1)
  410. //
  411. // Server should NOT perform updates:
  412. // - Response flags should N = 1, S = 0, O = 1
  413. // - Should not queue any NCRs
  414. TEST_F(NameDhcpv4SrvTest, updatesDisabled) {
  415. disableD2();
  416. flagVsConfigScenario((Option4ClientFqdn::FLAG_E |
  417. Option4ClientFqdn::FLAG_S),
  418. (Option4ClientFqdn::FLAG_E |
  419. Option4ClientFqdn::FLAG_N |
  420. Option4ClientFqdn::FLAG_O));
  421. }
  422. // Tests the following scenario:
  423. // - Updates are enabled
  424. // - All overrides are off.
  425. // - Client requests no updates (N = 1, S = 0)
  426. //
  427. // Server should NOT perform updates:
  428. // - Response flags should N = 1, S = 0, O = 0
  429. // - Should not queue any NCRs
  430. TEST_F(NameDhcpv4SrvTest, respectNoUpdate) {
  431. flagVsConfigScenario((Option4ClientFqdn::FLAG_E |
  432. Option4ClientFqdn::FLAG_N),
  433. (Option4ClientFqdn::FLAG_E |
  434. Option4ClientFqdn::FLAG_N));
  435. }
  436. // Tests the following scenario:
  437. // - Updates are enabled
  438. // - override-no-update is on
  439. // - Client requests no updates (N = 1, S = 0)
  440. //
  441. // Server should override "no update" request and perform updates:
  442. // - Response flags should be N = 0, S = 1, O = 1
  443. // - Should queue an NCR
  444. TEST_F(NameDhcpv4SrvTest, overrideNoUpdate) {
  445. enableD2(OVERRIDE_NO_UPDATE);
  446. flagVsConfigScenario((Option4ClientFqdn::FLAG_E |
  447. Option4ClientFqdn::FLAG_N),
  448. (Option4ClientFqdn::FLAG_E |
  449. Option4ClientFqdn::FLAG_S |
  450. Option4ClientFqdn::FLAG_O));
  451. }
  452. // Tests the following scenario:
  453. // - Updates are enabled
  454. // - All overrides are off.
  455. // - Client requests delegation (N = 0, S = 0)
  456. //
  457. // Server should respect client's delegation request and NOT do updates:
  458. // - Response flags should be N = 1, S = 0, O = 0
  459. // - Should not queue any NCRs
  460. TEST_F(NameDhcpv4SrvTest, respectClientDelegation) {
  461. flagVsConfigScenario(Option4ClientFqdn::FLAG_E,
  462. (Option4ClientFqdn::FLAG_E |
  463. Option4ClientFqdn::FLAG_N));
  464. }
  465. // Tests the following scenario:
  466. // - Updates are enabled
  467. // - override-client-update is on.
  468. // - Client requests delegation (N = 0, S = 0)
  469. //
  470. // Server should override client's delegation request and do updates:
  471. // - Response flags should be N = 0, S = 1, O = 1
  472. // - Should queue an NCR
  473. TEST_F(NameDhcpv4SrvTest, overrideClientDelegation) {
  474. // Turn on override-client-update.
  475. enableD2(OVERRIDE_CLIENT_UPDATE);
  476. flagVsConfigScenario(Option4ClientFqdn::FLAG_E,
  477. (Option4ClientFqdn::FLAG_E |
  478. Option4ClientFqdn::FLAG_S |
  479. Option4ClientFqdn::FLAG_O));
  480. }
  481. // Test that server processes the Hostname option sent by a client and
  482. // responds with the Hostname option to confirm that the server has
  483. // taken responsibility for the update.
  484. TEST_F(NameDhcpv4SrvTest, serverUpdateHostname) {
  485. Pkt4Ptr query;
  486. ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST,
  487. "myhost.example.com."));
  488. OptionCustomPtr hostname;
  489. ASSERT_NO_THROW(hostname = processHostname(query));
  490. ASSERT_TRUE(hostname);
  491. EXPECT_EQ("myhost.example.com.", hostname->readString());
  492. }
  493. // Test that the server skips processing of the empty Hostname option.
  494. TEST_F(NameDhcpv4SrvTest, serverUpdateEmptyHostname) {
  495. Pkt4Ptr query;
  496. ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, ""));
  497. OptionCustomPtr hostname;
  498. ASSERT_NO_THROW(hostname = processHostname(query));
  499. EXPECT_FALSE(hostname);
  500. }
  501. // Test that the server skips processing of a wrong Hostname option.
  502. TEST_F(NameDhcpv4SrvTest, serverUpdateWrongHostname) {
  503. Pkt4Ptr query;
  504. ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST,
  505. "abc..example.com"));
  506. OptionCustomPtr hostname;
  507. ASSERT_NO_THROW(hostname = processHostname(query));
  508. EXPECT_FALSE(hostname);
  509. }
  510. // Test that server generates the fully qualified domain name for the client
  511. // if client supplies the partial name.
  512. TEST_F(NameDhcpv4SrvTest, serverUpdateForwardPartialNameFqdn) {
  513. Pkt4Ptr query = generatePktWithFqdn(DHCPREQUEST,
  514. Option4ClientFqdn::FLAG_E |
  515. Option4ClientFqdn::FLAG_S,
  516. "myhost",
  517. Option4ClientFqdn::PARTIAL,
  518. true);
  519. testProcessFqdn(query,
  520. Option4ClientFqdn::FLAG_E | Option4ClientFqdn::FLAG_S,
  521. "myhost.example.com.");
  522. }
  523. // Test that server generates the fully qualified domain name for the client
  524. // if client supplies the unqualified name in the Hostname option.
  525. TEST_F(NameDhcpv4SrvTest, serverUpdateUnqualifiedHostname) {
  526. Pkt4Ptr query;
  527. ASSERT_NO_THROW(query = generatePktWithHostname(DHCPREQUEST, "myhost"));
  528. OptionCustomPtr hostname;
  529. ASSERT_NO_THROW(hostname = processHostname(query));
  530. ASSERT_TRUE(hostname);
  531. EXPECT_EQ("myhost.example.com.", hostname->readString());
  532. }
  533. // Test that server sets empty domain-name in the FQDN option when client
  534. // supplied no domain-name. The domain-name is supposed to be set after the
  535. // lease is acquired. The domain-name is then generated from the IP address
  536. // assigned to a client.
  537. TEST_F(NameDhcpv4SrvTest, serverUpdateForwardNoNameFqdn) {
  538. Pkt4Ptr query = generatePktWithFqdn(DHCPREQUEST,
  539. Option4ClientFqdn::FLAG_E |
  540. Option4ClientFqdn::FLAG_S,
  541. "",
  542. Option4ClientFqdn::PARTIAL,
  543. true);
  544. testProcessFqdn(query,
  545. Option4ClientFqdn::FLAG_E | Option4ClientFqdn::FLAG_S,
  546. "", Option4ClientFqdn::PARTIAL);
  547. }
  548. // Test that exactly one NameChangeRequest is generated when the new lease
  549. // has been acquired (old lease is NULL).
  550. TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsNewLease) {
  551. Lease4Ptr lease = createLease(IOAddress("192.0.2.3"), "myhost.example.com.",
  552. true, true);
  553. Lease4Ptr old_lease;
  554. ASSERT_NO_THROW(srv_->createNameChangeRequests(lease, old_lease));
  555. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  556. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  557. "192.0.2.3", "myhost.example.com.",
  558. "00010132E91AA355CFBB753C0F0497A5A940436965"
  559. "B68B6D438D98E680BF10B09F3BCF",
  560. lease->cltt_, 100);
  561. }
  562. // Test that no NameChangeRequest is generated when a lease is renewed and
  563. // the FQDN data hasn't changed.
  564. TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsRenewNoChange) {
  565. Lease4Ptr lease = createLease(IOAddress("192.0.2.3"), "myhost.example.com.",
  566. true, true);
  567. Lease4Ptr old_lease = createLease(IOAddress("192.0.2.3"),
  568. "myhost.example.com.", true, true);
  569. old_lease->valid_lft_ += 100;
  570. ASSERT_NO_THROW(srv_->createNameChangeRequests(lease, old_lease));
  571. ASSERT_EQ(0, d2_mgr_.getQueueSize());
  572. }
  573. // Test that no NameChangeRequest is generated when forward and reverse
  574. // DNS update flags are not set in the lease.
  575. TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsNoUpdate) {
  576. Lease4Ptr lease1 = createLease(IOAddress("192.0.2.3"),
  577. "lease1.example.com.",
  578. true, true);
  579. Lease4Ptr lease2 = createLease(IOAddress("192.0.2.3"),
  580. "lease2.example.com.",
  581. false, false);
  582. ASSERT_NO_THROW(srv_->createNameChangeRequests(lease2, lease1));
  583. EXPECT_EQ(1, d2_mgr_.getQueueSize());
  584. verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
  585. "192.0.2.3", "lease1.example.com.",
  586. "0001013A5B311F5B9FB10DDF8E53689B874F25D"
  587. "62CC147C2FF237A64C90E5A597C9B7A",
  588. lease1->cltt_, 100);
  589. lease2->hostname_ = "";
  590. lease2->fqdn_rev_ = true;
  591. lease2->fqdn_fwd_ = true;
  592. ASSERT_NO_THROW(srv_->createNameChangeRequests(lease2, lease1));
  593. EXPECT_EQ(1, d2_mgr_.getQueueSize());
  594. }
  595. // Test that two NameChangeRequests are generated when the lease is being
  596. // renewed and the new lease has updated FQDN data.
  597. TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsRenew) {
  598. Lease4Ptr lease1 = createLease(IOAddress("192.0.2.3"),
  599. "lease1.example.com.",
  600. true, true);
  601. Lease4Ptr lease2 = createLease(IOAddress("192.0.2.3"),
  602. "lease2.example.com.",
  603. true, true);
  604. ASSERT_NO_THROW(srv_->createNameChangeRequests(lease2, lease1));
  605. ASSERT_EQ(2, d2_mgr_.getQueueSize());
  606. verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
  607. "192.0.2.3", "lease1.example.com.",
  608. "0001013A5B311F5B9FB10DDF8E53689B874F25D"
  609. "62CC147C2FF237A64C90E5A597C9B7A",
  610. lease1->cltt_, 100);
  611. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  612. "192.0.2.3", "lease2.example.com.",
  613. "000101F906D2BB752E1B2EECC5FF2BF434C0B2D"
  614. "D6D7F7BD873F4F280165DB8C9DBA7CB",
  615. lease2->cltt_, 100);
  616. }
  617. // This test verifies that exception is thrown when leases passed to the
  618. // createNameChangeRequests function do not match, i.e. they comprise
  619. // different IP addresses, client ids etc.
  620. TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsLeaseMismatch) {
  621. Lease4Ptr lease1 = createLease(IOAddress("192.0.2.3"),
  622. "lease1.example.com.",
  623. true, true);
  624. Lease4Ptr lease2 = createLease(IOAddress("192.0.2.4"),
  625. "lease2.example.com.",
  626. true, true);
  627. EXPECT_THROW(srv_->createNameChangeRequests(lease2, lease1),
  628. isc::Unexpected);
  629. }
  630. // Test that the OFFER message generated as a result of the DISCOVER message
  631. // processing will not result in generation of the NameChangeRequests.
  632. TEST_F(NameDhcpv4SrvTest, processDiscover) {
  633. IfaceMgrTestConfig test_config(true);
  634. IfaceMgr::instance().openSockets4();
  635. Pkt4Ptr req = generatePktWithFqdn(DHCPDISCOVER, Option4ClientFqdn::FLAG_S |
  636. Option4ClientFqdn::FLAG_E,
  637. "myhost.example.com.",
  638. Option4ClientFqdn::FULL, true);
  639. Pkt4Ptr reply;
  640. ASSERT_NO_THROW(reply = srv_->processDiscover(req));
  641. checkResponse(reply, DHCPOFFER, 1234);
  642. EXPECT_EQ(0, d2_mgr_.getQueueSize());
  643. }
  644. // Test that server generates client's hostname from the IP address assigned
  645. // to it when DHCPv4 Client FQDN option specifies an empty domain-name.
  646. TEST_F(NameDhcpv4SrvTest, processRequestFqdnEmptyDomainName) {
  647. IfaceMgrTestConfig test_config(true);
  648. IfaceMgr::instance().openSockets4();
  649. Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  650. Option4ClientFqdn::FLAG_E,
  651. "", Option4ClientFqdn::PARTIAL, true);
  652. Pkt4Ptr reply;
  653. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  654. checkResponse(reply, DHCPACK, 1234);
  655. // Verify that there is one NameChangeRequest generated.
  656. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  657. // The hostname is generated from the IP address acquired (yiaddr).
  658. std::string hostname = generatedNameFromAddress(reply->getYiaddr());
  659. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  660. reply->getYiaddr().toText(), hostname,
  661. "", // empty DHCID forces that it is not checked
  662. time(NULL) + subnet_->getValid(),
  663. subnet_->getValid(), true);
  664. }
  665. // Test that server generates client's hostname from the IP address assigned
  666. // to it when DHCPv4 Client FQDN option specifies an empty domain-name AND
  667. // ddns updates are disabled.
  668. TEST_F(NameDhcpv4SrvTest, processRequestEmptyDomainNameDisabled) {
  669. // Create fake interfaces and open fake sockets.
  670. IfaceMgrTestConfig test_config(true);
  671. IfaceMgr::instance().openSockets4();
  672. disableD2();
  673. Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  674. Option4ClientFqdn::FLAG_E,
  675. "", Option4ClientFqdn::PARTIAL, true);
  676. Pkt4Ptr reply;
  677. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  678. checkResponse(reply, DHCPACK, 1234);
  679. Option4ClientFqdnPtr fqdn = getClientFqdnOption(reply);
  680. ASSERT_TRUE(fqdn);
  681. // The hostname is generated from the IP address acquired (yiaddr).
  682. std::string hostname = generatedNameFromAddress(reply->getYiaddr());
  683. EXPECT_EQ(hostname, fqdn->getDomainName());
  684. EXPECT_EQ(Option4ClientFqdn::FULL, fqdn->getDomainNameType());
  685. }
  686. // Test that server generates client's hostname from the IP address assigned
  687. // to it when Hostname option carries the top level domain-name.
  688. TEST_F(NameDhcpv4SrvTest, processRequestEmptyHostname) {
  689. IfaceMgrTestConfig test_config(true);
  690. IfaceMgr::instance().openSockets4();
  691. Pkt4Ptr req = generatePktWithHostname(DHCPREQUEST, ".");
  692. // Set interface for the incoming packet. The server requires it to
  693. // generate client id.
  694. req->setIface("eth1");
  695. Pkt4Ptr reply;
  696. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  697. checkResponse(reply, DHCPACK, 1234);
  698. // Verify that there is one NameChangeRequest generated.
  699. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  700. // The hostname is generated from the IP address acquired (yiaddr).
  701. std::string hostname = generatedNameFromAddress(reply->getYiaddr());
  702. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  703. reply->getYiaddr().toText(), hostname,
  704. "", // empty DHCID forces that it is not checked
  705. time(NULL), subnet_->getValid(), true);
  706. }
  707. // Test that client may send two requests, each carrying FQDN option with
  708. // a different domain-name. Server should use existing lease for the second
  709. // request but modify the DNS entries for the lease according to the contents
  710. // of the FQDN sent in the second request.
  711. TEST_F(NameDhcpv4SrvTest, processTwoRequestsFqdn) {
  712. IfaceMgrTestConfig test_config(true);
  713. IfaceMgr::instance().openSockets4();
  714. Pkt4Ptr req1 = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  715. Option4ClientFqdn::FLAG_E,
  716. "myhost.example.com.",
  717. Option4ClientFqdn::FULL, true);
  718. Pkt4Ptr reply;
  719. ASSERT_NO_THROW(reply = srv_->processRequest(req1));
  720. checkResponse(reply, DHCPACK, 1234);
  721. // Verify that there is one NameChangeRequest generated.
  722. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  723. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  724. reply->getYiaddr().toText(), "myhost.example.com.",
  725. "00010132E91AA355CFBB753C0F0497A5A940436"
  726. "965B68B6D438D98E680BF10B09F3BCF",
  727. time(NULL), subnet_->getValid(), true);
  728. // Create another Request message but with a different FQDN. Server
  729. // should generate two NameChangeRequests: one to remove existing entry,
  730. // another one to add new entry with updated domain-name.
  731. Pkt4Ptr req2 = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  732. Option4ClientFqdn::FLAG_E,
  733. "otherhost.example.com.",
  734. Option4ClientFqdn::FULL, true);
  735. ASSERT_NO_THROW(reply = srv_->processRequest(req2));
  736. checkResponse(reply, DHCPACK, 1234);
  737. // There should be two NameChangeRequests. Verify that they are valid.
  738. ASSERT_EQ(2, d2_mgr_.getQueueSize());
  739. verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
  740. reply->getYiaddr().toText(),
  741. "myhost.example.com.",
  742. "00010132E91AA355CFBB753C0F0497A5A940436"
  743. "965B68B6D438D98E680BF10B09F3BCF",
  744. time(NULL), subnet_->getValid(), true);
  745. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  746. reply->getYiaddr().toText(),
  747. "otherhost.example.com.",
  748. "000101A5AEEA7498BD5AD9D3BF600E49FF39A7E3"
  749. "AFDCE8C3D0E53F35CC584DD63C89CA",
  750. time(NULL), subnet_->getValid(), true);
  751. }
  752. // Test that client may send two requests, each carrying Hostname option with
  753. // a different name. Server should use existing lease for the second request
  754. // but modify the DNS entries for the lease according to the contents of the
  755. // Hostname sent in the second request.
  756. TEST_F(NameDhcpv4SrvTest, processTwoRequestsHostname) {
  757. IfaceMgrTestConfig test_config(true);
  758. IfaceMgr::instance().openSockets4();
  759. Pkt4Ptr req1 = generatePktWithHostname(DHCPREQUEST, "myhost.example.com.");
  760. // Set interface for the incoming packet. The server requires it to
  761. // generate client id.
  762. req1->setIface("eth1");
  763. Pkt4Ptr reply;
  764. ASSERT_NO_THROW(reply = srv_->processRequest(req1));
  765. checkResponse(reply, DHCPACK, 1234);
  766. // Verify that there is one NameChangeRequest generated.
  767. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  768. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  769. reply->getYiaddr().toText(), "myhost.example.com.",
  770. "00010132E91AA355CFBB753C0F0497A5A940436"
  771. "965B68B6D438D98E680BF10B09F3BCF",
  772. time(NULL), subnet_->getValid(), true);
  773. // Create another Request message but with a different Hostname. Server
  774. // should generate two NameChangeRequests: one to remove existing entry,
  775. // another one to add new entry with updated domain-name.
  776. Pkt4Ptr req2 = generatePktWithHostname(DHCPREQUEST, "otherhost");
  777. // Set interface for the incoming packet. The server requires it to
  778. // generate client id.
  779. req2->setIface("eth1");
  780. ASSERT_NO_THROW(reply = srv_->processRequest(req2));
  781. checkResponse(reply, DHCPACK, 1234);
  782. // There should be two NameChangeRequests. Verify that they are valid.
  783. ASSERT_EQ(2, d2_mgr_.getQueueSize());
  784. verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
  785. reply->getYiaddr().toText(),
  786. "myhost.example.com.",
  787. "00010132E91AA355CFBB753C0F0497A5A940436"
  788. "965B68B6D438D98E680BF10B09F3BCF",
  789. time(NULL), subnet_->getValid(), true);
  790. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  791. reply->getYiaddr().toText(),
  792. "otherhost.example.com.",
  793. "000101A5AEEA7498BD5AD9D3BF600E49FF39A7E3"
  794. "AFDCE8C3D0E53F35CC584DD63C89CA",
  795. time(NULL), subnet_->getValid(), true);
  796. }
  797. // Test that when a release message is sent for a previously acquired lease,
  798. // DDNS updates are enabled that the server genenerates a NameChangeRequest
  799. // to remove entries corresponding to the released lease.
  800. TEST_F(NameDhcpv4SrvTest, processRequestRelease) {
  801. IfaceMgrTestConfig test_config(true);
  802. IfaceMgr::instance().openSockets4();
  803. // Verify the updates are enabled.
  804. ASSERT_TRUE(CfgMgr::instance().ddnsEnabled());
  805. // Create and process a lease request so we have a lease to release.
  806. Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  807. Option4ClientFqdn::FLAG_E,
  808. "myhost.example.com.",
  809. Option4ClientFqdn::FULL, true);
  810. Pkt4Ptr reply;
  811. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  812. checkResponse(reply, DHCPACK, 1234);
  813. // Verify that there is one NameChangeRequest generated for lease.
  814. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  815. verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
  816. reply->getYiaddr().toText(), "myhost.example.com.",
  817. "00010132E91AA355CFBB753C0F0497A5A940436"
  818. "965B68B6D438D98E680BF10B09F3BCF",
  819. time(NULL), subnet_->getValid(), true);
  820. // Create and process the Release message.
  821. Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
  822. rel->setCiaddr(reply->getYiaddr());
  823. rel->setRemoteAddr(IOAddress("192.0.2.3"));
  824. rel->addOption(generateClientId());
  825. rel->addOption(srv_->getServerID());
  826. ASSERT_NO_THROW(srv_->processRelease(rel));
  827. // The lease has been removed, so there should be a NameChangeRequest to
  828. // remove corresponding DNS entries.
  829. ASSERT_EQ(1, d2_mgr_.getQueueSize());
  830. verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
  831. reply->getYiaddr().toText(), "myhost.example.com.",
  832. "00010132E91AA355CFBB753C0F0497A5A940436"
  833. "965B68B6D438D98E680BF10B09F3BCF",
  834. time(NULL), subnet_->getValid(), true);
  835. }
  836. // Test that when the Release message is sent for a previously acquired lease
  837. // and DDNS updates are disabled that server does NOT generate a
  838. // NameChangeRequest to remove entries corresponding to the released lease.
  839. // Queue size is not available when updates are not enabled, however,
  840. // attempting to send a NCR when updates disabled will result in a throw.
  841. // If no throws are experienced then no attempt was made to send a NCR.
  842. TEST_F(NameDhcpv4SrvTest, processRequestReleaseUpdatesDisabled) {
  843. // Create fake interfaces and open fake sockets.
  844. IfaceMgrTestConfig test_config(true);
  845. IfaceMgr::instance().openSockets4();
  846. // Disable DDNS.
  847. disableD2();
  848. ASSERT_FALSE(CfgMgr::instance().ddnsEnabled());
  849. // Create and process a lease request so we have a lease to release.
  850. Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
  851. Option4ClientFqdn::FLAG_E,
  852. "myhost.example.com.",
  853. Option4ClientFqdn::FULL, true);
  854. Pkt4Ptr reply;
  855. ASSERT_NO_THROW(reply = srv_->processRequest(req));
  856. checkResponse(reply, DHCPACK, 1234);
  857. // Create and process the Release message.
  858. Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
  859. rel->setCiaddr(reply->getYiaddr());
  860. rel->setRemoteAddr(IOAddress("192.0.2.3"));
  861. rel->addOption(generateClientId());
  862. rel->addOption(srv_->getServerID());
  863. ASSERT_NO_THROW(srv_->processRelease(rel));
  864. }
  865. } // end of anonymous namespace