subnet_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. // Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <asiolink/io_address.h>
  16. #include <dhcp/option.h>
  17. #include <dhcp/dhcp6.h>
  18. #include <dhcpsrv/subnet.h>
  19. #include <exceptions/exceptions.h>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <gtest/gtest.h>
  22. // don't import the entire boost namespace. It will unexpectedly hide uint8_t
  23. // for some systems.
  24. using boost::scoped_ptr;
  25. using namespace isc;
  26. using namespace isc::dhcp;
  27. using namespace isc::asiolink;
  28. namespace {
  29. TEST(Subnet4Test, constructor) {
  30. EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
  31. 1, 2, 3));
  32. EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
  33. BadValue); // invalid prefix length
  34. EXPECT_THROW(Subnet4 subnet3(IOAddress("2001:db8::1"), 24, 1, 2, 3),
  35. BadValue); // IPv6 addresses are not allowed in Subnet4
  36. }
  37. TEST(Subnet4Test, in_range) {
  38. Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
  39. EXPECT_EQ(1000, subnet.getT1());
  40. EXPECT_EQ(2000, subnet.getT2());
  41. EXPECT_EQ(3000, subnet.getValid());
  42. EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0")));
  43. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0")));
  44. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.1")));
  45. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.255")));
  46. EXPECT_FALSE(subnet.inRange(IOAddress("192.0.3.0")));
  47. EXPECT_FALSE(subnet.inRange(IOAddress("0.0.0.0")));
  48. EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255")));
  49. }
  50. TEST(Subnet4Test, Pool4InSubnet4) {
  51. Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
  52. PoolPtr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
  53. PoolPtr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
  54. PoolPtr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
  55. subnet->addPool(pool1);
  56. // If there's only one pool, get that pool
  57. PoolPtr mypool = subnet->getAnyPool(Pool::TYPE_V4);
  58. EXPECT_EQ(mypool, pool1);
  59. subnet->addPool(pool2);
  60. subnet->addPool(pool3);
  61. // If there are more than one pool and we didn't provide hint, we
  62. // should get the first pool
  63. mypool = subnet->getAnyPool(Pool::TYPE_V4);
  64. EXPECT_EQ(mypool, pool1);
  65. // If we provide a hint, we should get a pool that this hint belongs to
  66. mypool = subnet->getPool(Pool::TYPE_V4, IOAddress("192.1.2.195"));
  67. EXPECT_EQ(mypool, pool3);
  68. }
  69. TEST(Subnet4Test, Subnet4_Pool4_checks) {
  70. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  71. // this one is in subnet
  72. Pool4Ptr pool1(new Pool4(IOAddress("192.255.0.0"), 16));
  73. subnet->addPool(pool1);
  74. // this one is larger than the subnet!
  75. Pool4Ptr pool2(new Pool4(IOAddress("193.0.0.0"), 24));
  76. EXPECT_THROW(subnet->addPool(pool2), BadValue);
  77. // this one is totally out of blue
  78. Pool4Ptr pool3(new Pool4(IOAddress("1.2.3.4"), 16));
  79. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  80. }
  81. TEST(Subnet4Test, addInvalidOption) {
  82. // Create the V4 subnet.
  83. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  84. // Some dummy option code.
  85. uint16_t code = 100;
  86. // Create option with invalid universe (V6 instead of V4).
  87. // Attempt to add this option should result in exception.
  88. OptionPtr option1(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  89. EXPECT_THROW(subnet->addOption(option1, false, "dhcp4"),
  90. isc::BadValue);
  91. // Create NULL pointer option. Attempt to add NULL option
  92. // should result in exception.
  93. OptionPtr option2;
  94. ASSERT_FALSE(option2);
  95. EXPECT_THROW(subnet->addOption(option2, false, "dhcp4"),
  96. isc::BadValue);
  97. }
  98. // This test verifies that inRange() and inPool() methods work properly.
  99. TEST(Subnet4Test, inRangeinPool) {
  100. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.0.0"), 8, 1, 2, 3));
  101. // this one is in subnet
  102. Pool4Ptr pool1(new Pool4(IOAddress("192.2.0.0"), 16));
  103. subnet->addPool(pool1);
  104. // 192.1.1.1 belongs to the subnet...
  105. EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
  106. // ... but it does not belong to any pool within
  107. EXPECT_FALSE(subnet->inPool(IOAddress("192.1.1.1")));
  108. // the last address that is in range, but out of pool
  109. EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
  110. EXPECT_FALSE(subnet->inPool(IOAddress("192.1.255.255")));
  111. // the first address that is in range, in pool
  112. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
  113. EXPECT_TRUE (subnet->inPool(IOAddress("192.2.0.0")));
  114. // let's try something in the middle as well
  115. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
  116. EXPECT_TRUE (subnet->inPool(IOAddress("192.2.3.4")));
  117. // the last address that is in range, in pool
  118. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
  119. EXPECT_TRUE (subnet->inPool(IOAddress("192.2.255.255")));
  120. // the first address that is in range, but out of pool
  121. EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
  122. EXPECT_FALSE(subnet->inPool(IOAddress("192.3.0.0")));
  123. }
  124. // This test checks if the toText() method returns text representation
  125. TEST(Subnet4Test, toText) {
  126. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  127. EXPECT_EQ("192.0.2.0/24", subnet->toText());
  128. }
  129. // This test checks if the get() method returns proper parameters
  130. TEST(Subnet4Test, get) {
  131. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 28, 1, 2, 3));
  132. EXPECT_EQ("192.0.2.0", subnet->get().first.toText());
  133. EXPECT_EQ(28, subnet->get().second);
  134. }
  135. // Checks if last allocated address/prefix is stored/retrieved properly
  136. TEST(Subnet4Test, lastAllocated) {
  137. IOAddress addr("192.0.2.17");
  138. IOAddress last("192.0.2.255");
  139. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  140. // Check initial conditions (all should be set to the last address in range)
  141. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_V4).toText());
  142. // Now set last allocated for IA
  143. EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_V4, addr));
  144. EXPECT_EQ(addr.toText(), subnet->getLastAllocated(Pool::TYPE_V4).toText());
  145. // No, you can't set the last allocated IPv6 address in IPv4 subnet
  146. EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_IA, addr), BadValue);
  147. EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_TA, addr), BadValue);
  148. EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_PD, addr), BadValue);
  149. }
  150. // Checks if the V4 is the only allowed type for Pool4 and if getPool()
  151. // is working properly.
  152. TEST(Subnet4Test, PoolType) {
  153. Subnet4Ptr subnet(new Subnet4(IOAddress("192.2.0.0"), 16, 1, 2, 3));
  154. PoolPtr pool1(new Pool4(IOAddress("192.2.1.0"), 24));
  155. PoolPtr pool2(new Pool4(IOAddress("192.2.2.0"), 24));
  156. PoolPtr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
  157. PoolPtr pool4(new Pool6(Pool6::TYPE_TA, IOAddress("2001:db8:1:4::"), 64));
  158. PoolPtr pool5(new Pool6(Pool6::TYPE_PD, IOAddress("2001:db8:1:1::"), 64));
  159. // There should be no pools of any type by default
  160. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_V4));
  161. // It should not be possible to ask for V6 pools in Subnet4
  162. EXPECT_THROW(subnet->getAnyPool(Pool::TYPE_IA), BadValue);
  163. EXPECT_THROW(subnet->getAnyPool(Pool::TYPE_TA), BadValue);
  164. EXPECT_THROW(subnet->getAnyPool(Pool::TYPE_PD), BadValue);
  165. // Let's add a single V4 pool and check that it can be retrieved
  166. subnet->addPool(pool1);
  167. // If there's only one IA pool, get that pool (without and with hint)
  168. EXPECT_EQ(pool1, subnet->getAnyPool(Pool::TYPE_V4));
  169. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_V4, IOAddress("192.0.1.167")));
  170. // Let's add additional V4 pool
  171. subnet->addPool(pool2);
  172. // Try without hints
  173. EXPECT_EQ(pool1, subnet->getAnyPool(Pool::TYPE_V4));
  174. // Try with valid hints
  175. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_V4, IOAddress("192.2.1.5")));
  176. EXPECT_EQ(pool2, subnet->getPool(Pool::TYPE_V4, IOAddress("192.2.2.254")));
  177. // Try with bogus hints (hints should be ingored)
  178. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_V4, IOAddress("10.1.1.1")));
  179. // Trying to add Pool6 to Subnet4 is a big no,no!
  180. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  181. EXPECT_THROW(subnet->addPool(pool4), BadValue);
  182. EXPECT_THROW(subnet->addPool(pool5), BadValue);
  183. }
  184. // Tests for Subnet6
  185. TEST(Subnet6Test, constructor) {
  186. EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
  187. 1, 2, 3, 4));
  188. EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
  189. BadValue); // invalid prefix length
  190. EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
  191. BadValue); // IPv4 addresses are not allowed in Subnet6
  192. }
  193. TEST(Subnet6Test, in_range) {
  194. Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
  195. EXPECT_EQ(1000, subnet.getT1());
  196. EXPECT_EQ(2000, subnet.getT2());
  197. EXPECT_EQ(3000, subnet.getPreferred());
  198. EXPECT_EQ(4000, subnet.getValid());
  199. EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
  200. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
  201. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::1")));
  202. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff")));
  203. EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:1:1::")));
  204. EXPECT_FALSE(subnet.inRange(IOAddress("::")));
  205. }
  206. TEST(Subnet6Test, Pool6InSubnet6) {
  207. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  208. PoolPtr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
  209. PoolPtr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:2::"), 64));
  210. PoolPtr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:3::"), 64));
  211. subnet->addPool(pool1);
  212. // If there's only one pool, get that pool
  213. PoolPtr mypool = subnet->getAnyPool(Pool::TYPE_IA);
  214. EXPECT_EQ(mypool, pool1);
  215. subnet->addPool(pool2);
  216. subnet->addPool(pool3);
  217. // If there are more than one pool and we didn't provide hint, we
  218. // should get the first pool
  219. mypool = subnet->getAnyPool(Pool::TYPE_IA);
  220. EXPECT_EQ(mypool, pool1);
  221. // If we provide a hint, we should get a pool that this hint belongs to
  222. mypool = subnet->getPool(Pool::TYPE_IA, IOAddress("2001:db8:1:3::dead:beef"));
  223. EXPECT_EQ(mypool, pool3);
  224. }
  225. // Check if Subnet6 supports different types of pools properly.
  226. TEST(Subnet6Test, PoolTypes) {
  227. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  228. PoolPtr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
  229. PoolPtr pool2(new Pool6(Pool6::TYPE_TA, IOAddress("2001:db8:1:2::"), 64));
  230. PoolPtr pool3(new Pool6(Pool6::TYPE_PD, IOAddress("2001:db8:1:3::"), 64));
  231. PoolPtr pool4(new Pool6(Pool6::TYPE_PD, IOAddress("2001:db8:1:4::"), 64));
  232. PoolPtr pool5(new Pool4(IOAddress("192.0.2.0"), 24));
  233. // There should be no pools of any type by default
  234. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_IA));
  235. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_TA));
  236. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_PD));
  237. // Trying to get IPv4 pool from Subnet6 is not allowed
  238. EXPECT_THROW(subnet->getAnyPool(Pool::TYPE_V4), BadValue);
  239. // Let's add a single IA pool and check that it can be retrieved
  240. subnet->addPool(pool1);
  241. // If there's only one IA pool, get that pool
  242. EXPECT_EQ(pool1, subnet->getAnyPool(Pool::TYPE_IA));
  243. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_IA, IOAddress("2001:db8:1:1::1")));
  244. // Check if pools of different type are not returned
  245. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_TA));
  246. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Pool::TYPE_PD));
  247. // We ask with good hints, but wrong types, should return nothing
  248. EXPECT_EQ(PoolPtr(), subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8:1:2::1")));
  249. EXPECT_EQ(PoolPtr(), subnet->getPool(Pool::TYPE_TA, IOAddress("2001:db8:1:3::1")));
  250. // Let's add TA and PD pools
  251. subnet->addPool(pool2);
  252. subnet->addPool(pool3);
  253. // Try without hints
  254. EXPECT_EQ(pool1, subnet->getAnyPool(Pool::TYPE_IA));
  255. EXPECT_EQ(pool2, subnet->getAnyPool(Pool::TYPE_TA));
  256. EXPECT_EQ(pool3, subnet->getAnyPool(Pool::TYPE_PD));
  257. // Try with valid hints
  258. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_IA, IOAddress("2001:db8:1:1::1")));
  259. EXPECT_EQ(pool2, subnet->getPool(Pool::TYPE_TA, IOAddress("2001:db8:1:2::1")));
  260. EXPECT_EQ(pool3, subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8:1:3::1")));
  261. // Try with bogus hints (hints should be ingored)
  262. EXPECT_EQ(pool1, subnet->getPool(Pool::TYPE_IA, IOAddress("2001:db8:1:7::1")));
  263. EXPECT_EQ(pool2, subnet->getPool(Pool::TYPE_TA, IOAddress("2001:db8:1:7::1")));
  264. EXPECT_EQ(pool3, subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8:1:7::1")));
  265. // Let's add a second PD pool
  266. subnet->addPool(pool4);
  267. // Without hints, it should return the first pool
  268. EXPECT_EQ(pool3, subnet->getAnyPool(Pool::TYPE_PD));
  269. // With valid hint, it should return that hint
  270. EXPECT_EQ(pool3, subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8:1:3::1")));
  271. EXPECT_EQ(pool4, subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8:1:4::1")));
  272. // With invalid hint, it should return the first pool
  273. EXPECT_EQ(pool3, subnet->getPool(Pool::TYPE_PD, IOAddress("2001:db8::123")));
  274. // Adding Pool4 to Subnet6 is a big no, no!
  275. EXPECT_THROW(subnet->addPool(pool5), BadValue);
  276. }
  277. TEST(Subnet6Test, Subnet6_Pool6_checks) {
  278. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  279. // this one is in subnet
  280. Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
  281. subnet->addPool(pool1);
  282. // this one is larger than the subnet!
  283. Pool6Ptr pool2(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::"), 48));
  284. EXPECT_THROW(subnet->addPool(pool2), BadValue);
  285. // this one is totally out of blue
  286. Pool6Ptr pool3(new Pool6(Pool6::TYPE_IA, IOAddress("3000::"), 16));
  287. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  288. Pool6Ptr pool4(new Pool6(Pool6::TYPE_IA, IOAddress("4001:db8:1::"), 80));
  289. EXPECT_THROW(subnet->addPool(pool4), BadValue);
  290. }
  291. TEST(Subnet6Test, addOptions) {
  292. // Create as subnet to add options to it.
  293. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  294. // Differentiate options by their codes (100-109)
  295. for (uint16_t code = 100; code < 110; ++code) {
  296. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  297. ASSERT_NO_THROW(subnet->addOption(option, false, "dhcp6"));
  298. }
  299. // Add 7 options to another option space. The option codes partially overlap
  300. // with option codes that we have added to dhcp6 option space.
  301. for (uint16_t code = 105; code < 112; ++code) {
  302. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  303. ASSERT_NO_THROW(subnet->addOption(option, false, "isc"));
  304. }
  305. // Get options from the Subnet and check if all 10 are there.
  306. Subnet::OptionContainerPtr options = subnet->getOptionDescriptors("dhcp6");
  307. ASSERT_TRUE(options);
  308. ASSERT_EQ(10, options->size());
  309. // Validate codes of options added to dhcp6 option space.
  310. uint16_t expected_code = 100;
  311. for (Subnet::OptionContainer::const_iterator option_desc = options->begin();
  312. option_desc != options->end(); ++option_desc) {
  313. ASSERT_TRUE(option_desc->option);
  314. EXPECT_EQ(expected_code, option_desc->option->getType());
  315. ++expected_code;
  316. }
  317. options = subnet->getOptionDescriptors("isc");
  318. ASSERT_TRUE(options);
  319. ASSERT_EQ(7, options->size());
  320. // Validate codes of options added to isc option space.
  321. expected_code = 105;
  322. for (Subnet::OptionContainer::const_iterator option_desc = options->begin();
  323. option_desc != options->end(); ++option_desc) {
  324. ASSERT_TRUE(option_desc->option);
  325. EXPECT_EQ(expected_code, option_desc->option->getType());
  326. ++expected_code;
  327. }
  328. // Try to get options from a non-existing option space.
  329. options = subnet->getOptionDescriptors("abcd");
  330. ASSERT_TRUE(options);
  331. EXPECT_TRUE(options->empty());
  332. // Delete options from all spaces.
  333. subnet->delOptions();
  334. // Make sure that all options have been removed.
  335. options = subnet->getOptionDescriptors("dhcp6");
  336. ASSERT_TRUE(options);
  337. EXPECT_TRUE(options->empty());
  338. options = subnet->getOptionDescriptors("isc");
  339. ASSERT_TRUE(options);
  340. EXPECT_TRUE(options->empty());
  341. }
  342. TEST(Subnet6Test, addNonUniqueOptions) {
  343. // Create as subnet to add options to it.
  344. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  345. // Create a set of options with non-unique codes.
  346. for (int i = 0; i < 2; ++i) {
  347. // In the inner loop we create options with unique codes (100-109).
  348. for (uint16_t code = 100; code < 110; ++code) {
  349. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  350. ASSERT_NO_THROW(subnet->addOption(option, false, "dhcp6"));
  351. }
  352. }
  353. // Sanity check that all options are there.
  354. Subnet::OptionContainerPtr options = subnet->getOptionDescriptors("dhcp6");
  355. ASSERT_EQ(20, options->size());
  356. // Use container index #1 to get the options by their codes.
  357. Subnet::OptionContainerTypeIndex& idx = options->get<1>();
  358. // Look for the codes 100-109.
  359. for (uint16_t code = 100; code < 110; ++ code) {
  360. // For each code we should get two instances of options->
  361. std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
  362. Subnet::OptionContainerTypeIndex::const_iterator> range =
  363. idx.equal_range(code);
  364. // Distance between iterators indicates how many options
  365. // have been retured for the particular code.
  366. ASSERT_EQ(2, distance(range.first, range.second));
  367. // Check that returned options actually have the expected option code.
  368. for (Subnet::OptionContainerTypeIndex::const_iterator option_desc = range.first;
  369. option_desc != range.second; ++option_desc) {
  370. ASSERT_TRUE(option_desc->option);
  371. EXPECT_EQ(code, option_desc->option->getType());
  372. }
  373. }
  374. // Let's try to find some non-exiting option.
  375. const uint16_t non_existing_code = 150;
  376. std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
  377. Subnet::OptionContainerTypeIndex::const_iterator> range =
  378. idx.equal_range(non_existing_code);
  379. // Empty set is expected.
  380. EXPECT_EQ(0, distance(range.first, range.second));
  381. subnet->delOptions();
  382. options = subnet->getOptionDescriptors("dhcp6");
  383. EXPECT_EQ(0, options->size());
  384. }
  385. TEST(Subnet6Test, addInvalidOption) {
  386. // Create as subnet to add options to it.
  387. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  388. // Some dummy option code.
  389. uint16_t code = 100;
  390. // Create option with invalid universe (V4 instead of V6).
  391. // Attempt to add this option should result in exception.
  392. OptionPtr option1(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
  393. EXPECT_THROW(subnet->addOption(option1, false, "dhcp6"), isc::BadValue);
  394. // Create NULL pointer option. Attempt to add NULL option
  395. // should result in exception.
  396. OptionPtr option2;
  397. ASSERT_FALSE(option2);
  398. EXPECT_THROW(subnet->addOption(option2, false, "dhcp6"), isc::BadValue);
  399. }
  400. TEST(Subnet6Test, addPersistentOption) {
  401. // Create as subnet to add options to it.
  402. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  403. // Add 10 options to the subnet with option codes 100 - 109.
  404. for (uint16_t code = 100; code < 110; ++code) {
  405. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  406. // We create 10 options and want some of them to be flagged
  407. // persistent and some non-persistent. Persistent options are
  408. // those that server sends to clients regardless if they ask
  409. // for them or not. We pick 3 out of 10 options and mark them
  410. // non-persistent and 7 other options persistent.
  411. // Code values: 102, 105 and 108 are divisible by 3
  412. // and options with these codes will be flagged non-persistent.
  413. // Options with other codes will be flagged persistent.
  414. bool persistent = (code % 3) ? true : false;
  415. ASSERT_NO_THROW(subnet->addOption(option, persistent, "dhcp6"));
  416. }
  417. // Get added options from the subnet.
  418. Subnet::OptionContainerPtr options = subnet->getOptionDescriptors("dhcp6");
  419. // options->get<2> returns reference to container index #2. This
  420. // index is used to access options by the 'persistent' flag.
  421. Subnet::OptionContainerPersistIndex& idx = options->get<2>();
  422. // Get all persistent options->
  423. std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
  424. Subnet::OptionContainerPersistIndex::const_iterator> range_persistent =
  425. idx.equal_range(true);
  426. // 3 out of 10 options have been flagged persistent.
  427. ASSERT_EQ(7, distance(range_persistent.first, range_persistent.second));
  428. // Get all non-persistent options->
  429. std::pair<Subnet::OptionContainerPersistIndex::const_iterator,
  430. Subnet::OptionContainerPersistIndex::const_iterator> range_non_persistent =
  431. idx.equal_range(false);
  432. // 7 out of 10 options have been flagged persistent.
  433. ASSERT_EQ(3, distance(range_non_persistent.first, range_non_persistent.second));
  434. subnet->delOptions();
  435. options = subnet->getOptionDescriptors("dhcp6");
  436. EXPECT_EQ(0, options->size());
  437. }
  438. TEST(Subnet6Test, getOptionDescriptor) {
  439. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 56, 1, 2, 3, 4));
  440. // Add 10 options to a "dhcp6" option space in the subnet.
  441. for (uint16_t code = 100; code < 110; ++code) {
  442. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  443. ASSERT_NO_THROW(subnet->addOption(option, false, "dhcp6"));
  444. }
  445. // Check that we can get each added option descriptor using
  446. // individually.
  447. for (uint16_t code = 100; code < 110; ++code) {
  448. std::ostringstream stream;
  449. // First, try the invalid option space name.
  450. Subnet::OptionDescriptor desc = subnet->getOptionDescriptor("isc", code);
  451. // Returned descriptor should contain NULL option ptr.
  452. EXPECT_FALSE(desc.option);
  453. // Now, try the valid option space.
  454. desc = subnet->getOptionDescriptor("dhcp6", code);
  455. // Test that the option code matches the expected code.
  456. ASSERT_TRUE(desc.option);
  457. EXPECT_EQ(code, desc.option->getType());
  458. }
  459. }
  460. // This test verifies that inRange() and inPool() methods work properly.
  461. TEST(Subnet6Test, inRangeinPool) {
  462. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
  463. // this one is in subnet
  464. Pool6Ptr pool1(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8::10"),
  465. IOAddress("2001:db8::20")));
  466. subnet->addPool(pool1);
  467. // 192.1.1.1 belongs to the subnet...
  468. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
  469. // ... but it does not belong to any pool within
  470. EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::1")));
  471. // the last address that is in range, but out of pool
  472. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
  473. EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::f")));
  474. // the first address that is in range, in pool
  475. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
  476. EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::10")));
  477. // let's try something in the middle as well
  478. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
  479. EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::18")));
  480. // the last address that is in range, in pool
  481. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
  482. EXPECT_TRUE (subnet->inPool(IOAddress("2001:db8::20")));
  483. // the first address that is in range, but out of pool
  484. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
  485. EXPECT_FALSE(subnet->inPool(IOAddress("2001:db8::21")));
  486. }
  487. // This test checks if the toText() method returns text representation
  488. TEST(Subnet6Test, toText) {
  489. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  490. EXPECT_EQ("2001:db8::/32", subnet.toText());
  491. }
  492. // This test checks if the get() method returns proper parameters
  493. TEST(Subnet6Test, get) {
  494. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  495. EXPECT_EQ("2001:db8::", subnet.get().first.toText());
  496. EXPECT_EQ(32, subnet.get().second);
  497. }
  498. // This trivial test checks if interface name is stored properly
  499. // in Subnet6 objects.
  500. TEST(Subnet6Test, iface) {
  501. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  502. EXPECT_TRUE(subnet.getIface().empty());
  503. subnet.setIface("en1");
  504. EXPECT_EQ("en1", subnet.getIface());
  505. }
  506. // This trivial test checks if the interface-id option can be set and
  507. // later retrieved for a subnet6 object.
  508. TEST(Subnet6Test, interfaceId) {
  509. // Create as subnet to add options to it.
  510. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  511. EXPECT_FALSE(subnet->getInterfaceId());
  512. OptionPtr option(new Option(Option::V6, D6O_INTERFACE_ID, OptionBuffer(10, 0xFF)));
  513. subnet->setInterfaceId(option);
  514. EXPECT_EQ(option, subnet->getInterfaceId());
  515. }
  516. // Checks if last allocated address/prefix is stored/retrieved properly
  517. TEST(Subnet6Test, lastAllocated) {
  518. IOAddress ia("2001:db8:1::1");
  519. IOAddress ta("2001:db8:1::abcd");
  520. IOAddress pd("2001:db8:1::1234:5678");
  521. IOAddress last("2001:db8:1::ffff:ffff:ffff:ffff");
  522. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3, 4));
  523. // Check initial conditions (all should be set to the last address in range)
  524. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
  525. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
  526. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
  527. // Now set last allocated for IA
  528. EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_IA, ia));
  529. EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
  530. // TA and PD should be unchanged
  531. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
  532. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
  533. // Now set TA and PD
  534. EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_TA, ta));
  535. EXPECT_NO_THROW(subnet->setLastAllocated(Pool::TYPE_PD, pd));
  536. EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Pool::TYPE_IA).toText());
  537. EXPECT_EQ(ta.toText(), subnet->getLastAllocated(Pool::TYPE_TA).toText());
  538. EXPECT_EQ(pd.toText(), subnet->getLastAllocated(Pool::TYPE_PD).toText());
  539. // No, you can't set the last allocated IPv4 address in IPv6 subnet
  540. EXPECT_THROW(subnet->setLastAllocated(Pool::TYPE_V4, ia), BadValue);
  541. }
  542. };