cfgmgr_unittest.cc 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. // Copyright (C) 2012-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 <dhcpsrv/cfgmgr.h>
  16. #include <dhcpsrv/dhcp_parsers.h>
  17. #include <exceptions/exceptions.h>
  18. #include <dhcp/dhcp6.h>
  19. #include <dhcp/tests/iface_mgr_test_config.h>
  20. #include <gtest/gtest.h>
  21. #include <iostream>
  22. #include <sstream>
  23. #include <arpa/inet.h>
  24. using namespace std;
  25. using namespace isc::asiolink;
  26. using namespace isc::data;
  27. using namespace isc::dhcp;
  28. using namespace isc::dhcp::test;
  29. using namespace isc::util;
  30. using namespace isc;
  31. // don't import the entire boost namespace. It will unexpectedly hide uint8_t
  32. // for some systems.
  33. using boost::scoped_ptr;
  34. namespace {
  35. template <typename Storage>
  36. bool isZeroPosition(const Storage& storage, const std::string& param_name) {
  37. Element::Position position = storage.getPosition(param_name);
  38. return ((position.line_ == 0) && (position.pos_ == 0) &&
  39. (position.file_.empty()));
  40. }
  41. // This test verifies that BooleanStorage functions properly.
  42. TEST(ValueStorageTest, BooleanTesting) {
  43. BooleanStorage testStore;
  44. // Verify that we can add and retrieve parameters.
  45. testStore.setParam("firstBool", false, Element::Position("kea.conf", 123, 234));
  46. testStore.setParam("secondBool", true, Element::Position("keax.conf", 10, 20));
  47. EXPECT_FALSE(testStore.getParam("firstBool"));
  48. EXPECT_TRUE(testStore.getParam("secondBool"));
  49. EXPECT_EQ(123, testStore.getPosition("firstBool").line_);
  50. EXPECT_EQ(234, testStore.getPosition("firstBool").pos_);
  51. EXPECT_EQ("kea.conf", testStore.getPosition("firstBool").file_);
  52. EXPECT_EQ(10, testStore.getPosition("secondBool").line_);
  53. EXPECT_EQ(20, testStore.getPosition("secondBool").pos_);
  54. EXPECT_EQ("keax.conf", testStore.getPosition("secondBool").file_);
  55. // Verify that we can update parameters.
  56. testStore.setParam("firstBool", true, Element::Position("keax.conf", 555, 111));
  57. testStore.setParam("secondBool", false, Element::Position("kea.conf", 1, 3));
  58. EXPECT_TRUE(testStore.getParam("firstBool"));
  59. EXPECT_FALSE(testStore.getParam("secondBool"));
  60. EXPECT_EQ(555, testStore.getPosition("firstBool").line_);
  61. EXPECT_EQ(111, testStore.getPosition("firstBool").pos_);
  62. EXPECT_EQ("keax.conf", testStore.getPosition("firstBool").file_);
  63. EXPECT_EQ(1, testStore.getPosition("secondBool").line_);
  64. EXPECT_EQ(3, testStore.getPosition("secondBool").pos_);
  65. EXPECT_EQ("kea.conf", testStore.getPosition("secondBool").file_);
  66. // Verify that we can delete a parameter and it will no longer be found.
  67. testStore.delParam("firstBool");
  68. EXPECT_THROW(testStore.getParam("firstBool"), isc::dhcp::DhcpConfigError);
  69. // Verify that the "zero" position is returned when parameter doesn't exist.
  70. EXPECT_TRUE(isZeroPosition(testStore, "firstBool"));
  71. // Verify that the delete was safe and the store still operates.
  72. EXPECT_FALSE(testStore.getParam("secondBool"));
  73. EXPECT_EQ(1, testStore.getPosition("secondBool").line_);
  74. EXPECT_EQ(3, testStore.getPosition("secondBool").pos_);
  75. EXPECT_EQ("kea.conf", testStore.getPosition("secondBool").file_);
  76. // Verify that looking for a parameter that never existed throws.
  77. ASSERT_THROW(testStore.getParam("bogusBool"), isc::dhcp::DhcpConfigError);
  78. // Verify that the "zero" position is returned when parameter doesn't exist.
  79. EXPECT_TRUE(isZeroPosition(testStore, "bogusBool"));
  80. // Verify that attempting to delete a parameter that never existed does not throw.
  81. EXPECT_NO_THROW(testStore.delParam("bogusBool"));
  82. // Verify that we can empty the list.
  83. testStore.clear();
  84. EXPECT_THROW(testStore.getParam("secondBool"), isc::dhcp::DhcpConfigError);
  85. // Verify that the "zero" position is returned when parameter doesn't exist.
  86. EXPECT_TRUE(isZeroPosition(testStore, "secondBool"));
  87. }
  88. // This test verifies that Uint32Storage functions properly.
  89. TEST(ValueStorageTest, Uint32Testing) {
  90. Uint32Storage testStore;
  91. uint32_t int_one = 77;
  92. uint32_t int_two = 33;
  93. // Verify that we can add and retrieve parameters.
  94. testStore.setParam("firstInt", int_one, Element::Position("kea.conf", 123, 234));
  95. testStore.setParam("secondInt", int_two, Element::Position("keax.conf", 10, 20));
  96. EXPECT_EQ(testStore.getParam("firstInt"), int_one);
  97. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  98. EXPECT_EQ(123, testStore.getPosition("firstInt").line_);
  99. EXPECT_EQ(234, testStore.getPosition("firstInt").pos_);
  100. EXPECT_EQ("kea.conf", testStore.getPosition("firstInt").file_);
  101. EXPECT_EQ(10, testStore.getPosition("secondInt").line_);
  102. EXPECT_EQ(20, testStore.getPosition("secondInt").pos_);
  103. EXPECT_EQ("keax.conf", testStore.getPosition("secondInt").file_);
  104. // Verify that we can update parameters.
  105. testStore.setParam("firstInt", --int_one, Element::Position("keax.conf", 555, 111));
  106. testStore.setParam("secondInt", ++int_two, Element::Position("kea.conf", 1, 3));
  107. EXPECT_EQ(testStore.getParam("firstInt"), int_one);
  108. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  109. EXPECT_EQ(555, testStore.getPosition("firstInt").line_);
  110. EXPECT_EQ(111, testStore.getPosition("firstInt").pos_);
  111. EXPECT_EQ("keax.conf", testStore.getPosition("firstInt").file_);
  112. EXPECT_EQ(1, testStore.getPosition("secondInt").line_);
  113. EXPECT_EQ(3, testStore.getPosition("secondInt").pos_);
  114. EXPECT_EQ("kea.conf", testStore.getPosition("secondInt").file_);
  115. // Verify that we can delete a parameter and it will no longer be found.
  116. testStore.delParam("firstInt");
  117. EXPECT_THROW(testStore.getParam("firstInt"), isc::dhcp::DhcpConfigError);
  118. // Verify that the "zero" position is returned when parameter doesn't exist.
  119. EXPECT_TRUE(isZeroPosition(testStore, "firstInt"));
  120. // Verify that the delete was safe and the store still operates.
  121. EXPECT_EQ(testStore.getParam("secondInt"), int_two);
  122. EXPECT_EQ(1, testStore.getPosition("secondInt").line_);
  123. EXPECT_EQ(3, testStore.getPosition("secondInt").pos_);
  124. EXPECT_EQ("kea.conf", testStore.getPosition("secondInt").file_);
  125. // Verify that looking for a parameter that never existed throws.
  126. ASSERT_THROW(testStore.getParam("bogusInt"), isc::dhcp::DhcpConfigError);
  127. // Verify that attempting to delete a parameter that never existed does not throw.
  128. EXPECT_NO_THROW(testStore.delParam("bogusInt"));
  129. // Verify that the "zero" position is returned when parameter doesn't exist.
  130. EXPECT_TRUE(isZeroPosition(testStore, "bogusInt"));
  131. // Verify that we can empty the list.
  132. testStore.clear();
  133. EXPECT_THROW(testStore.getParam("secondInt"), isc::dhcp::DhcpConfigError);
  134. // Verify that the "zero" position is returned when parameter doesn't exist.
  135. EXPECT_TRUE(isZeroPosition(testStore, "secondInt"));
  136. }
  137. // This test verifies that StringStorage functions properly.
  138. TEST(ValueStorageTest, StringTesting) {
  139. StringStorage testStore;
  140. std::string string_one = "seventy-seven";
  141. std::string string_two = "thirty-three";
  142. // Verify that we can add and retrieve parameters.
  143. testStore.setParam("firstString", string_one,
  144. Element::Position("kea.conf", 123, 234));
  145. testStore.setParam("secondString", string_two,
  146. Element::Position("keax.conf", 10, 20));
  147. EXPECT_EQ(testStore.getParam("firstString"), string_one);
  148. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  149. EXPECT_EQ(123, testStore.getPosition("firstString").line_);
  150. EXPECT_EQ(234, testStore.getPosition("firstString").pos_);
  151. EXPECT_EQ("kea.conf", testStore.getPosition("firstString").file_);
  152. EXPECT_EQ(10, testStore.getPosition("secondString").line_);
  153. EXPECT_EQ(20, testStore.getPosition("secondString").pos_);
  154. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  155. // Verify that we can update parameters.
  156. string_one.append("-boo");
  157. string_two.append("-boo");
  158. testStore.setParam("firstString", string_one,
  159. Element::Position("kea.conf", 555, 111));
  160. testStore.setParam("secondString", string_two,
  161. Element::Position("keax.conf", 1, 3));
  162. EXPECT_EQ(testStore.getParam("firstString"), string_one);
  163. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  164. EXPECT_EQ(555, testStore.getPosition("firstString").line_);
  165. EXPECT_EQ(111, testStore.getPosition("firstString").pos_);
  166. EXPECT_EQ("kea.conf", testStore.getPosition("firstString").file_);
  167. EXPECT_EQ(1, testStore.getPosition("secondString").line_);
  168. EXPECT_EQ(3, testStore.getPosition("secondString").pos_);
  169. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  170. // Verify that we can delete a parameter and it will no longer be found.
  171. testStore.delParam("firstString");
  172. EXPECT_THROW(testStore.getParam("firstString"), isc::dhcp::DhcpConfigError);
  173. // Verify that the "zero" position is returned when parameter doesn't exist.
  174. EXPECT_TRUE(isZeroPosition(testStore, "firstString"));
  175. // Verify that the delete was safe and the store still operates.
  176. EXPECT_EQ(testStore.getParam("secondString"), string_two);
  177. EXPECT_EQ(1, testStore.getPosition("secondString").line_);
  178. EXPECT_EQ(3, testStore.getPosition("secondString").pos_);
  179. EXPECT_EQ("keax.conf", testStore.getPosition("secondString").file_);
  180. // Verify that looking for a parameter that never existed throws.
  181. ASSERT_THROW(testStore.getParam("bogusString"), isc::dhcp::DhcpConfigError);
  182. // Verify that attempting to delete a parameter that never existed does not throw.
  183. EXPECT_NO_THROW(testStore.delParam("bogusString"));
  184. // Verify that the "zero" position is returned when parameter doesn't exist.
  185. EXPECT_TRUE(isZeroPosition(testStore, "bogusString"));
  186. // Verify that we can empty the list.
  187. testStore.clear();
  188. EXPECT_THROW(testStore.getParam("secondString"), isc::dhcp::DhcpConfigError);
  189. // Verify that the "zero" position is returned when parameter doesn't exist.
  190. EXPECT_TRUE(isZeroPosition(testStore, "secondString"));
  191. }
  192. class CfgMgrTest : public ::testing::Test {
  193. public:
  194. CfgMgrTest() {
  195. // make sure we start with a clean configuration
  196. CfgMgr::instance().deleteSubnets4();
  197. CfgMgr::instance().deleteSubnets6();
  198. CfgMgr::instance().deleteOptionDefs();
  199. }
  200. /// @brief generates interface-id option based on provided text
  201. ///
  202. /// @param text content of the option to be created
  203. ///
  204. /// @return pointer to the option object created
  205. OptionPtr generateInterfaceId(const string& text) {
  206. OptionBuffer buffer(text.begin(), text.end());
  207. return OptionPtr(new Option(Option::V6, D6O_INTERFACE_ID, buffer));
  208. }
  209. ~CfgMgrTest() {
  210. // clean up after the test
  211. CfgMgr::instance().deleteSubnets4();
  212. CfgMgr::instance().deleteSubnets6();
  213. CfgMgr::instance().deleteOptionDefs();
  214. }
  215. /// used in client classification (or just empty container for other tests)
  216. isc::dhcp::ClientClasses classify_;
  217. };
  218. // Checks that there is a configuration structure available and that
  219. // it is empty by default.
  220. TEST_F(CfgMgrTest, configuration) {
  221. ConfigurationPtr configuration = CfgMgr::instance().getConfiguration();
  222. ASSERT_TRUE(configuration);
  223. EXPECT_TRUE(configuration->logging_info_.empty());
  224. }
  225. // This test verifies that multiple option definitions can be added
  226. // under different option spaces.
  227. TEST_F(CfgMgrTest, getOptionDefs) {
  228. CfgMgr& cfg_mgr = CfgMgr::instance();
  229. // Create a set of option definitions with codes between 100 and 109.
  230. for (uint16_t code = 100; code < 110; ++code) {
  231. std::ostringstream option_name;
  232. // Option name is unique, e.g. option-100, option-101 etc.
  233. option_name << "option-" << code;
  234. OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
  235. "uint16"));
  236. // Add option definition to "isc" option space.
  237. // Option codes are not duplicated so expect no error
  238. // when adding them.
  239. ASSERT_NO_THROW(cfg_mgr.addOptionDef(def, "isc"));
  240. }
  241. // Create a set of option definitions with codes between 105 and 114 and
  242. // add them to the different option space.
  243. for (uint16_t code = 105; code < 115; ++code) {
  244. std::ostringstream option_name;
  245. option_name << "option-" << code;
  246. OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
  247. "uint16"));
  248. ASSERT_NO_THROW(cfg_mgr.addOptionDef(def, "abcde"));
  249. }
  250. // Sanity check that all 10 option definitions are there.
  251. OptionDefContainerPtr option_defs1 = cfg_mgr.getOptionDefs("isc");
  252. ASSERT_TRUE(option_defs1);
  253. ASSERT_EQ(10, option_defs1->size());
  254. // Iterate over all option definitions and check that they have
  255. // valid codes. Also, their order should be the same as they
  256. // were added (codes 100-109).
  257. uint16_t code = 100;
  258. for (OptionDefContainer::const_iterator it = option_defs1->begin();
  259. it != option_defs1->end(); ++it, ++code) {
  260. OptionDefinitionPtr def(*it);
  261. ASSERT_TRUE(def);
  262. EXPECT_EQ(code, def->getCode());
  263. }
  264. // Sanity check that all 10 option definitions are there.
  265. OptionDefContainerPtr option_defs2 = cfg_mgr.getOptionDefs("abcde");
  266. ASSERT_TRUE(option_defs2);
  267. ASSERT_EQ(10, option_defs2->size());
  268. // Check that the option codes are valid.
  269. code = 105;
  270. for (OptionDefContainer::const_iterator it = option_defs2->begin();
  271. it != option_defs2->end(); ++it, ++code) {
  272. OptionDefinitionPtr def(*it);
  273. ASSERT_TRUE(def);
  274. EXPECT_EQ(code, def->getCode());
  275. }
  276. // Let's make one more check that the empty set is returned when
  277. // invalid option space is used.
  278. OptionDefContainerPtr option_defs3 = cfg_mgr.getOptionDefs("non-existing");
  279. ASSERT_TRUE(option_defs3);
  280. EXPECT_TRUE(option_defs3->empty());
  281. }
  282. // This test verifies that single option definition is correctly
  283. // returned with getOptionDef function.
  284. TEST_F(CfgMgrTest, getOptionDef) {
  285. CfgMgr& cfg_mgr = CfgMgr::instance();
  286. // Create a set of option definitions with codes between 100 and 109.
  287. for (uint16_t code = 100; code < 110; ++code) {
  288. std::ostringstream option_name;
  289. // Option name is unique, e.g. option-100, option-101 etc.
  290. option_name << "option-" << code;
  291. OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
  292. "uint16"));
  293. // Add option definition to "isc" option space.
  294. // Option codes are not duplicated so expect no error
  295. // when adding them.
  296. ASSERT_NO_THROW(cfg_mgr.addOptionDef(def, "isc"));
  297. }
  298. // Create a set of option definitions with codes between 105 and 114 and
  299. // add them to the different option space.
  300. for (uint16_t code = 105; code < 115; ++code) {
  301. std::ostringstream option_name;
  302. option_name << "option-other-" << code;
  303. OptionDefinitionPtr def(new OptionDefinition(option_name.str(), code,
  304. "uint16"));
  305. ASSERT_NO_THROW(cfg_mgr.addOptionDef(def, "abcde"));
  306. }
  307. // Try to get option definitions one by one using all codes
  308. // that we expect to be there.
  309. for (uint16_t code = 100; code < 110; ++code) {
  310. OptionDefinitionPtr def = cfg_mgr.getOptionDef("isc", code);
  311. ASSERT_TRUE(def);
  312. // Check that the option name is in the format of 'option-[code]'.
  313. // That way we make sure that the options that have the same codes
  314. // within different option spaces are different.
  315. std::ostringstream option_name;
  316. option_name << "option-" << code;
  317. EXPECT_EQ(option_name.str(), def->getName());
  318. EXPECT_EQ(code, def->getCode());
  319. }
  320. // Check that the option codes are valid.
  321. for (uint16_t code = 105; code < 115; ++code) {
  322. OptionDefinitionPtr def = cfg_mgr.getOptionDef("abcde", code);
  323. ASSERT_TRUE(def);
  324. // Check that the option name is in the format of 'option-other-[code]'.
  325. // That way we make sure that the options that have the same codes
  326. // within different option spaces are different.
  327. std::ostringstream option_name;
  328. option_name << "option-other-" << code;
  329. EXPECT_EQ(option_name.str(), def->getName());
  330. EXPECT_EQ(code, def->getCode());
  331. }
  332. // Check that an option definition can be added to the standard
  333. // (dhcp4 and dhcp6) option spaces when the option code is not
  334. // reserved by the standard option.
  335. OptionDefinitionPtr def6(new OptionDefinition("option-foo", 79, "uint16"));
  336. EXPECT_NO_THROW(cfg_mgr.addOptionDef(def6, "dhcp6"));
  337. OptionDefinitionPtr def4(new OptionDefinition("option-foo", 222, "uint16"));
  338. EXPECT_NO_THROW(cfg_mgr.addOptionDef(def4, "dhcp4"));
  339. // Try to query the option definition from an non-existing
  340. // option space and expect NULL pointer.
  341. OptionDefinitionPtr def = cfg_mgr.getOptionDef("non-existing", 56);
  342. EXPECT_FALSE(def);
  343. // Try to get the non-existing option definition from an
  344. // existing option space.
  345. EXPECT_FALSE(cfg_mgr.getOptionDef("isc", 56));
  346. }
  347. // This test verifies that it is not allowed to override a definition of the
  348. // standard option which has its definition defined in libdhcp++, but it is
  349. // allowed to create a definition for the standard option which doesn't have
  350. // its definition in libdhcp++.
  351. TEST_F(CfgMgrTest, overrideStdOptionDef) {
  352. CfgMgr& cfg_mgr = CfgMgr::instance();
  353. OptionDefinitionPtr def;
  354. // There is a definition for routers option in libdhcp++, so an attempt
  355. // to add (override) another definition for this option should fail.
  356. def.reset(new OptionDefinition("routers", DHO_ROUTERS, "uint32"));
  357. EXPECT_THROW(cfg_mgr.addOptionDef(def, "dhcp4"), isc::BadValue);
  358. /// @todo There is no definition for the NIS Server Addr option in
  359. /// libdhcp++. Once it is implemented it should be not allowed to
  360. /// add a custom definition for it. At the moment, it should be ok
  361. /// to add a definition for this option (using configuration mechanism)
  362. /// because we haven't implemented the one in libdhcp++.
  363. def.reset(new OptionDefinition("nis-server-addr", 65, "uint16"));
  364. EXPECT_NO_THROW(cfg_mgr.addOptionDef(def, "dhcp4"));
  365. // It is not allowed to override the definition of the option which
  366. // has its definition in the libdhcp++.
  367. def.reset(new OptionDefinition("sntp-servers", D6O_SNTP_SERVERS,
  368. "ipv4-address"));
  369. EXPECT_THROW(cfg_mgr.addOptionDef(def, "dhcp6"), isc::BadValue);
  370. // There is no definition for option 59 in libdhcp++ yet, so it should
  371. // be possible provide a custom definition.
  372. def.reset(new OptionDefinition("bootfile-url", 59, "uint32"));
  373. EXPECT_NO_THROW(cfg_mgr.addOptionDef(def, "dhcp6"));
  374. }
  375. // This test verifies that the function that adds new option definition
  376. // throws exceptions when arguments are invalid.
  377. TEST_F(CfgMgrTest, addOptionDefNegative) {
  378. CfgMgr& cfg_mgr = CfgMgr::instance();
  379. OptionDefinitionPtr def(new OptionDefinition("option-foo", 1000, "uint16"));
  380. // Try empty option space name.
  381. ASSERT_THROW(cfg_mgr.addOptionDef(def, ""), isc::BadValue);
  382. // Try NULL option definition.
  383. ASSERT_THROW(cfg_mgr.addOptionDef(OptionDefinitionPtr(), "isc"),
  384. isc::dhcp::MalformedOptionDefinition);
  385. // Try adding option definition twice and make sure that it
  386. // fails on the second attempt.
  387. ASSERT_NO_THROW(cfg_mgr.addOptionDef(def, "isc"));
  388. EXPECT_THROW(cfg_mgr.addOptionDef(def, "isc"), DuplicateOptionDefinition);
  389. }
  390. // This test verifies if the configuration manager is able to hold and return
  391. // valid subnets.
  392. TEST_F(CfgMgrTest, subnet4) {
  393. CfgMgr& cfg_mgr = CfgMgr::instance();
  394. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
  395. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
  396. Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
  397. // There shouldn't be any subnet configured at this stage
  398. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.0"), classify_));
  399. cfg_mgr.addSubnet4(subnet1);
  400. // Now we have only one subnet, any request will be served from it
  401. EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.63"),
  402. classify_));
  403. // Now we add more subnets and check that both old and new subnets
  404. // are accessible.
  405. cfg_mgr.addSubnet4(subnet2);
  406. cfg_mgr.addSubnet4(subnet3);
  407. EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("192.0.2.191"), classify_));
  408. EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.15"), classify_));
  409. EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.85"), classify_));
  410. // Try to find an address that does not belong to any subnet
  411. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.192"), classify_));
  412. // Check that deletion of the subnets works.
  413. cfg_mgr.deleteSubnets4();
  414. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.191"), classify_));
  415. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.15"), classify_));
  416. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.85"), classify_));
  417. }
  418. // This test verifies if the configuration manager is able to hold subnets with
  419. // their classifier information and return proper subnets, based on those
  420. // classes.
  421. TEST_F(CfgMgrTest, classifySubnet4) {
  422. CfgMgr& cfg_mgr = CfgMgr::instance();
  423. // Let's configure 3 subnets
  424. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
  425. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
  426. Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
  427. cfg_mgr.addSubnet4(subnet1);
  428. cfg_mgr.addSubnet4(subnet2);
  429. cfg_mgr.addSubnet4(subnet3);
  430. // Let's sanity check that we can use that configuration.
  431. EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_));
  432. EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_));
  433. EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_));
  434. // Client now belongs to bar class.
  435. classify_.insert("bar");
  436. // There are no class restrictions defined, so everything should work
  437. // as before
  438. EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_));
  439. EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_));
  440. EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_));
  441. // Now let's add client class restrictions.
  442. subnet1->allowClientClass("foo"); // Serve here only clients from foo class
  443. subnet2->allowClientClass("bar"); // Serve here only clients from bar class
  444. subnet3->allowClientClass("baz"); // Serve here only clients from baz class
  445. // The same check as above should result in client being served only in
  446. // bar class, i.e. subnet2
  447. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_));
  448. EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_));
  449. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_));
  450. // Now let's check that client with wrong class is not supported
  451. classify_.clear();
  452. classify_.insert("some_other_class");
  453. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_));
  454. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_));
  455. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_));
  456. // Finally, let's check that client without any classes is not supported
  457. classify_.clear();
  458. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_));
  459. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_));
  460. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_));
  461. }
  462. // This test verifies if the configuration manager is able to hold v4 subnets
  463. // with their relay address information and return proper subnets, based on
  464. // those addresses.
  465. TEST_F(CfgMgrTest, subnet4RelayOverride) {
  466. CfgMgr& cfg_mgr = CfgMgr::instance();
  467. // Let's configure 3 subnets
  468. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
  469. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
  470. Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
  471. cfg_mgr.addSubnet4(subnet1);
  472. cfg_mgr.addSubnet4(subnet2);
  473. cfg_mgr.addSubnet4(subnet3);
  474. // Check that without relay-info specified, subnets are not selected
  475. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.1"), classify_, true));
  476. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.2"), classify_, true));
  477. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.3"), classify_, true));
  478. // Now specify relay info
  479. subnet1->setRelayInfo(IOAddress("10.0.0.1"));
  480. subnet2->setRelayInfo(IOAddress("10.0.0.2"));
  481. subnet3->setRelayInfo(IOAddress("10.0.0.3"));
  482. // And try again. This time relay-info is there and should match.
  483. EXPECT_EQ(subnet1, cfg_mgr.getSubnet4(IOAddress("10.0.0.1"), classify_, true));
  484. EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("10.0.0.2"), classify_, true));
  485. EXPECT_EQ(subnet3, cfg_mgr.getSubnet4(IOAddress("10.0.0.3"), classify_, true));
  486. // Finally, check that the relay works only if hint provided is relay address
  487. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.1"), classify_, false));
  488. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.2"), classify_, false));
  489. EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("10.0.0.3"), classify_, false));
  490. }
  491. // This test verifies if the configuration manager is able to hold v6 subnets
  492. // with their relay address information and return proper subnets, based on
  493. // those addresses.
  494. TEST_F(CfgMgrTest, subnet6RelayOverride) {
  495. CfgMgr& cfg_mgr = CfgMgr::instance();
  496. // Let's configure 3 subnets
  497. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
  498. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
  499. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
  500. cfg_mgr.addSubnet6(subnet1);
  501. cfg_mgr.addSubnet6(subnet2);
  502. cfg_mgr.addSubnet6(subnet3);
  503. // Check that without relay-info specified, subnets are not selected
  504. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, true));
  505. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, true));
  506. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, true));
  507. // Now specify relay info
  508. subnet1->setRelayInfo(IOAddress("2001:db8:ff::1"));
  509. subnet2->setRelayInfo(IOAddress("2001:db8:ff::2"));
  510. subnet3->setRelayInfo(IOAddress("2001:db8:ff::3"));
  511. // And try again. This time relay-info is there and should match.
  512. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, true));
  513. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, true));
  514. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, true));
  515. // Finally, check that the relay works only if hint provided is relay address
  516. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, false));
  517. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, false));
  518. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, false));
  519. }
  520. // This test verifies if the configuration manager is able to hold and return
  521. // valid leases
  522. TEST_F(CfgMgrTest, classifySubnet6) {
  523. CfgMgr& cfg_mgr = CfgMgr::instance();
  524. // Let's configure 3 subnets
  525. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  526. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  527. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  528. cfg_mgr.addSubnet6(subnet1);
  529. cfg_mgr.addSubnet6(subnet2);
  530. cfg_mgr.addSubnet6(subnet3);
  531. // Let's sanity check that we can use that configuration.
  532. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  533. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_));
  534. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_));
  535. // Client now belongs to bar class.
  536. classify_.insert("bar");
  537. // There are no class restrictions defined, so everything should work
  538. // as before
  539. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  540. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_));
  541. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_));
  542. // Now let's add client class restrictions.
  543. subnet1->allowClientClass("foo"); // Serve here only clients from foo class
  544. subnet2->allowClientClass("bar"); // Serve here only clients from bar class
  545. subnet3->allowClientClass("baz"); // Serve here only clients from baz class
  546. // The same check as above should result in client being served only in
  547. // bar class, i.e. subnet2
  548. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  549. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_));
  550. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_));
  551. // Now let's check that client with wrong class is not supported
  552. classify_.clear();
  553. classify_.insert("some_other_class");
  554. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  555. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_));
  556. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_));
  557. // Finally, let's check that client without any classes is not supported
  558. classify_.clear();
  559. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  560. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_));
  561. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_));
  562. }
  563. // This test verifies if the configuration manager is able to hold, select
  564. // and return valid subnets, based on interface names along with client
  565. // classification.
  566. TEST_F(CfgMgrTest, classifySubnet6Interface) {
  567. CfgMgr& cfg_mgr = CfgMgr::instance();
  568. // Let's have an odd configuration: 3 shared subnets available on the
  569. // same direct link.
  570. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  571. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  572. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  573. subnet1->setIface("foo");
  574. subnet2->setIface("foo");
  575. subnet3->setIface("foo");
  576. cfg_mgr.addSubnet6(subnet1);
  577. cfg_mgr.addSubnet6(subnet2);
  578. cfg_mgr.addSubnet6(subnet3);
  579. // Regular client should get the first subnet, because it meets all
  580. // criteria (matching interface name, no class restrictions.
  581. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6("foo", classify_));
  582. // Now let's add class requirements for subnet1
  583. subnet1->allowClientClass("alpha");
  584. // Client should now get the subnet2, because he no longer meets
  585. // requirements for subnet1 (belongs to wrong class)
  586. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6("foo", classify_));
  587. // Now let's add (not matching) classes to the other two subnets
  588. subnet2->allowClientClass("beta");
  589. subnet3->allowClientClass("gamma");
  590. // No subnets are suitable, so nothing will be selected
  591. EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_));
  592. // Ok, let's add the client to gamme class, so he'll get a subnet
  593. classify_.insert("gamma");
  594. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6("foo", classify_));
  595. }
  596. // This test verifies if the configuration manager is able to hold, select
  597. // and return valid subnets, based on interface-id option inserted by relay,
  598. // along with client classification.
  599. TEST_F(CfgMgrTest, classifySubnet6InterfaceId) {
  600. CfgMgr& cfg_mgr = CfgMgr::instance();
  601. // Let's have an odd configuration: 3 shared subnets available via the
  602. // same remote relay with the same interface-id.
  603. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  604. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  605. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  606. OptionPtr ifaceid = generateInterfaceId("relay1.eth0");
  607. subnet1->setInterfaceId(ifaceid);
  608. subnet2->setInterfaceId(ifaceid);
  609. subnet3->setInterfaceId(ifaceid);
  610. cfg_mgr.addSubnet6(subnet1);
  611. cfg_mgr.addSubnet6(subnet2);
  612. cfg_mgr.addSubnet6(subnet3);
  613. // Regular client should get the first subnet, because it meets all
  614. // criteria (matching interface name, no class restrictions.
  615. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(ifaceid, classify_));
  616. // Now let's add class requirements for subnet1
  617. subnet1->allowClientClass("alpha");
  618. // Client should now get the subnet2, because he no longer meets
  619. // requirements for subnet1 (belongs to wrong class)
  620. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(ifaceid, classify_));
  621. // Now let's add (not matching) classes to the other two subnets
  622. subnet2->allowClientClass("beta");
  623. subnet3->allowClientClass("gamma");
  624. // No subnets are suitable, so nothing will be selected
  625. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid, classify_));
  626. // Ok, let's add the client to gamme class, so he'll get a subnet
  627. classify_.insert("gamma");
  628. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(ifaceid, classify_));
  629. }
  630. // This test verifies if the configuration manager is able to hold and return
  631. // valid leases
  632. TEST_F(CfgMgrTest, subnet6) {
  633. CfgMgr& cfg_mgr = CfgMgr::instance();
  634. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  635. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  636. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  637. // There shouldn't be any subnet configured at this stage
  638. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::1"), classify_));
  639. cfg_mgr.addSubnet6(subnet1);
  640. // Now we have only one subnet, any request will be served from it
  641. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::1"), classify_));
  642. // We used to allow getting a sole subnet if there was only one subnet
  643. // configured. That is no longer true. The code should not return
  644. // a subnet.
  645. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef"), classify_));
  646. cfg_mgr.addSubnet6(subnet2);
  647. cfg_mgr.addSubnet6(subnet3);
  648. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::123"), classify_));
  649. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::dead:beef"),
  650. classify_));
  651. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("5000::1"), classify_));
  652. // Check that deletion of the subnets works.
  653. cfg_mgr.deleteSubnets6();
  654. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_));
  655. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::123"), classify_));
  656. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::123"), classify_));
  657. }
  658. // This test verifies if the configuration manager is able to hold, select
  659. // and return valid subnets, based on interface names.
  660. TEST_F(CfgMgrTest, subnet6Interface) {
  661. CfgMgr& cfg_mgr = CfgMgr::instance();
  662. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  663. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  664. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  665. subnet1->setIface("foo");
  666. subnet2->setIface("bar");
  667. subnet3->setIface("foobar");
  668. // There shouldn't be any subnet configured at this stage
  669. EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_));
  670. cfg_mgr.addSubnet6(subnet1);
  671. // Now we have only one subnet, any request will be served from it
  672. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6("foo", classify_));
  673. // Check that the interface name is checked even when there is
  674. // only one subnet defined.
  675. EXPECT_FALSE(cfg_mgr.getSubnet6("bar", classify_));
  676. // We used to allow getting a sole subnet if there was only one subnet
  677. // configured. That is no longer true. The code should not return
  678. // a subnet.
  679. EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef"), classify_));
  680. cfg_mgr.addSubnet6(subnet2);
  681. cfg_mgr.addSubnet6(subnet3);
  682. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6("foobar", classify_));
  683. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6("bar", classify_));
  684. EXPECT_FALSE(cfg_mgr.getSubnet6("xyzzy", classify_)); // no such interface
  685. // Check that deletion of the subnets works.
  686. cfg_mgr.deleteSubnets6();
  687. EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_));
  688. EXPECT_FALSE(cfg_mgr.getSubnet6("bar", classify_));
  689. EXPECT_FALSE(cfg_mgr.getSubnet6("foobar", classify_));
  690. }
  691. // This test verifies if the configuration manager is able to hold, select
  692. // and return valid leases, based on interface-id option values
  693. TEST_F(CfgMgrTest, subnet6InterfaceId) {
  694. CfgMgr& cfg_mgr = CfgMgr::instance();
  695. Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4));
  696. Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4));
  697. Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4));
  698. // interface-id options used in subnets 1,2, and 3
  699. OptionPtr ifaceid1 = generateInterfaceId("relay1.eth0");
  700. OptionPtr ifaceid2 = generateInterfaceId("VL32");
  701. // That's a strange interface-id, but this is a real life example
  702. OptionPtr ifaceid3 = generateInterfaceId("ISAM144|299|ipv6|nt:vp:1:110");
  703. // bogus interface-id
  704. OptionPtr ifaceid_bogus = generateInterfaceId("non-existent");
  705. subnet1->setInterfaceId(ifaceid1);
  706. subnet2->setInterfaceId(ifaceid2);
  707. subnet3->setInterfaceId(ifaceid3);
  708. // There shouldn't be any subnet configured at this stage
  709. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid1, classify_));
  710. cfg_mgr.addSubnet6(subnet1);
  711. // If we have only a single subnet and the request came from a local
  712. // address, let's use that subnet
  713. EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(ifaceid1, classify_));
  714. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid2, classify_));
  715. cfg_mgr.addSubnet6(subnet2);
  716. cfg_mgr.addSubnet6(subnet3);
  717. EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(ifaceid3, classify_));
  718. EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(ifaceid2, classify_));
  719. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid_bogus, classify_));
  720. // Check that deletion of the subnets works.
  721. cfg_mgr.deleteSubnets6();
  722. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid1, classify_));
  723. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid2, classify_));
  724. EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid3, classify_));
  725. }
  726. // This test verifies that new DHCPv4 option spaces can be added to
  727. // the configuration manager and that duplicated option space is
  728. // rejected.
  729. TEST_F(CfgMgrTest, optionSpace4) {
  730. CfgMgr& cfg_mgr = CfgMgr::instance();
  731. // Create some option spaces.
  732. OptionSpacePtr space1(new OptionSpace("isc", false));
  733. OptionSpacePtr space2(new OptionSpace("xyz", true));
  734. // Add option spaces with different names and expect they
  735. // are accepted.
  736. ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space1));
  737. ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space2));
  738. // Validate that the option spaces have been added correctly.
  739. const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces4();
  740. ASSERT_EQ(2, spaces.size());
  741. EXPECT_FALSE(spaces.find("isc") == spaces.end());
  742. EXPECT_FALSE(spaces.find("xyz") == spaces.end());
  743. // Create another option space with the name that duplicates
  744. // the existing option space.
  745. OptionSpacePtr space3(new OptionSpace("isc", true));
  746. // Expect that the duplicate option space is rejected.
  747. ASSERT_THROW(
  748. cfg_mgr.addOptionSpace4(space3), isc::dhcp::InvalidOptionSpace
  749. );
  750. /// @todo decode if a duplicate vendor space is allowed.
  751. }
  752. // This test verifies that new DHCPv6 option spaces can be added to
  753. // the configuration manager and that duplicated option space is
  754. // rejected.
  755. TEST_F(CfgMgrTest, optionSpace6) {
  756. CfgMgr& cfg_mgr = CfgMgr::instance();
  757. // Create some option spaces.
  758. OptionSpacePtr space1(new OptionSpace("isc", false));
  759. OptionSpacePtr space2(new OptionSpace("xyz", true));
  760. // Add option spaces with different names and expect they
  761. // are accepted.
  762. ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space1));
  763. ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space2));
  764. // Validate that the option spaces have been added correctly.
  765. const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces6();
  766. ASSERT_EQ(2, spaces.size());
  767. EXPECT_FALSE(spaces.find("isc") == spaces.end());
  768. EXPECT_FALSE(spaces.find("xyz") == spaces.end());
  769. // Create another option space with the name that duplicates
  770. // the existing option space.
  771. OptionSpacePtr space3(new OptionSpace("isc", true));
  772. // Expect that the duplicate option space is rejected.
  773. ASSERT_THROW(
  774. cfg_mgr.addOptionSpace6(space3), isc::dhcp::InvalidOptionSpace
  775. );
  776. /// @todo decide if a duplicate vendor space is allowed.
  777. }
  778. // This test verifies that RFC6842 (echo client-id) compatibility may be
  779. // configured.
  780. TEST_F(CfgMgrTest, echoClientId) {
  781. CfgMgr& cfg_mgr = CfgMgr::instance();
  782. // Check that the default is true
  783. EXPECT_TRUE(cfg_mgr.echoClientId());
  784. // Check that it can be modified to false
  785. cfg_mgr.echoClientId(false);
  786. EXPECT_FALSE(cfg_mgr.echoClientId());
  787. // Check that the default value can be restored
  788. cfg_mgr.echoClientId(true);
  789. EXPECT_TRUE(cfg_mgr.echoClientId());
  790. }
  791. // This test checks the D2ClientMgr wrapper methods.
  792. TEST_F(CfgMgrTest, d2ClientConfig) {
  793. // After CfgMgr construction, D2ClientMgr member should be initialized
  794. // with a D2 configuration that is disabled.
  795. // Verify we can Fetch the mgr.
  796. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  797. EXPECT_FALSE(d2_mgr.ddnsEnabled());
  798. // Make sure the convenience method fetches the config correctly.
  799. D2ClientConfigPtr original_config = CfgMgr::instance().getD2ClientConfig();
  800. ASSERT_TRUE(original_config);
  801. EXPECT_FALSE(original_config->getEnableUpdates());
  802. // Verify that we cannot set the configuration to an empty pointer.
  803. D2ClientConfigPtr new_cfg;
  804. ASSERT_THROW(CfgMgr::instance().setD2ClientConfig(new_cfg), D2ClientError);
  805. // Create a new, enabled configuration.
  806. ASSERT_NO_THROW(new_cfg.reset(new D2ClientConfig(true,
  807. isc::asiolink::IOAddress("127.0.0.1"), 477,
  808. isc::asiolink::IOAddress("127.0.0.1"), 478,
  809. 1024,
  810. dhcp_ddns::NCR_UDP, dhcp_ddns::FMT_JSON,
  811. true, true, true, true,
  812. "pre-fix", "suf-fix")));
  813. // Verify that we can assign a new, non-empty configuration.
  814. ASSERT_NO_THROW(CfgMgr::instance().setD2ClientConfig(new_cfg));
  815. // Verify that we can fetch the newly assigned configuration.
  816. D2ClientConfigPtr updated_config = CfgMgr::instance().getD2ClientConfig();
  817. ASSERT_TRUE(updated_config);
  818. EXPECT_TRUE(updated_config->getEnableUpdates());
  819. // Make sure convenience method agrees with updated configuration.
  820. EXPECT_TRUE(CfgMgr::instance().ddnsEnabled());
  821. // Make sure the configuration we fetched is the one we assigned,
  822. // and not the original configuration.
  823. EXPECT_EQ(*new_cfg, *updated_config);
  824. EXPECT_NE(*original_config, *updated_config);
  825. }
  826. // This test verfies that CfgMgr correctly determines that the address of the
  827. // interface belongs to existing IPv4 subnet.
  828. TEST_F(CfgMgrTest, getSubnet4ForInterface) {
  829. IfaceMgrTestConfig config(true);
  830. // Initially, there are no subnets configured, so none of the IPv4
  831. // addresses assigned to eth0 and eth1 can match with any subnet.
  832. EXPECT_FALSE(CfgMgr::instance().getSubnet4("eth0", classify_));
  833. EXPECT_FALSE(CfgMgr::instance().getSubnet4("eth1", classify_));
  834. // Configure first subnet which address on eth0 corresponds to.
  835. Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.1"), 24, 1, 2, 3));
  836. CfgMgr::instance().addSubnet4(subnet1);
  837. // The address on eth0 should match the existing subnet.
  838. Subnet4Ptr subnet1_ret;
  839. subnet1_ret = CfgMgr::instance().getSubnet4("eth0", classify_);
  840. ASSERT_TRUE(subnet1_ret);
  841. EXPECT_EQ(subnet1->get().first, subnet1_ret->get().first);
  842. // There should still be no match for eth1.
  843. EXPECT_FALSE(CfgMgr::instance().getSubnet4("eth1", classify_));
  844. // Configure a second subnet.
  845. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.1"), 24, 1, 2, 3));
  846. CfgMgr::instance().addSubnet4(subnet2);
  847. // There should be match between eth0 and subnet1 and between eth1 and
  848. // subnet 2.
  849. subnet1_ret = CfgMgr::instance().getSubnet4("eth0", classify_);
  850. ASSERT_TRUE(subnet1_ret);
  851. EXPECT_EQ(subnet1->get().first, subnet1_ret->get().first);
  852. Subnet4Ptr subnet2_ret = CfgMgr::instance().getSubnet4("eth1", classify_);
  853. ASSERT_TRUE(subnet2_ret);
  854. EXPECT_EQ(subnet2->get().first, subnet2_ret->get().first);
  855. // This function throws an exception if the name of the interface is wrong.
  856. EXPECT_THROW(CfgMgr::instance().getSubnet4("bogus-interface", classify_),
  857. isc::BadValue);
  858. }
  859. // Checks that detection of duplicated subnet IDs works as expected. It should
  860. // not be possible to add two IPv4 subnets holding the same ID to the config
  861. // manager.
  862. TEST_F(CfgMgrTest, subnet4Duplication) {
  863. CfgMgr& cfg_mgr = CfgMgr::instance();
  864. Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3, 123));
  865. Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3, 124));
  866. Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3, 123));
  867. ASSERT_NO_THROW(cfg_mgr.addSubnet4(subnet1));
  868. EXPECT_NO_THROW(cfg_mgr.addSubnet4(subnet2));
  869. // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
  870. EXPECT_THROW(cfg_mgr.addSubnet4(subnet3), isc::dhcp::DuplicateSubnetID);
  871. }
  872. // Checks that detection of duplicated subnet IDs works as expected. It should
  873. // not be possible to add two IPv6 subnets holding the same ID to the config
  874. // manager.
  875. TEST_F(CfgMgrTest, subnet6Duplication) {
  876. CfgMgr& cfg_mgr = CfgMgr::instance();
  877. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3,
  878. 4, 123));
  879. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 64, 1, 2, 3,
  880. 4, 124));
  881. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 64, 1, 2, 3,
  882. 4, 123));
  883. ASSERT_NO_THROW(cfg_mgr.addSubnet6(subnet1));
  884. EXPECT_NO_THROW(cfg_mgr.addSubnet6(subnet2));
  885. // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it.
  886. EXPECT_THROW(cfg_mgr.addSubnet6(subnet3), isc::dhcp::DuplicateSubnetID);
  887. }
  888. /// @todo Add unit-tests for testing:
  889. /// - addActiveIface() with invalid interface name
  890. /// - addActiveIface() with the same interface twice
  891. /// - addActiveIface() with a bogus address
  892. ///
  893. /// This is somewhat tricky. Care should be taken here, because it is rather
  894. /// difficult to decide if interface name is valid or not. Some servers, e.g.
  895. /// dibbler, allow to specify interface names that are not currently present in
  896. /// the system. The server accepts them, but upon discovering that they are
  897. /// yet available (for different definitions of not being available), adds
  898. /// the to to-be-activated list.
  899. ///
  900. /// Cases covered by dibbler are:
  901. /// - missing interface (e.g. PPP connection that is not established yet)
  902. /// - downed interface (no link local address, no way to open sockets)
  903. /// - up, but not running interface (wifi up, but not associated)
  904. /// - tentative addresses (interface up and running, but DAD procedure is
  905. /// still in progress)
  906. /// - weird interfaces without link-local addresses (don't ask, 6rd tunnels
  907. /// look weird to me as well)
  908. // No specific tests for getSubnet6. That method (2 overloaded versions) is tested
  909. // in Dhcpv6SrvTest.selectSubnetAddr and Dhcpv6SrvTest.selectSubnetIface
  910. // (see src/bin/dhcp6/tests/dhcp6_srv_unittest.cc)
  911. } // end of anonymous namespace