subnet_unittest.cc 31 KB

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