rebind_unittest.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // Copyright (C) 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 <cc/data.h>
  17. #include <dhcp/tests/iface_mgr_test_config.h>
  18. #include <dhcp6/config_parser.h>
  19. #include <dhcp6/tests/dhcp6_test_utils.h>
  20. #include <dhcp6/tests/dhcp6_client.h>
  21. using namespace isc;
  22. using namespace isc::asiolink;
  23. using namespace isc::data;
  24. using namespace isc::dhcp;
  25. using namespace isc::dhcp::test;
  26. using namespace isc::test;
  27. namespace {
  28. /// @brief Set of JSON configurations used throughout the Rebind tests.
  29. ///
  30. /// - Configuration 0:
  31. /// - only addresses (no prefixes)
  32. /// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::64
  33. /// - 1 subnet for eth0 and 1 subnet for eth1
  34. ///
  35. /// - Configuration 1:
  36. /// - similar to Configuration 0 but different subnets
  37. /// - pools configured: 2001:db8:3::/64 and 2001:db8:4::/64
  38. ///
  39. /// - Configuration 2:
  40. /// - similar to Configuration 0 and Configuration 1
  41. /// - pools configured: 3000:1::/64 and 3000:2::/64
  42. /// - this specific configuration is used by tests using relays
  43. ///
  44. /// - Configuration 3:
  45. /// - similar to Configuration 2 but with different subnets
  46. /// - pools configured: 3000:3::/64 and 3000:4::/64
  47. /// - this specific configuration is used by tests using relays
  48. ///
  49. /// - Configuration 5:
  50. /// - only prefixes (no addresses)
  51. /// - 2 subnets: 2001:db8:1::/40 and 2001:db8:2::/40
  52. /// - 2 prefix pools: 2001:db8:1::/72 and 2001:db8:2::/72
  53. /// - 1 subnet for eth0 and 1 subnet for eth1
  54. /// - this specific configuration is used by tests which don't use relays
  55. ///
  56. /// - Configuration 6:
  57. /// - similar to Configuration 5 but with different subnets
  58. /// - 2 subnets: 2001:db8:3::/40 and 2001:db8:4::/40
  59. /// - 2 prefix pools: 2001:db8:3::/72 and 2001:db8:4::/72
  60. /// - delegated length /80
  61. /// - this specific configuration is used by tests which don't use relays
  62. const char* REBIND_CONFIGS[] = {
  63. // Configuration 0
  64. "{ \"interfaces\": [ \"all\" ],"
  65. "\"preferred-lifetime\": 3000,"
  66. "\"rebind-timer\": 2000, "
  67. "\"renew-timer\": 1000, "
  68. "\"subnet6\": [ { "
  69. " \"pool\": [ \"2001:db8:1::/64\" ],"
  70. " \"subnet\": \"2001:db8:1::/48\", "
  71. " \"interface-id\": \"\","
  72. " \"interface\": \"eth0\""
  73. " },"
  74. " {"
  75. " \"pool\": [ \"2001:db8:2::/64\" ],"
  76. " \"subnet\": \"2001:db8:2::/48\", "
  77. " \"interface-id\": \"\","
  78. " \"interface\": \"eth1\""
  79. " } ],"
  80. "\"valid-lifetime\": 4000 }",
  81. // Configuration 1
  82. "{ \"interfaces\": [ \"all\" ],"
  83. "\"preferred-lifetime\": 3000,"
  84. "\"rebind-timer\": 2000, "
  85. "\"renew-timer\": 1000, "
  86. "\"subnet6\": [ { "
  87. " \"pool\": [ \"2001:db8:3::/64\" ],"
  88. " \"subnet\": \"2001:db8:3::/48\", "
  89. " \"interface-id\": \"\","
  90. " \"interface\": \"eth1\""
  91. " },"
  92. " {"
  93. " \"pool\": [ \"2001:db8:4::/64\" ],"
  94. " \"subnet\": \"2001:db8:4::/48\", "
  95. " \"interface-id\": \"\","
  96. " \"interface\": \"eth0\""
  97. " } ],"
  98. "\"valid-lifetime\": 4000 }",
  99. // Configuration 2
  100. "{ \"interfaces\": [ \"all\" ],"
  101. "\"preferred-lifetime\": 3000,"
  102. "\"rebind-timer\": 2000, "
  103. "\"renew-timer\": 1000, "
  104. "\"subnet6\": [ { "
  105. " \"pool\": [ \"3000:1::/64\" ],"
  106. " \"subnet\": \"3000:1::/48\", "
  107. " \"interface-id\": \"\","
  108. " \"interface\": \"eth0\""
  109. " },"
  110. " {"
  111. " \"pool\": [ \"3000:2::/64\" ],"
  112. " \"subnet\": \"3000:2::/48\", "
  113. " \"interface-id\": \"\","
  114. " \"interface\": \"eth1\""
  115. " } ],"
  116. "\"valid-lifetime\": 4000 }",
  117. // Configuration 3
  118. "{ \"interfaces\": [ \"all\" ],"
  119. "\"preferred-lifetime\": 3000,"
  120. "\"rebind-timer\": 2000, "
  121. "\"renew-timer\": 1000, "
  122. "\"subnet6\": [ { "
  123. " \"pool\": [ \"3000:3::/64\" ],"
  124. " \"subnet\": \"3000:3::/48\", "
  125. " \"interface-id\": \"\","
  126. " \"interface\": \"eth1\""
  127. " },"
  128. " {"
  129. " \"pool\": [ \"3000:4::/64\" ],"
  130. " \"subnet\": \"3000:4::/48\", "
  131. " \"interface-id\": \"\","
  132. " \"interface\": \"eth0\""
  133. " } ],"
  134. "\"valid-lifetime\": 4000 }",
  135. // Configuration 4
  136. "{ \"interfaces\": [ \"all\" ],"
  137. "\"preferred-lifetime\": 3000,"
  138. "\"rebind-timer\": 2000, "
  139. "\"renew-timer\": 1000, "
  140. "\"subnet6\": [ { "
  141. " \"pd-pools\": ["
  142. " { \"prefix\": \"2001:db8:1:01::\", "
  143. " \"prefix-len\": 72, "
  144. " \"delegated-len\": 80"
  145. " } ],"
  146. " \"subnet\": \"2001:db8:1::/40\", "
  147. " \"interface-id\": \"\","
  148. " \"interface\": \"eth0\""
  149. " },"
  150. " {"
  151. " \"pd-pools\": ["
  152. " { \"prefix\": \"2001:db8:2:01::\", "
  153. " \"prefix-len\": 72, "
  154. " \"delegated-len\": 80"
  155. " } ],"
  156. " \"subnet\": \"2001:db8:2::/40\", "
  157. " \"interface-id\": \"\","
  158. " \"interface\": \"eth1\""
  159. " } ],"
  160. "\"valid-lifetime\": 4000 }",
  161. // Configuration 5
  162. "{ \"interfaces\": [ \"all\" ],"
  163. "\"preferred-lifetime\": 3000,"
  164. "\"rebind-timer\": 2000, "
  165. "\"renew-timer\": 1000, "
  166. "\"subnet6\": [ { "
  167. " \"pd-pools\": ["
  168. " { \"prefix\": \"2001:db8:3:01::\", "
  169. " \"prefix-len\": 72, "
  170. " \"delegated-len\": 80"
  171. " } ],"
  172. " \"subnet\": \"2001:db8:3::/40\", "
  173. " \"interface-id\": \"\","
  174. " \"interface\": \"eth1\""
  175. " },"
  176. " {"
  177. " \"pd-pools\": ["
  178. " { \"prefix\": \"2001:db8:4:01::\", "
  179. " \"prefix-len\": 72, "
  180. " \"delegated-len\": 80"
  181. " } ],"
  182. " \"subnet\": \"2001:db8:4::/40\", "
  183. " \"interface-id\": \"\","
  184. " \"interface\": \"eth0\""
  185. " } ],"
  186. "\"valid-lifetime\": 4000 }",
  187. };
  188. /// @brief Test fixture class for testing Rebind.
  189. class RebindTest : public Dhcpv6SrvTest {
  190. public:
  191. /// @brief Constructor.
  192. ///
  193. /// Sets up fake interfaces.
  194. RebindTest()
  195. : Dhcpv6SrvTest(),
  196. iface_mgr_test_config_(true) {
  197. }
  198. /// @brief Configure the DHCPv6 server using the JSON string.
  199. ///
  200. /// @param config New configuration in JSON format.
  201. /// @param srv Server to be configured.
  202. void configure(const std::string& config, NakedDhcpv6Srv& srv);
  203. /// @brief Make 4-way exchange to obtain a lease.
  204. ///
  205. /// @param config_index Index of the configuration held in @c REBIND_CONFIGS
  206. /// to use to configure the server.
  207. /// @param subnets_num Number of subnets being created with the specified
  208. /// configuration.
  209. /// @param client Object representing a test DHCPv6 client to use.
  210. void requestLease(const int config_index, const int subnets_num,
  211. Dhcp6Client& client);
  212. /// @brief Interface Manager's fake configuration control.
  213. IfaceMgrTestConfig iface_mgr_test_config_;
  214. };
  215. void
  216. RebindTest::configure(const std::string& config, NakedDhcpv6Srv& srv) {
  217. ElementPtr json = Element::fromJSON(config);
  218. ConstElementPtr status;
  219. // Configure the server and make sure the config is accepted
  220. EXPECT_NO_THROW(status = configureDhcp6Server(srv, json));
  221. ASSERT_TRUE(status);
  222. int rcode;
  223. ConstElementPtr comment = config::parseAnswer(rcode, status);
  224. ASSERT_EQ(0, rcode);
  225. }
  226. void
  227. RebindTest::requestLease(const int config_index, const int subnets_num,
  228. Dhcp6Client& client) {
  229. // Check that the index is in the configuration table.
  230. ASSERT_LT(config_index, sizeof(REBIND_CONFIGS)/sizeof(REBIND_CONFIGS[0]));
  231. // Configure the server.
  232. configure(REBIND_CONFIGS[config_index], *client.getServer());
  233. // Make sure we ended-up having expected number of subnets configured.
  234. const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
  235. ASSERT_EQ(subnets_num, subnets->size());
  236. // Do the actual 4-way exchange.
  237. ASSERT_NO_THROW(client.doSARR());
  238. // Simulate aging of leases, by moving their cltt_ back by 1000s.
  239. client.fastFwdTime(1000);
  240. // Make sure that we have obtained a lease that belongs to one of the
  241. // subnets.
  242. ASSERT_EQ(1, client.getLeaseNum());
  243. Lease6 lease_client = client.getLease(0);
  244. ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client.addr_,
  245. ClientClasses()));
  246. // Check that the client's lease matches the information on the server
  247. // side.
  248. Lease6Ptr lease_server = checkLease(lease_client);
  249. ASSERT_TRUE(lease_server);
  250. // And that status code was OK.
  251. EXPECT_EQ(STATUS_Success, client.getStatusCode(0));
  252. }
  253. // Test that directly connected client's Rebind message is processed and Reply
  254. // message is sent back.
  255. TEST_F(RebindTest, directClient) {
  256. Dhcp6Client client;
  257. // Configure client to request IA_NA.
  258. client.useNA();
  259. // Make 4-way exchange to get the lease.
  260. ASSERT_NO_FATAL_FAILURE(requestLease(0, 2, client));
  261. // Keep the client's lease for future reference.
  262. Lease6 lease_client = client.getLease(0);
  263. // Send Rebind message to the server.
  264. ASSERT_NO_THROW(client.doRebind());
  265. // The client should still have one lease which belong to one of the
  266. // subnets.
  267. ASSERT_EQ(1, client.getLeaseNum());
  268. Lease6 lease_client2 = client.getLease(0);
  269. ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_,
  270. ClientClasses()));
  271. // The client's lease should have been extended. The client will
  272. // update the cltt to current time when the lease gets extended.
  273. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  274. // Make sure, that the client's lease matches the lease held by the
  275. // server.
  276. Lease6Ptr lease_server2 = checkLease(lease_client2);
  277. EXPECT_TRUE(lease_server2);
  278. }
  279. // Test that server doesn't extend the lease when the configuration has changed
  280. // such that the existing subnet is replaced with a different subnet.
  281. TEST_F(RebindTest, directClientChangingSubnet) {
  282. Dhcp6Client client;
  283. // Configure client to request IA_NA.
  284. client.useNA();
  285. // Make 4-way exchange to get the lease.
  286. ASSERT_NO_FATAL_FAILURE(requestLease(0, 2, client));
  287. // Keep the client's lease for future reference.
  288. Lease6 lease_client = client.getLease(0);
  289. // Reconfigure the server so as the new subnet is served on the
  290. // client's interface. Note that there will also be a new subnet
  291. // id assigned to the subnet on this interface.
  292. configure(REBIND_CONFIGS[1], *client.getServer());
  293. // Try to rebind, using the address that the client had acquired using
  294. // previous server configuration.
  295. ASSERT_NO_THROW(client.doRebind());
  296. // We are expecting that the server didn't extend the lease because
  297. // the address that client is using doesn't match the new subnet.
  298. // But, the client still has an old lease.
  299. ASSERT_EQ(1, client.getLeaseNum());
  300. Lease6 lease_client2 = client.getLease(0);
  301. // The current lease should be exactly the same as old lease,
  302. // because server shouldn't have extended.
  303. EXPECT_TRUE(lease_client == lease_client2);
  304. // Make sure, that the lease that client has, is matching the lease
  305. // in the lease database.
  306. Lease6Ptr lease_server2 = checkLease(lease_client2);
  307. EXPECT_TRUE(lease_server2);
  308. // Client should have received NoBinding status code.
  309. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  310. }
  311. // Check that the server doesn't extend the lease for the client when the
  312. // client sends IAID which doesn't belong to the lease that client has.
  313. TEST_F(RebindTest, directClientChangingIAID) {
  314. Dhcp6Client client;
  315. // Configure client to request IA_NA.
  316. client.useNA();
  317. // Make 4-way exchange to get the lease.
  318. ASSERT_NO_FATAL_FAILURE(requestLease(0, 2, client));
  319. // Keep the client's lease for future reference.
  320. Lease6 lease_client = client.getLease(0);
  321. // Modify the IAID of the lease record that client stores. By adding
  322. // one to IAID we guarantee that the IAID will change.
  323. ++client.config_.leases_[0].lease_.iaid_;
  324. // Try to Rebind. Note that client will use a different IAID (which
  325. // is not matching IAID that server retains for the client). Server
  326. // should not find the lease that client is trying to extend and
  327. // should return NoBinding.
  328. ASSERT_NO_THROW(client.doRebind());
  329. // The lease obtained in 4-way exchange should not change after the Rebind
  330. // attempt.
  331. Lease6Ptr lease_server2 = checkLease(lease_client);
  332. EXPECT_TRUE(lease_server2);
  333. // The Status code returned to the client, should be NoBinding.
  334. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  335. }
  336. // Check that server sends NoBinding when the lease has been lost from
  337. // the database and client is trying to Rebind it.
  338. TEST_F(RebindTest, directClientLostLease) {
  339. Dhcp6Client client;
  340. // Configure client to request IA_NA.
  341. client.useNA();
  342. // Make 4-way exchange to get the lease.
  343. ASSERT_NO_FATAL_FAILURE(requestLease(0, 2, client));
  344. // Keep the client's lease for future reference.
  345. Lease6 lease_client = client.getLease(0);
  346. // The lease has been acquired. Now, let's explicitly remove it from the
  347. // lease database.
  348. LeaseMgrFactory::instance().deleteLease(lease_client.addr_);
  349. // An attempt to Rebind should fail. The lease should not be found by
  350. // the server and the server should return NoBinding status code.
  351. ASSERT_NO_THROW(client.doRebind());
  352. ASSERT_EQ(1, client.getLeaseNum());
  353. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  354. }
  355. /// @todo Extend tests for direct client changing address.
  356. // Check that the client can Rebind existing lease through a relay.
  357. TEST_F(RebindTest, relayedClient) {
  358. Dhcp6Client client;
  359. // Configure client to request IA_NA.
  360. client.useNA();
  361. // Configure DHCPv6 client to simulate sending the message through a relay
  362. // agent. The default link-addr is 3001:1::1. This address should be used
  363. // by the server to pick the suitable subnet.
  364. client.useRelay();
  365. // Make 4-way exchange to get the lease. Pick the configuration #2 as it
  366. // specifies the subnet for the relay agent's link address.
  367. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  368. // Keep the client's lease for future reference.
  369. Lease6 lease_client = client.getLease(0);
  370. // Send Rebind message to the server.
  371. ASSERT_NO_THROW(client.doRebind());
  372. // The client should still have one lease which belongs to one of the
  373. // subnets.
  374. ASSERT_EQ(1, client.getLeaseNum());
  375. Lease6 lease_client2 = client.getLease(0);
  376. ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_,
  377. ClientClasses()));
  378. // The client's lease should have been extended. The client will
  379. // update the cltt to current time when the lease gets extended.
  380. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  381. // Make sure, that the client's lease matches the lease held by the
  382. // server.
  383. Lease6Ptr lease_server2 = checkLease(lease_client2);
  384. EXPECT_TRUE(lease_server2);
  385. }
  386. // Check that the lease is not extended for the relayed client when the
  387. // configuration has changed such that the subnet that client is using
  388. // doesn't exist anymore.
  389. TEST_F(RebindTest, relayedClientChangingSubnet) {
  390. Dhcp6Client client;
  391. // Configure client to request IA_NA.
  392. client.useNA();
  393. // Configure DHCPv6 client to simulate sending the message through a relay
  394. // agent. The default link-addr is 3001:1::1. This address should be used
  395. // by the server to pick the suitable subnet.
  396. client.useRelay();
  397. // Make 4-way exchange to get the lease.
  398. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  399. // Keep the client's lease for future reference.
  400. Lease6 lease_client = client.getLease(0);
  401. // Reconfigure the server so as the new subnet is served on the
  402. // client's interface. Note that there will also be a new subnet
  403. // id assigned to the subnet on this interface.
  404. configure(REBIND_CONFIGS[3], *client.getServer());
  405. // Update relay link address to match the new subnet.
  406. client.relay_link_addr_ = IOAddress("3001:4::1");
  407. // Try to rebind, using the address that the client had acquired using
  408. // previous server configuration.
  409. ASSERT_NO_THROW(client.doRebind());
  410. // We are expecting that the server didn't extend the lease because
  411. // the address that client is using doesn't match the new subnet.
  412. // But, the client still has an old lease.
  413. ASSERT_EQ(1, client.getLeaseNum());
  414. Lease6 lease_client2 = client.getLease(0);
  415. // The current lease should be exactly the same as old lease,
  416. // because server shouldn't have extended.
  417. EXPECT_TRUE(lease_client == lease_client2);
  418. // Make sure, that the lease that client has, is matching the lease
  419. // in the lease database.
  420. Lease6Ptr lease_server2 = checkLease(lease_client2);
  421. EXPECT_TRUE(lease_server2);
  422. // Client should have received NoBinding status code.
  423. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  424. }
  425. // Check that the lease is not extended for the relayed client when the IAID in
  426. // the Rebind message doesn't match the one recorded for the client.
  427. TEST_F(RebindTest, relayedClientChangingIAID) {
  428. Dhcp6Client client;
  429. // Configure client to request IA_NA.
  430. client.useNA();
  431. // Configure DHCPv6 client to simulate sending the message through a relay
  432. // agent. The default link-addr is 3001:1::1. This address should be used
  433. // by the server to pick the suitable subnet.
  434. client.useRelay();
  435. // Make 4-way exchange to get the lease.
  436. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  437. // Keep the client's lease for future reference.
  438. Lease6 lease_client = client.getLease(0);
  439. // Modify the IAID of the lease record that client stores. By adding
  440. // one to IAID we guarantee that the IAID will change.
  441. ++client.config_.leases_[0].lease_.iaid_;
  442. // Try to Rebind. Note that client will use a different IAID (which
  443. // is not matching IAID that server retains for the client). Server
  444. // should not find the lease that client is trying to extend and
  445. // should return NoBinding.
  446. ASSERT_NO_THROW(client.doRebind());
  447. // The lease obtained in 4-way exchange should not change after the Rebind
  448. // attempt.
  449. Lease6Ptr lease_server2 = checkLease(lease_client);
  450. EXPECT_TRUE(lease_server2);
  451. // The Status code returned to the client, should be NoBinding.
  452. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  453. }
  454. // Check that the relayed client receives NoBinding when the lease that he
  455. // is Rebinding has been lost from the database.
  456. TEST_F(RebindTest, relayedClientLostLease) {
  457. Dhcp6Client client;
  458. // Configure client to request IA_NA.
  459. client.useNA();
  460. // Configure DHCPv6 client to simulate sending the message through a relay
  461. // agent. The default link-addr is 3001:1::1. This address should be used
  462. // by the server to pick the suitable subnet.
  463. client.useRelay();
  464. // Make 4-way exchange to get the lease.
  465. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  466. // Keep the client's lease for future reference.
  467. Lease6 lease_client = client.getLease(0);
  468. // The lease has been acquired. Now, let's explicitly remove it from the
  469. // lease database.
  470. LeaseMgrFactory::instance().deleteLease(lease_client.addr_);
  471. // An attempt to Rebind should fail. The lease should not be found by
  472. // the server and the server should return NoBinding status code.
  473. ASSERT_NO_THROW(client.doRebind());
  474. ASSERT_EQ(1, client.getLeaseNum());
  475. EXPECT_EQ(STATUS_NoBinding, client.getStatusCode(0));
  476. }
  477. // Check that relayed client receives the IA with lifetimes of 0, when
  478. // client is tgrying to Rebind using an address it doesn't have.
  479. TEST_F(RebindTest, relayedClientChangingAddress) {
  480. Dhcp6Client client;
  481. // Configure client to request IA_NA.
  482. client.useNA();
  483. // Make 4-way exchange to get the lease.
  484. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  485. // Keep the client's lease for future reference.
  486. Lease6 lease_client = client.getLease(0);
  487. // Modify the address of the lease record that client stores. The server
  488. // should check that the address is invalid (hasn't been allocated for
  489. // the particular IAID).
  490. client.config_.leases_[0].lease_.addr_ = IOAddress("3000::100");
  491. // Try to Rebind. The client will use correct IAID but will specify a
  492. // wrong address. The server will discover that the client has a binding
  493. // but the address will not match.
  494. ASSERT_NO_THROW(client.doRebind());
  495. // Make sure that the server has discarded client's message. In such case,
  496. // the message sent back to the client should be NULL.
  497. EXPECT_TRUE(client.getContext().response_)
  498. << "The server discarded the Rebind message, while it should have"
  499. " sent a response indicating that the client should stop using the"
  500. " lease, by setting lifetime values to 0.";
  501. // Get the client's lease.
  502. ASSERT_EQ(1, client.getLeaseNum());
  503. Lease6 lease_client2 = client.getLease(0);
  504. // The lifetimes should be set to 0, as an explicit notification to the
  505. // client to stop using invalid prefix.
  506. EXPECT_EQ(0, lease_client2.valid_lft_);
  507. EXPECT_EQ(0, lease_client2.preferred_lft_);
  508. // Check that server still has the same lease.
  509. Lease6Ptr lease_server = checkLease(lease_client);
  510. EXPECT_TRUE(lease_server);
  511. // Make sure that the lease in the data base hasn't been addected.
  512. EXPECT_NE(0, lease_server->valid_lft_);
  513. EXPECT_NE(0, lease_server->preferred_lft_);
  514. }
  515. // Check that the server extends the lease for the client having a prefix.
  516. TEST_F(RebindTest, directClientPD) {
  517. Dhcp6Client client;
  518. // Configure client to request IA_PD.
  519. client.usePD();
  520. // Make 4-way exchange to get the lease.
  521. ASSERT_NO_FATAL_FAILURE(requestLease(4, 2, client));
  522. // Keep the client's lease for future reference.
  523. Lease6 lease_client = client.getLease(0);
  524. // Send Rebind message to the server.
  525. ASSERT_NO_THROW(client.doRebind());
  526. // The client should still have one lease which belong to one of the
  527. // subnets.
  528. ASSERT_EQ(1, client.getLeaseNum());
  529. Lease6 lease_client2 = client.getLease(0);
  530. ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_,
  531. ClientClasses()));
  532. // The client's lease should have been extended. The client will
  533. // update the cltt to current time when the lease gets extended.
  534. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  535. // Make sure, that the client's lease matches the lease held by the
  536. // server.
  537. Lease6Ptr lease_server2 = checkLease(lease_client2);
  538. EXPECT_TRUE(lease_server2);
  539. }
  540. // Check that the prefix lifetime is not extended for the client in case
  541. // the configuration has been changed such, that the subnet he is using
  542. // doesn't exist anymore.
  543. TEST_F(RebindTest, directClientPDChangingSubnet) {
  544. Dhcp6Client client;
  545. // Configure client to request IA_PD.
  546. client.usePD();
  547. // Make 4-way exchange to get the lease.
  548. ASSERT_NO_FATAL_FAILURE(requestLease(4, 2, client));
  549. // Keep the client's lease for future reference.
  550. Lease6 lease_client = client.getLease(0);
  551. // Reconfigure the server so as the new subnet is served on the
  552. // client's interface. Note that there will also be a new subnet
  553. // id assigned to the subnet on this interface.
  554. configure(REBIND_CONFIGS[5], *client.getServer());
  555. // Try to rebind, using the address that the client had acquired using
  556. // previous server configuration.
  557. ASSERT_NO_THROW(client.doRebind());
  558. // Make sure that the server has discarded client's message. In such case,
  559. // the message sent back to the client should be NULL.
  560. EXPECT_FALSE(client.getContext().response_)
  561. << "The server responded to the Rebind message, while it should have"
  562. " discarded it because there is no binding for the client.";
  563. // We are expecting that the server didn't extend the lease because
  564. // the address that client is using doesn't match the new subnet.
  565. // But, the client still has an old lease.
  566. ASSERT_EQ(1, client.getLeaseNum());
  567. Lease6 lease_client2 = client.getLease(0);
  568. // The current lease should be exactly the same as old lease,
  569. // because server shouldn't have extended.
  570. EXPECT_TRUE(lease_client == lease_client2);
  571. // Make sure, that the lease that client has, is matching the lease
  572. // in the lease database.
  573. Lease6Ptr lease_server2 = checkLease(lease_client2);
  574. EXPECT_TRUE(lease_server2);
  575. }
  576. // Check that the prefix lifetime is not extended for the client when the
  577. // IAID used in the Rebind is not matching the one recorded by the server
  578. // for the particular client.
  579. TEST_F(RebindTest, directClientPDChangingIAID) {
  580. Dhcp6Client client;
  581. // Configure client to request IA_PD.
  582. client.usePD();
  583. // Make 4-way exchange to get the lease.
  584. ASSERT_NO_FATAL_FAILURE(requestLease(4, 2, client));
  585. // Keep the client's lease for future reference.
  586. Lease6 lease_client = client.getLease(0);
  587. // Modify the IAID of the lease record that client stores. By adding
  588. // one to IAID we guarantee that the IAID will change.
  589. ++client.config_.leases_[0].lease_.iaid_;
  590. // Try to Rebind. Note that client will use a different IAID (which
  591. // is not matching IAID that server retains for the client). This is
  592. // a condition described in RFC3633, section 12.2 as the server finds
  593. // no binding for the client. It is an indication that some other
  594. // server has probably allocated the lease for the client. Hence, our
  595. // server should discard the message.
  596. ASSERT_NO_THROW(client.doRebind());
  597. // Make sure that the server has discarded client's message. In such case,
  598. // the message sent back to the client should be NULL.
  599. EXPECT_FALSE(client.getContext().response_)
  600. << "The server responded to the Rebind message, while it should have"
  601. " discarded it because there is no binding for the client.";
  602. // Check that server still has the same lease.
  603. Lease6Ptr lease_server = checkLease(lease_client);
  604. EXPECT_TRUE(lease_server);
  605. }
  606. // Check that the prefix lifetime is not extended for the client when the
  607. // prefix used in Rebind message doesn't match the one that client has.
  608. TEST_F(RebindTest, directClientPDChangingPrefix) {
  609. Dhcp6Client client;
  610. // Configure client to request IA_PD.
  611. client.usePD();
  612. // Make 4-way exchange to get the lease.
  613. ASSERT_NO_FATAL_FAILURE(requestLease(4, 2, client));
  614. // Keep the client's lease for future reference.
  615. Lease6 lease_client = client.getLease(0);
  616. // Modify the Prefix of the lease record that client stores. The server
  617. // should check that the prefix is invalid (hasn't been allocated for
  618. // the particular IAID).
  619. ASSERT_NE(client.config_.leases_[0].lease_.addr_,
  620. IOAddress("2001:db8:1:10::"));
  621. client.config_.leases_[0].lease_.addr_ = IOAddress("2001:db8:1:10::");
  622. // Try to Rebind. The client will use correct IAID but will specify a
  623. // wrong prefix. The server will discover that the client has a binding
  624. // but the prefix will not match. According to the RFC3633, section 12.2.
  625. // the server has to return the lease with lifetimes set to 0, when there
  626. // is a binding for the client but the prefix doesn't match.
  627. ASSERT_NO_THROW(client.doRebind());
  628. // Make sure that the server has discarded client's message. In such case,
  629. // the message sent back to the client should be NULL.
  630. EXPECT_TRUE(client.getContext().response_)
  631. << "The server discarded the Rebind message, while it should have"
  632. " sent a response indicating that the client should stop using the"
  633. " lease, by setting lifetime values to 0.";
  634. // Get the client's lease.
  635. ASSERT_EQ(1, client.getLeaseNum());
  636. Lease6 lease_client2 = client.getLease(0);
  637. // The lifetimes should be set to 0, as an explicit notification to the
  638. // client to stop using invalid prefix.
  639. EXPECT_EQ(0, lease_client2.valid_lft_);
  640. EXPECT_EQ(0, lease_client2.preferred_lft_);
  641. // Check that server still has the same lease.
  642. Lease6Ptr lease_server = checkLease(lease_client);
  643. ASSERT_TRUE(lease_server);
  644. // Make sure that the lease in the data base hasn't been addected.
  645. EXPECT_NE(0, lease_server->valid_lft_);
  646. EXPECT_NE(0, lease_server->preferred_lft_);
  647. }
  648. /// @todo Extend PD tests for relayed messages.
  649. /// @todo Extend PD tests to cover same prefix buyt different length.
  650. // This test checks that the Rebind message is discarded by the server if it
  651. // has been sent to unicast address (RFC3315, section 15).
  652. TEST_F(RebindTest, unicast) {
  653. Dhcp6Client client;
  654. // Configure client to request IA_NA.
  655. client.useNA();
  656. // Make 4-way exchange to get the lease.
  657. ASSERT_NO_FATAL_FAILURE(requestLease(0, 2, client));
  658. // Keep the client's lease for future reference.
  659. Lease6 lease_client = client.getLease(0);
  660. // Set the unicast destination address for the Rebind message.
  661. // The Rebind should be discarded when sent to unicast address,
  662. // according to section 15 of RFC3315.
  663. client.setDestAddress(IOAddress("2001:db8:1::1"));
  664. // Send the Rebind message to a unicast address.
  665. ASSERT_NO_THROW(client.doRebind());
  666. // The client's lease should remain with no change (shouldn't be extended)
  667. // because server is supposed to drop the message sent to a unicast address.
  668. ASSERT_EQ(1, client.getLeaseNum());
  669. Lease6 lease_client2 = client.getLease(0);
  670. ASSERT_TRUE(lease_client2 == lease_client);
  671. // Check that server still has the lease.
  672. Lease6Ptr lease_server2 = checkLease(lease_client2);
  673. EXPECT_TRUE(lease_server2);
  674. // Make sure that the server has discarded client's message. In such case,
  675. // the message sent back to the client should be NULL.
  676. EXPECT_FALSE(client.getContext().response_);
  677. }
  678. // This test checks that the relayed Rebind message is processed by the server
  679. // when sent to unicast address.
  680. TEST_F(RebindTest, relayedUnicast) {
  681. Dhcp6Client client;
  682. // Configure client to request IA_NA.
  683. client.useNA();
  684. // Configure DHCPv6 client to simulate sending the message through a relay
  685. // agent. The default link-addr is 3001:1::1. This address should be used
  686. // by the server to pick the suitable subnet.
  687. client.useRelay();
  688. // Make 4-way exchange to get the lease. Pick the configuration #2 as it
  689. // specifies the subnet for the relay agent's link address.
  690. ASSERT_NO_FATAL_FAILURE(requestLease(2, 2, client));
  691. // Keep the client's lease for future reference.
  692. Lease6 lease_client = client.getLease(0);
  693. // Set the unicast destination address.
  694. client.setDestAddress(IOAddress("2001:db8:1::1"));
  695. // Send Rebind message to the server.
  696. ASSERT_NO_THROW(client.doRebind());
  697. // The client should still have one lease which belongs to one of the
  698. // subnets.
  699. ASSERT_EQ(1, client.getLeaseNum());
  700. Lease6 lease_client2 = client.getLease(0);
  701. ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_,
  702. ClientClasses()));
  703. // The client's lease should have been extended. The client will
  704. // update the cltt to current time when the lease gets extended.
  705. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
  706. // Make sure, that the client's lease matches the lease held by the
  707. // server.
  708. Lease6Ptr lease_server2 = checkLease(lease_client2);
  709. EXPECT_TRUE(lease_server2);
  710. }
  711. } // end of anonymous namespace