cfgmgr_unittest.cc 45 KB

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