host_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. // Copyright (C) 2015-2016 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 <asiolink/io_address.h>
  8. #include <dhcp/tests/iface_mgr_test_config.h>
  9. #include <dhcp6/tests/dhcp6_test_utils.h>
  10. #include <dhcp6/tests/dhcp6_client.h>
  11. #include <boost/algorithm/string/join.hpp>
  12. #include <boost/lexical_cast.hpp>
  13. #include <list>
  14. #include <sstream>
  15. using namespace isc;
  16. using namespace isc::asiolink;
  17. using namespace isc::dhcp;
  18. using namespace isc::dhcp::test;
  19. namespace {
  20. /// @brief Set of JSON configurations used by the Host reservation unit tests.
  21. ///
  22. /// - Configuration 0:
  23. /// Single subnet with two reservations, one with a hostname, one without
  24. /// - Configuration 1:
  25. /// Multiple reservations using different host identifiers.
  26. /// - Configuration 2:
  27. /// Same as configuration 1 but 'host-reservation-identifiers' specified
  28. /// in non-default order.
  29. const char* CONFIGS[] = {
  30. // Configuration 0:
  31. "{ "
  32. "\"interfaces-config\": {"
  33. " \"interfaces\": [ \"*\" ]"
  34. "},"
  35. "\"valid-lifetime\": 4000, "
  36. "\"preferred-lifetime\": 3000,"
  37. "\"rebind-timer\": 2000, "
  38. "\"renew-timer\": 1000, "
  39. "\"subnet6\": [ "
  40. " { "
  41. " \"subnet\": \"2001:db8:1::/48\", "
  42. " \"pools\": [ { \"pool\": \"2001:db8:1:1::/64\" } ],"
  43. " \"interface\" : \"eth0\" , "
  44. " \"reservations\": ["
  45. " {"
  46. " \"duid\": \"01:02:03:04\","
  47. " \"ip-addresses\": [ \"2001:db8:1:1::babe\" ],"
  48. " \"hostname\": \"alice\""
  49. " },"
  50. " {"
  51. " \"duid\": \"01:02:03:05\","
  52. " \"ip-addresses\": [ \"2001:db8:1:1::babf\" ]"
  53. " } ]"
  54. " } ]"
  55. "}",
  56. // Configuration 1:
  57. "{ "
  58. "\"interfaces-config\": {"
  59. " \"interfaces\": [ \"*\" ]"
  60. "},"
  61. "\"valid-lifetime\": 4000, "
  62. "\"preferred-lifetime\": 3000,"
  63. "\"rebind-timer\": 2000, "
  64. "\"renew-timer\": 1000, "
  65. "\"mac-sources\": [ \"ipv6-link-local\" ], "
  66. "\"subnet6\": [ "
  67. " { "
  68. " \"subnet\": \"2001:db8:1::/48\", "
  69. " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
  70. " \"interface\" : \"eth0\" , "
  71. " \"reservations\": ["
  72. " {"
  73. " \"hw-address\": \"38:60:77:d5:ff:ee\","
  74. " \"ip-addresses\": [ \"2001:db8:1::1\" ]"
  75. " },"
  76. " {"
  77. " \"duid\": \"01:02:03:05\","
  78. " \"ip-addresses\": [ \"2001:db8:1::2\" ]"
  79. " } ]"
  80. " } ]"
  81. "}",
  82. // Configuration 2:
  83. "{ "
  84. "\"interfaces-config\": {"
  85. " \"interfaces\": [ \"*\" ]"
  86. "},"
  87. "\"host-reservation-identifiers\": [ \"duid\", \"hw-address\" ],"
  88. "\"valid-lifetime\": 4000, "
  89. "\"preferred-lifetime\": 3000,"
  90. "\"rebind-timer\": 2000, "
  91. "\"renew-timer\": 1000, "
  92. "\"mac-sources\": [ \"ipv6-link-local\" ], "
  93. "\"subnet6\": [ "
  94. " { "
  95. " \"subnet\": \"2001:db8:1::/48\", "
  96. " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
  97. " \"interface\" : \"eth0\" , "
  98. " \"reservations\": ["
  99. " {"
  100. " \"hw-address\": \"38:60:77:d5:ff:ee\","
  101. " \"ip-addresses\": [ \"2001:db8:1::1\" ]"
  102. " },"
  103. " {"
  104. " \"duid\": \"01:02:03:05\","
  105. " \"ip-addresses\": [ \"2001:db8:1::2\" ]"
  106. " } ]"
  107. " } ]"
  108. "}",
  109. // Configuration 3:
  110. "{ "
  111. "\"interfaces-config\": {"
  112. " \"interfaces\": [ \"*\" ]"
  113. "},"
  114. "\"valid-lifetime\": 4000, "
  115. "\"preferred-lifetime\": 3000,"
  116. "\"rebind-timer\": 2000, "
  117. "\"renew-timer\": 1000, "
  118. "\"subnet6\": [ "
  119. " { "
  120. " \"subnet\": \"2001:db8:1::/48\", "
  121. " \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::10\" } ],"
  122. " \"interface\" : \"eth0\","
  123. " \"reservations\": ["
  124. " {"
  125. " \"duid\": \"01:02:03:04\","
  126. " \"ip-addresses\": [ \"2001:db8:1:1::1\", \"2001:db8:1:1::2\","
  127. "\"2001:db8:1:1::3\" ],"
  128. " \"prefixes\": [ \"3000:1:1::/32\", \"3000:1:2::/32\","
  129. "\"3000:1:3::/32\" ]"
  130. " } ]"
  131. " } ]"
  132. "}"
  133. };
  134. class Reservation {
  135. public:
  136. Reservation(const std::string& resource);
  137. bool isEmpty() const;
  138. bool isPrefix() const;
  139. static const Reservation& UNSPEC();
  140. operator std::string() const;
  141. private:
  142. IOAddress prefix_;
  143. uint8_t prefix_len_;
  144. };
  145. Reservation::Reservation(const std::string& resource)
  146. : prefix_(IOAddress::IPV6_ZERO_ADDRESS()), prefix_len_(0) {
  147. size_t slash_pos = resource.find("/");
  148. if ((slash_pos != std::string::npos) && (slash_pos < resource.size() - 1)) {
  149. prefix_len_ = boost::lexical_cast<unsigned int>(resource.substr(slash_pos + 1));
  150. }
  151. prefix_ = IOAddress(resource.substr(0, slash_pos));
  152. }
  153. bool
  154. Reservation::isEmpty() const {
  155. return (prefix_.isV6Zero());
  156. }
  157. bool
  158. Reservation::isPrefix() const {
  159. return (!isEmpty() && (prefix_len_ > 0));
  160. }
  161. const Reservation& Reservation::UNSPEC() {
  162. static Reservation unspec("::/0");
  163. return (unspec);
  164. }
  165. Reservation::operator std::string() const {
  166. std::ostringstream s;
  167. s << "\"" << prefix_;
  168. if (prefix_len_ > 0) {
  169. s << "/" << static_cast<int>(prefix_len_);
  170. }
  171. s << "\"";
  172. return (s.str());
  173. }
  174. /// @brief Test fixture class for testing host reservations
  175. class HostTest : public Dhcpv6SrvTest {
  176. public:
  177. /// @brief Constructor.
  178. ///
  179. /// Sets up fake interfaces.
  180. HostTest()
  181. : Dhcpv6SrvTest(),
  182. iface_mgr_test_config_(true) {
  183. }
  184. /// @brief Verifies that the reservation is retrieved by the server
  185. /// using one of the host identifiers.
  186. ///
  187. /// @param client Reference to a client to be used in the test.
  188. /// The client should be preconfigured to insert a specific identifier
  189. /// into the message, e.g. DUID, HW address etc.
  190. /// @param config_index Index of the configuration to use in the CONFIGS
  191. /// table.
  192. /// @param exp_ip_address Expected IPv6 address in the returned
  193. /// reservation.
  194. void testReservationByIdentifier(Dhcp6Client& client,
  195. const unsigned int config_index,
  196. const std::string exp_ip_address) {
  197. configure(CONFIGS[config_index], *client.getServer());
  198. const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
  199. getCfgSubnets6()->getAll();
  200. ASSERT_EQ(1, subnets->size());
  201. // Configure client to request IA_NA and append IA_NA option
  202. // to the client's message.
  203. client.requestAddress(1234, IOAddress("2001:db8:1:1::dead:beef"));
  204. // Perform 4-way exchange.
  205. ASSERT_NO_THROW(client.doSARR());
  206. // Verify that the client we got the reserved address
  207. ASSERT_EQ(1, client.getLeaseNum());
  208. Lease6 lease_client = client.getLease(0);
  209. EXPECT_EQ(exp_ip_address, lease_client.addr_.toText());
  210. }
  211. static void storeReservation(const Reservation& r,
  212. std::list<std::string>& address_list,
  213. std::list<std::string>& prefix_list);
  214. std::string configString(const DUID& duid,
  215. const Reservation& r1 = Reservation::UNSPEC(),
  216. const Reservation& r2 = Reservation::UNSPEC(),
  217. const Reservation& r3 = Reservation::UNSPEC(),
  218. const Reservation& r4 = Reservation::UNSPEC(),
  219. const Reservation& r5 = Reservation::UNSPEC(),
  220. const Reservation& r6 = Reservation::UNSPEC()) const;
  221. /// @brief Interface Manager's fake configuration control.
  222. IfaceMgrTestConfig iface_mgr_test_config_;
  223. };
  224. void
  225. HostTest::storeReservation(const Reservation& r,
  226. std::list<std::string>& address_list,
  227. std::list<std::string>& prefix_list) {
  228. if (!r.isEmpty()) {
  229. if (r.isPrefix()) {
  230. prefix_list.push_back(r);
  231. } else {
  232. address_list.push_back(r);
  233. }
  234. }
  235. }
  236. std::string
  237. HostTest::configString(const DUID& duid,
  238. const Reservation& r1, const Reservation& r2,
  239. const Reservation& r3, const Reservation& r4,
  240. const Reservation& r5, const Reservation& r6) const {
  241. std::list<std::string> address_list;
  242. std::list<std::string> prefix_list;
  243. storeReservation(r1, address_list, prefix_list);
  244. storeReservation(r2, address_list, prefix_list);
  245. storeReservation(r3, address_list, prefix_list);
  246. storeReservation(r4, address_list, prefix_list);
  247. storeReservation(r5, address_list, prefix_list);
  248. storeReservation(r6, address_list, prefix_list);
  249. std::ostringstream s;
  250. s << "{ "
  251. "\"interfaces-config\": {"
  252. " \"interfaces\": [ \"*\" ]"
  253. "},"
  254. "\"valid-lifetime\": 4000, "
  255. "\"preferred-lifetime\": 3000,"
  256. "\"rebind-timer\": 2000, "
  257. "\"renew-timer\": 1000, "
  258. "\"subnet6\": [ "
  259. " { "
  260. " \"subnet\": \"2001:db8:1::/48\", "
  261. " \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::10\" } ],"
  262. " \"pd-pools\": [ { \"prefix\": \"3001::\", \"prefix-len\": 32,"
  263. " \"delegated-len\": 64 } ],"
  264. " \"interface\" : \"eth0\"";
  265. if (!address_list.empty() || !prefix_list.empty()) {
  266. s << ","
  267. " \"reservations\": ["
  268. " {"
  269. " \"duid\": ";
  270. s << "\"" << duid.toText() << "\",";
  271. if (!address_list.empty()) {
  272. s << " \"ip-addresses\": [ "
  273. << boost::algorithm::join(address_list, ", ")
  274. << "]";
  275. }
  276. if (!prefix_list.empty()) {
  277. if (!address_list.empty()) {
  278. s << ", ";
  279. }
  280. s << " \"prefixes\": [ "
  281. << boost::algorithm::join(prefix_list, ", ")
  282. << "]";
  283. }
  284. s << " } ]";
  285. }
  286. s << " } ]"
  287. "}";
  288. return (s.str());
  289. }
  290. // Test basic SARR scenarios against a server configured with one subnet
  291. // containing two reservations. One reservation with a hostname, one
  292. // without a hostname. Scenarios:
  293. //
  294. // - Verify that a client when matched to a host reservation with a hostname
  295. // gets that reservation and the lease hostname matches the reserved hostname
  296. //
  297. // - Verify that a client when matched to a host reservation without a hostname
  298. // gets that reservation and the lease hostname is blank
  299. //
  300. // - Verify that a client that does not match a host reservation gets a dynamic
  301. // lease and the hostname for the lease is blank.
  302. //
  303. TEST_F(HostTest, basicSarrs) {
  304. Dhcp6Client client;
  305. configure(CONFIGS[0], *client.getServer());
  306. const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
  307. getCfgSubnets6()->getAll();
  308. ASSERT_EQ(1, subnets->size());
  309. // Configure client to request IA_NA and aAppend IA_NA option
  310. // to the client's message.
  311. client.setDUID("01:02:03:04");
  312. client.requestAddress(1234, IOAddress("2001:db8:1:1::dead:beef"));
  313. // Perform 4-way exchange.
  314. ASSERT_NO_THROW(client.doSARR());
  315. // Verify that the client we got the reserved address
  316. ASSERT_EQ(1, client.getLeaseNum());
  317. Lease6 lease_client = client.getLease(0);
  318. EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
  319. // Check that the server recorded the lease.
  320. // and lease has reserved hostname
  321. Lease6Ptr lease_server = checkLease(lease_client);
  322. ASSERT_TRUE(lease_server);
  323. EXPECT_EQ("alice", lease_server->hostname_);
  324. // Now redo the client, adding one to the DUID
  325. client.clearConfig();
  326. client.modifyDUID();
  327. // Perform 4-way exchange.
  328. ASSERT_NO_THROW(client.doSARR());
  329. // Verify that the client we got the reserved address
  330. ASSERT_EQ(1, client.getLeaseNum());
  331. lease_client = client.getLease(0);
  332. EXPECT_EQ("2001:db8:1:1::babf", lease_client.addr_.toText());
  333. // Check that the server recorded the lease.
  334. // and that the server lease has NO hostname
  335. lease_server = checkLease(lease_client);
  336. ASSERT_TRUE(lease_server);
  337. EXPECT_EQ("", lease_server->hostname_);
  338. // Now redo the client with yet another DUID and verify that
  339. // we get a dynamic address.
  340. client.clearConfig();
  341. client.modifyDUID();
  342. client.clearRequestedIAs();
  343. client.requestAddress(1234);
  344. // Perform 4-way exchange.
  345. ASSERT_NO_THROW(client.doSARR());
  346. // Verify that the client got a dynamic address
  347. ASSERT_EQ(1, client.getLeaseNum());
  348. lease_client = client.getLease(0);
  349. EXPECT_EQ("2001:db8:1:1::", lease_client.addr_.toText());
  350. // Check that the server recorded the lease.
  351. // and that the server lease has NO hostname
  352. lease_server = checkLease(lease_client);
  353. ASSERT_TRUE(lease_server);
  354. EXPECT_EQ("", lease_server->hostname_);
  355. }
  356. // Test basic SARR and renew situation with a client that matches a host
  357. // reservation
  358. TEST_F(HostTest, sarrAndRenew) {
  359. Dhcp6Client client;
  360. configure(CONFIGS[0], *client.getServer());
  361. // Configure client to request IA_NA.
  362. client.requestAddress();
  363. const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
  364. getCfgSubnets6()->getAll();
  365. ASSERT_EQ(1, subnets->size());
  366. // Configure client to request IA_NA and aAppend IA_NA option
  367. // to the client's message.
  368. client.setDUID("01:02:03:04");
  369. client.requestAddress(1234, IOAddress("2001:db8:1:1::dead:beef"));
  370. // Perform 4-way exchange.
  371. ASSERT_NO_THROW(client.doSARR());
  372. // Now play with time
  373. client.fastFwdTime(1000);
  374. // Verify that the client we got the reserved address
  375. ASSERT_EQ(1, client.getLeaseNum());
  376. Lease6 lease_client = client.getLease(0);
  377. EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
  378. // Do not send the hint while renewing.
  379. client.clearRequestedIAs();
  380. // Send Renew message to the server.
  381. ASSERT_NO_THROW(client.doRenew());
  382. // Verify that we got an extended lease back
  383. ASSERT_EQ(1, client.getLeaseNum());
  384. Lease6 lease_client2 = client.getLease(0);
  385. EXPECT_EQ("2001:db8:1:1::babe", lease_client2.addr_.toText());
  386. // The client's lease should have been extended. The client will
  387. // update the cltt to current time when the lease gets extended.
  388. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  389. // Make sure, that the client's lease matches the lease held by the
  390. // server and that we have the reserved host name.
  391. Lease6Ptr lease_server2 = checkLease(lease_client2);
  392. EXPECT_TRUE(lease_server2);
  393. EXPECT_EQ("alice", lease_server2->hostname_);
  394. }
  395. // Test basic SARR and rebind situation with a client that matches a host
  396. // reservation.
  397. TEST_F(HostTest, sarrAndRebind) {
  398. Dhcp6Client client;
  399. configure(CONFIGS[0], *client.getServer());
  400. // Configure client to request IA_NA.
  401. client.requestAddress();
  402. const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
  403. getCfgSubnets6()->getAll();
  404. ASSERT_EQ(1, subnets->size());
  405. // Configure client to request IA_NA and aAppend IA_NA option
  406. // to the client's message.
  407. client.setDUID("01:02:03:04");
  408. client.requestAddress(1234, IOAddress("2001:db8:1:1::dead:beef"));
  409. // Perform 4-way exchange.
  410. ASSERT_NO_THROW(client.doSARR());
  411. // Now play with time
  412. client.fastFwdTime(1000);
  413. // Verify that the client we got the reserved address
  414. ASSERT_EQ(1, client.getLeaseNum());
  415. Lease6 lease_client = client.getLease(0);
  416. EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
  417. // Do not send the hint while renewing.
  418. client.clearRequestedIAs();
  419. // Send Rebind message to the server.
  420. ASSERT_NO_THROW(client.doRebind());
  421. // Verify that we got an extended lease back
  422. ASSERT_EQ(1, client.getLeaseNum());
  423. Lease6 lease_client2 = client.getLease(0);
  424. EXPECT_EQ("2001:db8:1:1::babe", lease_client2.addr_.toText());
  425. // The client's lease should have been extended. The client will
  426. // update the cltt to current time when the lease gets extended.
  427. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  428. // Make sure, that the client's lease matches the lease held by the
  429. // server and that we have the reserved host name.
  430. Lease6Ptr lease_server2 = checkLease(lease_client2);
  431. EXPECT_TRUE(lease_server2);
  432. EXPECT_EQ("alice", lease_server2->hostname_);
  433. }
  434. // This test verfies that the host reservation by DUID is found by the
  435. // server.
  436. TEST_F(HostTest, reservationByDUID) {
  437. Dhcp6Client client;
  438. // Set DUID matching the one used to create host reservations.
  439. client.setDUID("01:02:03:05");
  440. // Run the actual test.
  441. testReservationByIdentifier(client, 1, "2001:db8:1::2");
  442. }
  443. // This test verfies that the host reservation by HW address is found
  444. // by the server.
  445. TEST_F(HostTest, reservationByHWAddress) {
  446. Dhcp6Client client;
  447. // Set link local address for the client which the server will
  448. // use to decode the HW address as 38:60:77:d5:ff:ee. This
  449. // decoded address will be used to search for host reservations.
  450. client.setLinkLocal(IOAddress("fe80::3a60:77ff:fed5:ffee"));
  451. // Run the actual test.
  452. testReservationByIdentifier(client, 1, "2001:db8:1::1");
  453. }
  454. // This test verifies that order in which host identifiers are used to
  455. // retrieve host reservations can be controlled.
  456. TEST_F(HostTest, hostIdentifiersOrder) {
  457. Dhcp6Client client;
  458. // Set DUID matching the one used to create host reservations.
  459. client.setDUID("01:02:03:05");
  460. // Set link local address for the client which the server will
  461. // use to decode the HW address as 38:60:77:d5:ff:ee. This
  462. // decoded address will be used to search for host reservations.
  463. client.setLinkLocal(IOAddress("fe80::3a60:77ff:fed5:ffee"));
  464. testReservationByIdentifier(client, 2, "2001:db8:1::2");
  465. }
  466. TEST_F(HostTest, reservationMultipleIASolicit) {
  467. Dhcp6Client client;
  468. client.setDUID("01:02:03:04");
  469. const std::string c = configString(*client.getDuid(),
  470. Reservation("2001:db8:1:1::1"),
  471. Reservation("2001:db8:1:1::2"),
  472. Reservation("2001:db8:1:1::3"),
  473. Reservation("3000:1:1::/32"),
  474. Reservation("3000:1:2::/32"),
  475. Reservation("3000:1:3::/32"));
  476. ASSERT_NO_THROW(configure(c, *client.getServer()));
  477. client.requestAddress(1234);
  478. client.requestAddress(2345);
  479. client.requestAddress(3456);
  480. client.requestPrefix(5678);
  481. client.requestPrefix(6789);
  482. client.requestPrefix(7890);
  483. // Send Solicit and require that the client saves received configuration
  484. // so as we can test that advertised configuration is correct.
  485. ASSERT_NO_THROW(client.doSolicit(true));
  486. ASSERT_EQ(6, client.getLeaseNum());
  487. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::1")));
  488. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::2")));
  489. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::3")));
  490. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:1::"), 32));
  491. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:2::"), 32));
  492. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:3::"), 32));
  493. }
  494. TEST_F(HostTest, reservationMultipleIARequest) {
  495. Dhcp6Client client;
  496. client.setDUID("01:02:03:04");
  497. const std::string c = configString(*client.getDuid(),
  498. Reservation("2001:db8:1:1::1"),
  499. Reservation("2001:db8:1:1::2"),
  500. Reservation("2001:db8:1:1::3"),
  501. Reservation("3000:1:1::/32"),
  502. Reservation("3000:1:2::/32"),
  503. Reservation("3000:1:3::/32"));
  504. ASSERT_NO_THROW(configure(c, *client.getServer()));
  505. client.requestAddress(1234);
  506. client.requestAddress(2345);
  507. client.requestAddress(3456);
  508. client.requestPrefix(5678);
  509. client.requestPrefix(6789);
  510. client.requestPrefix(7890);
  511. ASSERT_NO_THROW(client.doSARR());
  512. ASSERT_EQ(6, client.getLeaseNum());
  513. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::1")));
  514. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::2")));
  515. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::3")));
  516. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:1::"), 32));
  517. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:2::"), 32));
  518. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:3::"), 32));
  519. }
  520. TEST_F(HostTest, reservationAndDynamicIAs) {
  521. Dhcp6Client client;
  522. client.setDUID("01:02:03:04");
  523. const std::string c = configString(*client.getDuid(),
  524. Reservation("2001:db8:1:1::2"),
  525. Reservation("2001:db8:1:1::3"),
  526. Reservation("3000:1:1::/32"),
  527. Reservation("3000:1:3::/32"));
  528. ASSERT_NO_THROW(configure(c, *client.getServer()));
  529. client.requestAddress(1234);
  530. client.requestAddress(2345);
  531. client.requestAddress(3456);
  532. client.requestPrefix(5678);
  533. client.requestPrefix(6789);
  534. client.requestPrefix(7890);
  535. // Send Solicit and require that the client saves received configuration
  536. // so as we can test that advertised configuration is correct.
  537. ASSERT_NO_THROW(client.doSolicit(true));
  538. ASSERT_EQ(6, client.getLeaseNum());
  539. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::2")));
  540. EXPECT_TRUE(client.hasLeaseForAddress(IOAddress("2001:db8:1:1::3")));
  541. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:1::"), 32));
  542. EXPECT_TRUE(client.hasLeaseForPrefix(IOAddress("3000:1:3::"), 32));
  543. EXPECT_TRUE(client.hasLeaseForAddressRange(IOAddress("2001:db8:1::1"),
  544. IOAddress("2001:db8:1::10")));
  545. EXPECT_TRUE(client.hasLeaseForPrefixPool(IOAddress("3001::"), 32, 64));
  546. }
  547. } // end of anonymous namespace