d2_cfg_mgr_unittests.cc 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. // Copyright (C) 2013-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/module_spec.h>
  15. #include <d2/d2_config.h>
  16. #include <d2/d2_cfg_mgr.h>
  17. #include <d_test_stubs.h>
  18. #include <test_data_files_config.h>
  19. #include <boost/foreach.hpp>
  20. #include <gtest/gtest.h>
  21. using namespace std;
  22. using namespace isc;
  23. using namespace isc::d2;
  24. namespace {
  25. std::string specfile(const std::string& name) {
  26. return (std::string(D2_SRC_DIR) + "/" + name);
  27. }
  28. /// @brief Test fixture class for testing D2CfgMgr class.
  29. /// It maintains an member instance of D2CfgMgr and provides methods for
  30. /// converting JSON strings to configuration element sets, checking parse
  31. /// results, and accessing the configuration context.
  32. class D2CfgMgrTest : public ConfigParseTest {
  33. public:
  34. /// @brief Constructor
  35. D2CfgMgrTest():cfg_mgr_(new D2CfgMgr) {
  36. }
  37. /// @brief Destructor
  38. ~D2CfgMgrTest() {
  39. }
  40. /// @brief Configuration manager instance.
  41. D2CfgMgrPtr cfg_mgr_;
  42. };
  43. /// @brief Tests that the spec file is valid.
  44. /// Verifies that the BIND10 DHCP-DDNS configuration specification file
  45. // is valid.
  46. TEST(D2SpecTest, basicSpec) {
  47. ASSERT_NO_THROW(isc::config::
  48. moduleSpecFromFile(specfile("dhcp-ddns.spec")));
  49. }
  50. /// @brief Convenience function which compares the contents of the given
  51. /// DnsServerInfo against the given set of values.
  52. ///
  53. /// It is structured in such a way that each value is checked, and output
  54. /// is generate for all that do not match.
  55. ///
  56. /// @param server is a pointer to the server to check against.
  57. /// @param hostname is the value to compare against server's hostname_.
  58. /// @param ip_address is the string value to compare against server's
  59. /// ip_address_.
  60. /// @param port is the value to compare against server's port.
  61. ///
  62. /// @return returns true if there is a match across the board, otherwise it
  63. /// returns false.
  64. bool checkServer(DnsServerInfoPtr server, const char* hostname,
  65. const char *ip_address, uint32_t port)
  66. {
  67. // Return value, assume its a match.
  68. bool result = true;
  69. if (!server) {
  70. EXPECT_TRUE(server);
  71. return false;
  72. }
  73. // Check hostname.
  74. if (server->getHostname() != hostname) {
  75. EXPECT_EQ(hostname, server->getHostname());
  76. result = false;
  77. }
  78. // Check IP address.
  79. if (server->getIpAddress().toText() != ip_address) {
  80. EXPECT_EQ(ip_address, server->getIpAddress().toText());
  81. result = false;
  82. }
  83. // Check port.
  84. if (server->getPort() != port) {
  85. EXPECT_EQ (port, server->getPort());
  86. result = false;
  87. }
  88. return (result);
  89. }
  90. /// @brief Convenience function which compares the contents of the given
  91. /// TSIGKeyInfo against the given set of values.
  92. ///
  93. /// It is structured in such a way that each value is checked, and output
  94. /// is generate for all that do not match.
  95. ///
  96. /// @param key is a pointer to the key to check against.
  97. /// @param name is the value to compare against key's name_.
  98. /// @param algorithm is the string value to compare against key's algorithm.
  99. /// @param secret is the value to compare against key's secret.
  100. ///
  101. /// @return returns true if there is a match across the board, otherwise it
  102. /// returns false.
  103. bool checkKey(TSIGKeyInfoPtr key, const char* name,
  104. const char *algorithm, const char* secret)
  105. {
  106. // Return value, assume its a match.
  107. bool result = true;
  108. if (!key) {
  109. EXPECT_TRUE(key);
  110. return false;
  111. }
  112. // Check name.
  113. if (key->getName() != name) {
  114. EXPECT_EQ(name, key->getName());
  115. result = false;
  116. }
  117. // Check algorithm.
  118. if (key->getAlgorithm() != algorithm) {
  119. EXPECT_EQ(algorithm, key->getAlgorithm());
  120. result = false;
  121. }
  122. // Check secret.
  123. if (key->getSecret() != secret) {
  124. EXPECT_EQ (secret, key->getSecret());
  125. result = false;
  126. }
  127. return (result);
  128. }
  129. /// @brief Test fixture class for testing DnsServerInfo parsing.
  130. class TSIGKeyInfoTest : public ConfigParseTest {
  131. public:
  132. /// @brief Constructor
  133. TSIGKeyInfoTest() {
  134. reset();
  135. }
  136. /// @brief Destructor
  137. ~TSIGKeyInfoTest() {
  138. }
  139. /// @brief Wipe out the current storage and parser and replace
  140. /// them with new ones.
  141. void reset() {
  142. keys_.reset(new TSIGKeyInfoMap());
  143. parser_.reset(new TSIGKeyInfoParser("test", keys_));
  144. }
  145. /// @brief Storage for "committing" keys.
  146. TSIGKeyInfoMapPtr keys_;
  147. /// @brief Pointer to the current parser instance.
  148. isc::dhcp::ParserPtr parser_;
  149. };
  150. /// @brief Test fixture class for testing DnsServerInfo parsing.
  151. class DnsServerInfoTest : public ConfigParseTest {
  152. public:
  153. /// @brief Constructor
  154. DnsServerInfoTest() {
  155. reset();
  156. }
  157. /// @brief Destructor
  158. ~DnsServerInfoTest() {
  159. }
  160. /// @brief Wipe out the current storage and parser and replace
  161. /// them with new ones.
  162. void reset() {
  163. servers_.reset(new DnsServerInfoStorage());
  164. parser_.reset(new DnsServerInfoParser("test", servers_));
  165. }
  166. /// @brief Storage for "committing" servers.
  167. DnsServerInfoStoragePtr servers_;
  168. /// @brief Pointer to the current parser instance.
  169. isc::dhcp::ParserPtr parser_;
  170. };
  171. /// @brief Test fixture class for testing DDnsDomain parsing.
  172. class DdnsDomainTest : public ConfigParseTest {
  173. public:
  174. /// @brief Constructor
  175. DdnsDomainTest() {
  176. reset();
  177. }
  178. /// @brief Destructor
  179. ~DdnsDomainTest() {
  180. }
  181. /// @brief Wipe out the current storage and parser and replace
  182. /// them with new ones.
  183. void reset() {
  184. keys_.reset(new TSIGKeyInfoMap());
  185. domains_.reset(new DdnsDomainMap());
  186. parser_.reset(new DdnsDomainParser("test", domains_, keys_));
  187. }
  188. /// @brief Add TSIGKeyInfos to the key map
  189. ///
  190. /// @param name the name of the key
  191. /// @param algorithm the algorithm of the key
  192. /// @param secret the secret value of the key
  193. void addKey(const std::string& name, const std::string& algorithm,
  194. const std::string& secret) {
  195. TSIGKeyInfoPtr key_info(new TSIGKeyInfo(name, algorithm, secret));
  196. (*keys_)[name]=key_info;
  197. }
  198. /// @brief Storage for "committing" domains.
  199. DdnsDomainMapPtr domains_;
  200. /// @brief Storage for TSIGKeys
  201. TSIGKeyInfoMapPtr keys_;
  202. /// @brief Pointer to the current parser instance.
  203. isc::dhcp::ParserPtr parser_;
  204. };
  205. /// @brief Tests the enforcement of data validation when parsing TSIGKeyInfos.
  206. /// It verifies that:
  207. /// 1. Name cannot be blank.
  208. /// 2. Algorithm cannot be blank.
  209. /// 3. Secret cannot be blank.
  210. /// @TODO TSIG keys are not fully functional. Only basic validation is
  211. /// currently supported. This test will need to expand as they evolve.
  212. TEST_F(TSIGKeyInfoTest, invalidEntry) {
  213. // Config with a blank name entry.
  214. std::string config = "{"
  215. " \"name\": \"\" , "
  216. " \"algorithm\": \"md5\" , "
  217. " \"secret\": \"0123456789\" "
  218. "}";
  219. ASSERT_TRUE(fromJSON(config));
  220. // Verify that build fails on blank name.
  221. EXPECT_THROW(parser_->build(config_set_), D2CfgError);
  222. // Config with a blank algorithm entry.
  223. config = "{"
  224. " \"name\": \"d2_key_one\" , "
  225. " \"algorithm\": \"\" , "
  226. " \"secret\": \"0123456789\" "
  227. "}";
  228. ASSERT_TRUE(fromJSON(config));
  229. // Verify that build fails on blank algorithm.
  230. EXPECT_THROW(parser_->build(config_set_), D2CfgError);
  231. // Config with a blank secret entry.
  232. config = "{"
  233. " \"name\": \"d2_key_one\" , "
  234. " \"algorithm\": \"md5\" , "
  235. " \"secret\": \"\" "
  236. "}";
  237. ASSERT_TRUE(fromJSON(config));
  238. // Verify that build fails blank secret
  239. EXPECT_THROW(parser_->build(config_set_), D2CfgError);
  240. }
  241. /// @brief Verifies that TSIGKeyInfo parsing creates a proper TSIGKeyInfo
  242. /// when given a valid combination of entries.
  243. TEST_F(TSIGKeyInfoTest, validEntry) {
  244. // Valid entries for TSIG key, all items are required.
  245. std::string config = "{"
  246. " \"name\": \"d2_key_one\" , "
  247. " \"algorithm\": \"md5\" , "
  248. " \"secret\": \"0123456789\" "
  249. "}";
  250. ASSERT_TRUE(fromJSON(config));
  251. // Verify that it builds and commits without throwing.
  252. ASSERT_NO_THROW(parser_->build(config_set_));
  253. ASSERT_NO_THROW(parser_->commit());
  254. // Verify the correct number of keys are present
  255. int count = keys_->size();
  256. EXPECT_EQ(1, count);
  257. // Find the key and retrieve it.
  258. TSIGKeyInfoMap::iterator gotit = keys_->find("d2_key_one");
  259. ASSERT_TRUE(gotit != keys_->end());
  260. TSIGKeyInfoPtr& key = gotit->second;
  261. // Verify the key contents.
  262. EXPECT_TRUE(checkKey(key, "d2_key_one", "md5", "0123456789"));
  263. }
  264. /// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
  265. /// entries is detected.
  266. TEST_F(TSIGKeyInfoTest, invalidTSIGKeyList) {
  267. // Construct a list of keys with an invalid key entry.
  268. std::string config = "["
  269. " { \"name\": \"key1\" , "
  270. " \"algorithm\": \"algo1\" ,"
  271. " \"secret\": \"secret11\" "
  272. " },"
  273. " { \"name\": \"key2\" , "
  274. " \"algorithm\": \"\" ,"
  275. " \"secret\": \"secret12\" "
  276. " },"
  277. " { \"name\": \"key3\" , "
  278. " \"algorithm\": \"algo3\" ,"
  279. " \"secret\": \"secret13\" "
  280. " }"
  281. " ]";
  282. ASSERT_TRUE(fromJSON(config));
  283. // Create the list parser.
  284. isc::dhcp::ParserPtr parser;
  285. ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
  286. // Verify that the list builds without errors.
  287. EXPECT_THROW(parser->build(config_set_), D2CfgError);
  288. }
  289. /// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
  290. /// entries is detected.
  291. TEST_F(TSIGKeyInfoTest, duplicateTSIGKey) {
  292. // Construct a list of keys with an invalid key entry.
  293. std::string config = "["
  294. " { \"name\": \"key1\" , "
  295. " \"algorithm\": \"algo1\" ,"
  296. " \"secret\": \"secret11\" "
  297. " },"
  298. " { \"name\": \"key2\" , "
  299. " \"algorithm\": \"algo2\" ,"
  300. " \"secret\": \"secret12\" "
  301. " },"
  302. " { \"name\": \"key1\" , "
  303. " \"algorithm\": \"algo3\" ,"
  304. " \"secret\": \"secret13\" "
  305. " }"
  306. " ]";
  307. ASSERT_TRUE(fromJSON(config));
  308. // Create the list parser.
  309. isc::dhcp::ParserPtr parser;
  310. ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
  311. // Verify that the list builds without errors.
  312. EXPECT_THROW(parser->build(config_set_), D2CfgError);
  313. }
  314. /// @brief Verifies a valid list of TSIG Keys parses correctly.
  315. TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
  316. // Construct a valid list of keys.
  317. std::string config = "["
  318. " { \"name\": \"key1\" , "
  319. " \"algorithm\": \"algo1\" ,"
  320. " \"secret\": \"secret1\" "
  321. " },"
  322. " { \"name\": \"key2\" , "
  323. " \"algorithm\": \"algo2\" ,"
  324. " \"secret\": \"secret2\" "
  325. " },"
  326. " { \"name\": \"key3\" , "
  327. " \"algorithm\": \"algo3\" ,"
  328. " \"secret\": \"secret3\" "
  329. " }"
  330. " ]";
  331. ASSERT_TRUE(fromJSON(config));
  332. // Verify that the list builds and commits without errors.
  333. // Create the list parser.
  334. isc::dhcp::ParserPtr parser;
  335. ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
  336. ASSERT_NO_THROW(parser->build(config_set_));
  337. ASSERT_NO_THROW(parser->commit());
  338. // Verify the correct number of keys are present
  339. int count = keys_->size();
  340. ASSERT_EQ(3, count);
  341. // Find the 1st key and retrieve it.
  342. TSIGKeyInfoMap::iterator gotit = keys_->find("key1");
  343. ASSERT_TRUE(gotit != keys_->end());
  344. TSIGKeyInfoPtr& key = gotit->second;
  345. // Verify the key contents.
  346. EXPECT_TRUE(checkKey(key, "key1", "algo1", "secret1"));
  347. // Find the 2nd key and retrieve it.
  348. gotit = keys_->find("key2");
  349. ASSERT_TRUE(gotit != keys_->end());
  350. key = gotit->second;
  351. // Verify the key contents.
  352. EXPECT_TRUE(checkKey(key, "key2", "algo2", "secret2"));
  353. // Find the 3rd key and retrieve it.
  354. gotit = keys_->find("key3");
  355. ASSERT_TRUE(gotit != keys_->end());
  356. key = gotit->second;
  357. // Verify the key contents.
  358. EXPECT_TRUE(checkKey(key, "key3", "algo3", "secret3"));
  359. }
  360. /// @brief Tests the enforcement of data validation when parsing DnsServerInfos.
  361. /// It verifies that:
  362. /// 1. Specifying both a hostname and an ip address is not allowed.
  363. /// 2. Specifying both blank a hostname and blank ip address is not allowed.
  364. /// 3. Specifying a negative port number is not allowed.
  365. TEST_F(DnsServerInfoTest, invalidEntry) {
  366. // Create a config in which both host and ip address are supplied.
  367. // Verify that build fails.
  368. std::string config = "{ \"hostname\": \"pegasus.tmark\", "
  369. " \"ip_address\": \"127.0.0.1\" } ";
  370. ASSERT_TRUE(fromJSON(config));
  371. EXPECT_THROW(parser_->build(config_set_), D2CfgError);
  372. // Neither host nor ip address supplied
  373. // Verify that builds fails.
  374. config = "{ \"hostname\": \"\", "
  375. " \"ip_address\": \"\" } ";
  376. ASSERT_TRUE(fromJSON(config));
  377. EXPECT_THROW(parser_->build(config_set_), D2CfgError);
  378. // Create a config with a negative port number.
  379. // Verify that build fails.
  380. config = "{ \"ip_address\": \"192.168.5.6\" ,"
  381. " \"port\": -100 }";
  382. ASSERT_TRUE(fromJSON(config));
  383. EXPECT_THROW (parser_->build(config_set_), isc::BadValue);
  384. }
  385. /// @brief Verifies that DnsServerInfo parsing creates a proper DnsServerInfo
  386. /// when given a valid combination of entries.
  387. /// It verifies that:
  388. /// 1. A DnsServerInfo entry is correctly made, when given only a hostname.
  389. /// 2. A DnsServerInfo entry is correctly made, when given ip address and port.
  390. /// 3. A DnsServerInfo entry is correctly made, when given only an ip address.
  391. TEST_F(DnsServerInfoTest, validEntry) {
  392. // Valid entries for dynamic host
  393. std::string config = "{ \"hostname\": \"pegasus.tmark\" }";
  394. ASSERT_TRUE(fromJSON(config));
  395. // Verify that it builds and commits without throwing.
  396. ASSERT_NO_THROW(parser_->build(config_set_));
  397. ASSERT_NO_THROW(parser_->commit());
  398. // Verify the correct number of servers are present
  399. int count = servers_->size();
  400. EXPECT_EQ(1, count);
  401. // Verify the server exists and has the correct values.
  402. DnsServerInfoPtr server = (*servers_)[0];
  403. EXPECT_TRUE(checkServer(server, "pegasus.tmark",
  404. DnsServerInfo::EMPTY_IP_STR,
  405. DnsServerInfo::STANDARD_DNS_PORT));
  406. // Start over for a new test.
  407. reset();
  408. // Valid entries for static ip
  409. config = " { \"ip_address\": \"127.0.0.1\" , "
  410. " \"port\": 100 }";
  411. ASSERT_TRUE(fromJSON(config));
  412. // Verify that it builds and commits without throwing.
  413. ASSERT_NO_THROW(parser_->build(config_set_));
  414. ASSERT_NO_THROW(parser_->commit());
  415. // Verify the correct number of servers are present
  416. count = servers_->size();
  417. EXPECT_EQ(1, count);
  418. // Verify the server exists and has the correct values.
  419. server = (*servers_)[0];
  420. EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
  421. // Start over for a new test.
  422. reset();
  423. // Valid entries for static ip, no port
  424. config = " { \"ip_address\": \"192.168.2.5\" }";
  425. ASSERT_TRUE(fromJSON(config));
  426. // Verify that it builds and commits without throwing.
  427. ASSERT_NO_THROW(parser_->build(config_set_));
  428. ASSERT_NO_THROW(parser_->commit());
  429. // Verify the correct number of servers are present
  430. count = servers_->size();
  431. EXPECT_EQ(1, count);
  432. // Verify the server exists and has the correct values.
  433. server = (*servers_)[0];
  434. EXPECT_TRUE(checkServer(server, "", "192.168.2.5",
  435. DnsServerInfo::STANDARD_DNS_PORT));
  436. }
  437. /// @brief Verifies that attempting to parse an invalid list of DnsServerInfo
  438. /// entries is detected.
  439. TEST_F(ConfigParseTest, invalidServerList) {
  440. // Construct a list of servers with an invalid server entry.
  441. std::string config = "[ { \"hostname\": \"one.tmark\" }, "
  442. "{ \"hostname\": \"\" }, "
  443. "{ \"hostname\": \"three.tmark\" } ]";
  444. ASSERT_TRUE(fromJSON(config));
  445. // Create the server storage and list parser.
  446. DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
  447. isc::dhcp::ParserPtr parser;
  448. ASSERT_NO_THROW(parser.reset(new DnsServerInfoListParser("test", servers)));
  449. // Verify that build fails.
  450. EXPECT_THROW(parser->build(config_set_), D2CfgError);
  451. }
  452. /// @brief Verifies that a list of DnsServerInfo entries parses correctly given
  453. /// a valid configuration.
  454. TEST_F(ConfigParseTest, validServerList) {
  455. // Create a valid list of servers.
  456. std::string config = "[ { \"hostname\": \"one.tmark\" }, "
  457. "{ \"hostname\": \"two.tmark\" }, "
  458. "{ \"hostname\": \"three.tmark\" } ]";
  459. ASSERT_TRUE(fromJSON(config));
  460. // Create the server storage and list parser.
  461. DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
  462. isc::dhcp::ParserPtr parser;
  463. ASSERT_NO_THROW(parser.reset(new DnsServerInfoListParser("test", servers)));
  464. // Verfiy that the list builds and commits without error.
  465. ASSERT_NO_THROW(parser->build(config_set_));
  466. ASSERT_NO_THROW(parser->commit());
  467. // Verify that the server storage contains the correct number of servers.
  468. int count = servers->size();
  469. EXPECT_EQ(3, count);
  470. // Verify the first server exists and has the correct values.
  471. DnsServerInfoPtr server = (*servers)[0];
  472. EXPECT_TRUE(checkServer(server, "one.tmark", DnsServerInfo::EMPTY_IP_STR,
  473. DnsServerInfo::STANDARD_DNS_PORT));
  474. // Verify the second server exists and has the correct values.
  475. server = (*servers)[1];
  476. EXPECT_TRUE(checkServer(server, "two.tmark", DnsServerInfo::EMPTY_IP_STR,
  477. DnsServerInfo::STANDARD_DNS_PORT));
  478. // Verify the third server exists and has the correct values.
  479. server = (*servers)[2];
  480. EXPECT_TRUE(checkServer(server, "three.tmark", DnsServerInfo::EMPTY_IP_STR,
  481. DnsServerInfo::STANDARD_DNS_PORT));
  482. }
  483. /// @brief Tests the enforcement of data validation when parsing DdnsDomains.
  484. /// It verifies that:
  485. /// 1. Domain storage cannot be null when constructing a DdnsDomainParser.
  486. /// 2. The name entry is not optional.
  487. /// 3. The server list man not be empty.
  488. /// 4. That a mal-formed server entry is detected.
  489. /// 5. That an undefined key name is detected.
  490. TEST_F(DdnsDomainTest, invalidDdnsDomainEntry) {
  491. // Verify that attempting to construct the parser with null storage fails.
  492. DdnsDomainMapPtr domains;
  493. ASSERT_THROW(isc::dhcp::ParserPtr(
  494. new DdnsDomainParser("test", domains, keys_)), D2CfgError);
  495. // Create a domain configuration without a name
  496. std::string config = "{ \"key_name\": \"d2_key.tmark.org\" , "
  497. " \"dns_servers\" : [ "
  498. " { \"ip_address\": \"127.0.0.1\" , "
  499. " \"port\": 100 },"
  500. " { \"ip_address\": \"127.0.0.2\" , "
  501. " \"port\": 200 },"
  502. " { \"ip_address\": \"127.0.0.3\" , "
  503. " \"port\": 300 } ] } ";
  504. ASSERT_TRUE(fromJSON(config));
  505. // Verify that the domain configuration builds but commit fails.
  506. ASSERT_NO_THROW(parser_->build(config_set_));
  507. ASSERT_THROW(parser_->commit(), isc::dhcp::DhcpConfigError);
  508. // Create a domain configuration with an empty server list.
  509. config = "{ \"name\": \"tmark.org\" , "
  510. " \"key_name\": \"d2_key.tmark.org\" , "
  511. " \"dns_servers\" : [ "
  512. " ] } ";
  513. ASSERT_TRUE(fromJSON(config));
  514. // Verify that the domain configuration build fails.
  515. ASSERT_THROW(parser_->build(config_set_), D2CfgError);
  516. // Create a domain configuration with a mal-formed server entry.
  517. config = "{ \"name\": \"tmark.org\" , "
  518. " \"key_name\": \"d2_key.tmark.org\" , "
  519. " \"dns_servers\" : [ "
  520. " { \"ip_address\": \"127.0.0.3\" , "
  521. " \"port\": -1 } ] } ";
  522. ASSERT_TRUE(fromJSON(config));
  523. // Verify that the domain configuration build fails.
  524. ASSERT_THROW(parser_->build(config_set_), isc::BadValue);
  525. // Create a domain configuration without an defined key name
  526. config = "{ \"name\": \"tmark.org\" , "
  527. " \"key_name\": \"d2_key.tmark.org\" , "
  528. " \"dns_servers\" : [ "
  529. " { \"ip_address\": \"127.0.0.3\" , "
  530. " \"port\": 300 } ] } ";
  531. ASSERT_TRUE(fromJSON(config));
  532. // Verify that the domain configuration build succeeds but commit fails.
  533. ASSERT_NO_THROW(parser_->build(config_set_));
  534. ASSERT_THROW(parser_->commit(), D2CfgError);
  535. }
  536. /// @brief Verifies the basics of parsing DdnsDomains.
  537. /// It verifies that:
  538. /// 1. Valid construction of DdnsDomainParser functions.
  539. /// 2. Given a valid, configuration entry, DdnsDomainParser parses
  540. /// correctly.
  541. /// (It indirectly verifies the operation of DdnsDomainMap).
  542. TEST_F(DdnsDomainTest, ddnsDomainParsing) {
  543. // Create a valid domain configuration entry containing three valid
  544. // servers.
  545. std::string config =
  546. "{ \"name\": \"tmark.org\" , "
  547. " \"key_name\": \"d2_key.tmark.org\" , "
  548. " \"dns_servers\" : [ "
  549. " { \"ip_address\": \"127.0.0.1\" , "
  550. " \"port\": 100 },"
  551. " { \"ip_address\": \"127.0.0.2\" , "
  552. " \"port\": 200 },"
  553. " { \"ip_address\": \"127.0.0.3\" , "
  554. " \"port\": 300 } ] } ";
  555. ASSERT_TRUE(fromJSON(config));
  556. // Add a TSIG key to the test key map, so key validation will pass.
  557. addKey("d2_key.tmark.org", "md5", "0123456789");
  558. // Verify that the domain configuration builds and commits without error.
  559. ASSERT_NO_THROW(parser_->build(config_set_));
  560. ASSERT_NO_THROW(parser_->commit());
  561. // Verify that the domain storage contains the correct number of domains.
  562. int count = domains_->size();
  563. EXPECT_EQ(1, count);
  564. // Verify that the expected domain exists and can be retrieved from
  565. // the storage.
  566. DdnsDomainMap::iterator gotit = domains_->find("tmark.org");
  567. ASSERT_TRUE(gotit != domains_->end());
  568. DdnsDomainPtr& domain = gotit->second;
  569. // Verify the name and key_name values.
  570. EXPECT_EQ("tmark.org", domain->getName());
  571. EXPECT_EQ("d2_key.tmark.org", domain->getKeyName());
  572. // Verify that the server list exists and contains the correct number of
  573. // servers.
  574. const DnsServerInfoStoragePtr& servers = domain->getServers();
  575. EXPECT_TRUE(servers);
  576. count = servers->size();
  577. EXPECT_EQ(3, count);
  578. // Fetch each server and verify its contents.
  579. DnsServerInfoPtr server = (*servers)[0];
  580. EXPECT_TRUE(server);
  581. EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
  582. server = (*servers)[1];
  583. EXPECT_TRUE(server);
  584. EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
  585. server = (*servers)[2];
  586. EXPECT_TRUE(server);
  587. EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
  588. }
  589. /// @brief Tests the fundamentals of parsing DdnsDomain lists.
  590. /// This test verifies that given a valid domain list configuration
  591. /// it will accurately parse and populate each domain in the list.
  592. TEST_F(DdnsDomainTest, DdnsDomainListParsing) {
  593. // Create a valid domain list configuration, with two domains
  594. // that have three servers each.
  595. std::string config =
  596. "[ "
  597. "{ \"name\": \"tmark.org\" , "
  598. " \"key_name\": \"d2_key.tmark.org\" , "
  599. " \"dns_servers\" : [ "
  600. " { \"ip_address\": \"127.0.0.1\" , "
  601. " \"port\": 100 },"
  602. " { \"ip_address\": \"127.0.0.2\" , "
  603. " \"port\": 200 },"
  604. " { \"ip_address\": \"127.0.0.3\" , "
  605. " \"port\": 300 } ] } "
  606. ", "
  607. "{ \"name\": \"billcat.net\" , "
  608. " \"key_name\": \"d2_key.billcat.net\" , "
  609. " \"dns_servers\" : [ "
  610. " { \"ip_address\": \"127.0.0.4\" , "
  611. " \"port\": 400 },"
  612. " { \"ip_address\": \"127.0.0.5\" , "
  613. " \"port\": 500 },"
  614. " { \"ip_address\": \"127.0.0.6\" , "
  615. " \"port\": 600 } ] } "
  616. "] ";
  617. ASSERT_TRUE(fromJSON(config));
  618. // Add keys to key map so key validation passes.
  619. addKey("d2_key.tmark.org", "algo1", "secret1");
  620. addKey("d2_key.billcat.net", "algo2", "secret2");
  621. // Create the list parser
  622. isc::dhcp::ParserPtr list_parser;
  623. ASSERT_NO_THROW(list_parser.reset(
  624. new DdnsDomainListParser("test", domains_, keys_)));
  625. // Verify that the domain configuration builds and commits without error.
  626. ASSERT_NO_THROW(list_parser->build(config_set_));
  627. ASSERT_NO_THROW(list_parser->commit());
  628. // Verify that the domain storage contains the correct number of domains.
  629. int count = domains_->size();
  630. EXPECT_EQ(2, count);
  631. // Verify that the first domain exists and can be retrieved.
  632. DdnsDomainMap::iterator gotit = domains_->find("tmark.org");
  633. ASSERT_TRUE(gotit != domains_->end());
  634. DdnsDomainPtr& domain = gotit->second;
  635. // Verify the name and key_name values of the first domain.
  636. EXPECT_EQ("tmark.org", domain->getName());
  637. EXPECT_EQ("d2_key.tmark.org", domain->getKeyName());
  638. // Verify the each of the first domain's servers
  639. DnsServerInfoStoragePtr servers = domain->getServers();
  640. EXPECT_TRUE(servers);
  641. count = servers->size();
  642. EXPECT_EQ(3, count);
  643. DnsServerInfoPtr server = (*servers)[0];
  644. EXPECT_TRUE(server);
  645. EXPECT_TRUE(checkServer(server, "", "127.0.0.1", 100));
  646. server = (*servers)[1];
  647. EXPECT_TRUE(server);
  648. EXPECT_TRUE(checkServer(server, "", "127.0.0.2", 200));
  649. server = (*servers)[2];
  650. EXPECT_TRUE(server);
  651. EXPECT_TRUE(checkServer(server, "", "127.0.0.3", 300));
  652. // Verify second domain
  653. gotit = domains_->find("billcat.net");
  654. ASSERT_TRUE(gotit != domains_->end());
  655. domain = gotit->second;
  656. // Verify the name and key_name values of the second domain.
  657. EXPECT_EQ("billcat.net", domain->getName());
  658. EXPECT_EQ("d2_key.billcat.net", domain->getKeyName());
  659. // Verify the each of second domain's servers
  660. servers = domain->getServers();
  661. EXPECT_TRUE(servers);
  662. count = servers->size();
  663. EXPECT_EQ(3, count);
  664. server = (*servers)[0];
  665. EXPECT_TRUE(server);
  666. EXPECT_TRUE(checkServer(server, "", "127.0.0.4", 400));
  667. server = (*servers)[1];
  668. EXPECT_TRUE(server);
  669. EXPECT_TRUE(checkServer(server, "", "127.0.0.5", 500));
  670. server = (*servers)[2];
  671. EXPECT_TRUE(server);
  672. EXPECT_TRUE(checkServer(server, "", "127.0.0.6", 600));
  673. }
  674. /// @brief Tests that a domain list configuration cannot contain duplicates.
  675. TEST_F(DdnsDomainTest, duplicateDomain) {
  676. // Create a domain list configuration that contains two domains with
  677. // the same name.
  678. std::string config =
  679. "[ "
  680. "{ \"name\": \"tmark.org\" , "
  681. " \"dns_servers\" : [ "
  682. " { \"ip_address\": \"127.0.0.3\" , "
  683. " \"port\": 300 } ] } "
  684. ", "
  685. "{ \"name\": \"tmark.org\" , "
  686. " \"dns_servers\" : [ "
  687. " { \"ip_address\": \"127.0.0.3\" , "
  688. " \"port\": 300 } ] } "
  689. "] ";
  690. ASSERT_TRUE(fromJSON(config));
  691. // Create the list parser
  692. isc::dhcp::ParserPtr list_parser;
  693. ASSERT_NO_THROW(list_parser.reset(
  694. new DdnsDomainListParser("test", domains_, keys_)));
  695. // Verify that the parse build succeeds but the commit fails.
  696. ASSERT_NO_THROW(list_parser->build(config_set_));
  697. ASSERT_THROW(list_parser->commit(), D2CfgError);
  698. }
  699. /// @brief Tests construction of D2CfgMgr
  700. /// This test verifies that a D2CfgMgr constructs properly.
  701. TEST(D2CfgMgr, construction) {
  702. D2CfgMgr *cfg_mgr = NULL;
  703. // Verify that configuration manager constructions without error.
  704. ASSERT_NO_THROW(cfg_mgr = new D2CfgMgr());
  705. // Verify that the context can be retrieved and is not null.
  706. D2CfgContextPtr context;
  707. ASSERT_NO_THROW(context = cfg_mgr->getD2CfgContext());
  708. EXPECT_TRUE(context);
  709. // Verify that the forward manager can be retrieved and is not null.
  710. EXPECT_TRUE(context->getForwardMgr());
  711. // Verify that the reverse manager can be retrieved and is not null.
  712. EXPECT_TRUE(context->getReverseMgr());
  713. // Verify that the manager can be destructed without error.
  714. EXPECT_NO_THROW(delete cfg_mgr);
  715. }
  716. /// @brief Tests the parsing of a complete, valid DHCP-DDNS configuration.
  717. /// This tests passes the configuration into an instance of D2CfgMgr just
  718. /// as it would be done by d2_process in response to a configuration update
  719. /// event.
  720. TEST_F(D2CfgMgrTest, fullConfig) {
  721. // Create a configuration with all of application level parameters, plus
  722. // both the forward and reverse ddns managers. Both managers have two
  723. // domains with three servers per domain.
  724. std::string config = "{ "
  725. "\"interface\" : \"eth1\" , "
  726. "\"ip_address\" : \"192.168.1.33\" , "
  727. "\"port\" : 88 , "
  728. "\"tsig_keys\": ["
  729. "{"
  730. " \"name\": \"d2_key.tmark.org\" , "
  731. " \"algorithm\": \"md5\" , "
  732. " \"secret\": \"ssh-dont-tell\" "
  733. "},"
  734. "{"
  735. " \"name\": \"d2_key.billcat.net\" , "
  736. " \"algorithm\": \"md5\" , "
  737. " \"secret\": \"ollie-ollie-in-free\" "
  738. "}"
  739. "],"
  740. "\"forward_ddns\" : {"
  741. "\"ddns_domains\": [ "
  742. "{ \"name\": \"tmark.org\" , "
  743. " \"key_name\": \"d2_key.tmark.org\" , "
  744. " \"dns_servers\" : [ "
  745. " { \"hostname\": \"one.tmark\" } , "
  746. " { \"hostname\": \"two.tmark\" } , "
  747. " { \"hostname\": \"three.tmark\"} "
  748. " ] } "
  749. ", "
  750. "{ \"name\": \"billcat.net\" , "
  751. " \"key_name\": \"d2_key.billcat.net\" , "
  752. " \"dns_servers\" : [ "
  753. " { \"hostname\": \"four.billcat\" } , "
  754. " { \"hostname\": \"five.billcat\" } , "
  755. " { \"hostname\": \"six.billcat\" } "
  756. " ] } "
  757. "] },"
  758. "\"reverse_ddns\" : {"
  759. "\"ddns_domains\": [ "
  760. "{ \"name\": \" 0.168.192.in.addr.arpa.\" , "
  761. " \"key_name\": \"d2_key.tmark.org\" , "
  762. " \"dns_servers\" : [ "
  763. " { \"hostname\": \"one.rev\" } , "
  764. " { \"hostname\": \"two.rev\" } , "
  765. " { \"hostname\": \"three.rev\" } "
  766. " ] } "
  767. ", "
  768. "{ \"name\": \" 0.247.106.in.addr.arpa.\" , "
  769. " \"key_name\": \"d2_key.billcat.net\" , "
  770. " \"dns_servers\" : [ "
  771. " { \"hostname\": \"four.rev\" }, "
  772. " { \"hostname\": \"five.rev\" } , "
  773. " { \"hostname\": \"six.rev\" } "
  774. " ] } "
  775. "] } }";
  776. ASSERT_TRUE(fromJSON(config));
  777. // Verify that we can parse the configuration.
  778. answer_ = cfg_mgr_->parseConfig(config_set_);
  779. ASSERT_TRUE(checkAnswer(0));
  780. // Verify that the D2 context can be retrieved and is not null.
  781. D2CfgContextPtr context;
  782. ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
  783. // Verify that the application level scalars have the proper values.
  784. std::string interface;
  785. EXPECT_NO_THROW (context->getParam("interface", interface));
  786. EXPECT_EQ("eth1", interface);
  787. std::string ip_address;
  788. EXPECT_NO_THROW (context->getParam("ip_address", ip_address));
  789. EXPECT_EQ("192.168.1.33", ip_address);
  790. uint32_t port = 0;
  791. EXPECT_NO_THROW (context->getParam("port", port));
  792. EXPECT_EQ(88, port);
  793. // Verify that the forward manager can be retrieved.
  794. DdnsDomainListMgrPtr mgr = context->getForwardMgr();
  795. ASSERT_TRUE(mgr);
  796. // Verify that the forward manager has the correct number of domains.
  797. DdnsDomainMapPtr domains = mgr->getDomains();
  798. ASSERT_TRUE(domains);
  799. int count = domains->size();
  800. EXPECT_EQ(2, count);
  801. // Verify that the server count in each of the forward manager domains.
  802. // NOTE that since prior tests have validated server parsing, we are are
  803. // assuming that the servers did in fact parse correctly if the correct
  804. // number of them are there.
  805. DdnsDomainMapPair domain_pair;
  806. BOOST_FOREACH(domain_pair, (*domains)) {
  807. DdnsDomainPtr domain = domain_pair.second;
  808. DnsServerInfoStoragePtr servers = domain->getServers();
  809. count = servers->size();
  810. EXPECT_TRUE(servers);
  811. EXPECT_EQ(3, count);
  812. }
  813. // Verify that the reverse manager can be retrieved.
  814. mgr = context->getReverseMgr();
  815. ASSERT_TRUE(mgr);
  816. // Verify that the reverse manager has the correct number of domains.
  817. domains = mgr->getDomains();
  818. count = domains->size();
  819. EXPECT_EQ(2, count);
  820. // Verify that the server count in each of the reverse manager domains.
  821. // NOTE that since prior tests have validated server parsing, we are are
  822. // assuming that the servers did in fact parse correctly if the correct
  823. // number of them are there.
  824. BOOST_FOREACH(domain_pair, (*domains)) {
  825. DdnsDomainPtr domain = domain_pair.second;
  826. DnsServerInfoStoragePtr servers = domain->getServers();
  827. count = servers->size();
  828. EXPECT_TRUE(servers);
  829. EXPECT_EQ(3, count);
  830. }
  831. // Test directional update flags.
  832. EXPECT_TRUE(cfg_mgr_->forwardUpdatesEnabled());
  833. EXPECT_TRUE(cfg_mgr_->reverseUpdatesEnabled());
  834. // Verify that parsing the exact same configuration a second time
  835. // does not cause a duplicate value errors.
  836. answer_ = cfg_mgr_->parseConfig(config_set_);
  837. ASSERT_TRUE(checkAnswer(0));
  838. }
  839. /// @brief Tests the basics of the D2CfgMgr FQDN-domain matching
  840. /// This test uses a valid configuration to exercise the D2CfgMgr
  841. /// forward FQDN-to-domain matching.
  842. /// It verifies that:
  843. /// 1. Given an FQDN which exactly matches a domain's name, that domain is
  844. /// returned as match.
  845. /// 2. Given a FQDN for sub-domain in the list, returns the proper match.
  846. /// 3. Given a FQDN that matches no domain name, returns the wild card domain
  847. /// as a match.
  848. TEST_F(D2CfgMgrTest, forwardMatch) {
  849. // Create configuration with one domain, one sub domain, and the wild
  850. // card.
  851. std::string config = "{ "
  852. "\"interface\" : \"eth1\" , "
  853. "\"ip_address\" : \"192.168.1.33\" , "
  854. "\"port\" : 88 , "
  855. "\"tsig_keys\": [] ,"
  856. "\"forward_ddns\" : {"
  857. "\"ddns_domains\": [ "
  858. "{ \"name\": \"tmark.org\" , "
  859. " \"dns_servers\" : [ "
  860. " { \"ip_address\": \"127.0.0.1\" } "
  861. " ] } "
  862. ", "
  863. "{ \"name\": \"one.tmark.org\" , "
  864. " \"dns_servers\" : [ "
  865. " { \"ip_address\": \"127.0.0.2\" } "
  866. " ] } "
  867. ", "
  868. "{ \"name\": \"*\" , "
  869. " \"dns_servers\" : [ "
  870. " { \"hostname\": \"global.net\" } "
  871. " ] } "
  872. "] }, "
  873. "\"reverse_ddns\" : {} "
  874. "}";
  875. ASSERT_TRUE(fromJSON(config));
  876. // Verify that we can parse the configuration.
  877. answer_ = cfg_mgr_->parseConfig(config_set_);
  878. ASSERT_TRUE(checkAnswer(0));
  879. // Verify that the D2 context can be retrieved and is not null.
  880. D2CfgContextPtr context;
  881. ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
  882. // Test directional update flags.
  883. EXPECT_TRUE(cfg_mgr_->forwardUpdatesEnabled());
  884. EXPECT_FALSE(cfg_mgr_->reverseUpdatesEnabled());
  885. DdnsDomainPtr match;
  886. // Verify that an exact match works.
  887. EXPECT_TRUE(cfg_mgr_->matchForward("tmark.org", match));
  888. EXPECT_EQ("tmark.org", match->getName());
  889. // Verify that search is case insensisitive.
  890. EXPECT_TRUE(cfg_mgr_->matchForward("TMARK.ORG", match));
  891. EXPECT_EQ("tmark.org", match->getName());
  892. // Verify that an exact match works.
  893. EXPECT_TRUE(cfg_mgr_->matchForward("one.tmark.org", match));
  894. EXPECT_EQ("one.tmark.org", match->getName());
  895. // Verify that a FQDN for sub-domain matches.
  896. EXPECT_TRUE(cfg_mgr_->matchForward("blue.tmark.org", match));
  897. EXPECT_EQ("tmark.org", match->getName());
  898. // Verify that a FQDN for sub-domain matches.
  899. EXPECT_TRUE(cfg_mgr_->matchForward("red.one.tmark.org", match));
  900. EXPECT_EQ("one.tmark.org", match->getName());
  901. // Verify that an FQDN with no match, returns the wild card domain.
  902. EXPECT_TRUE(cfg_mgr_->matchForward("shouldbe.wildcard", match));
  903. EXPECT_EQ("*", match->getName());
  904. // Verify that an attempt to match an empty FQDN throws.
  905. ASSERT_THROW(cfg_mgr_->matchForward("", match), D2CfgError);
  906. }
  907. /// @brief Tests domain matching when there is no wild card domain.
  908. /// This test verifies that matches are found only for FQDNs that match
  909. /// some or all of a domain name. FQDNs without matches should not return
  910. /// a match.
  911. TEST_F(D2CfgMgrTest, matchNoWildcard) {
  912. // Create a configuration with one domain, one sub-domain, and NO wild card.
  913. std::string config = "{ "
  914. "\"interface\" : \"eth1\" , "
  915. "\"ip_address\" : \"192.168.1.33\" , "
  916. "\"port\" : 88 , "
  917. "\"tsig_keys\": [] ,"
  918. "\"forward_ddns\" : {"
  919. "\"ddns_domains\": [ "
  920. "{ \"name\": \"tmark.org\" , "
  921. " \"dns_servers\" : [ "
  922. " { \"ip_address\": \"127.0.0.1\" } "
  923. " ] } "
  924. ", "
  925. "{ \"name\": \"one.tmark.org\" , "
  926. " \"dns_servers\" : [ "
  927. " { \"ip_address\": \"127.0.0.2\" } "
  928. " ] } "
  929. "] }, "
  930. "\"reverse_ddns\" : {} "
  931. " }";
  932. ASSERT_TRUE(fromJSON(config));
  933. // Verify that we can parse the configuration.
  934. answer_ = cfg_mgr_->parseConfig(config_set_);
  935. ASSERT_TRUE(checkAnswer(0));
  936. // Verify that the D2 context can be retrieved and is not null.
  937. D2CfgContextPtr context;
  938. ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
  939. DdnsDomainPtr match;
  940. // Verify that full or partial matches, still match.
  941. EXPECT_TRUE(cfg_mgr_->matchForward("tmark.org", match));
  942. EXPECT_EQ("tmark.org", match->getName());
  943. EXPECT_TRUE(cfg_mgr_->matchForward("blue.tmark.org", match));
  944. EXPECT_EQ("tmark.org", match->getName());
  945. EXPECT_TRUE(cfg_mgr_->matchForward("red.one.tmark.org", match));
  946. EXPECT_EQ("one.tmark.org", match->getName());
  947. // Verify that a FQDN with no match, fails to match.
  948. EXPECT_FALSE(cfg_mgr_->matchForward("shouldbe.wildcard", match));
  949. }
  950. /// @brief Tests domain matching when there is ONLY a wild card domain.
  951. /// This test verifies that any FQDN matches the wild card.
  952. TEST_F(D2CfgMgrTest, matchAll) {
  953. std::string config = "{ "
  954. "\"interface\" : \"eth1\" , "
  955. "\"ip_address\" : \"192.168.1.33\" , "
  956. "\"port\" : 88 , "
  957. "\"tsig_keys\": [] ,"
  958. "\"forward_ddns\" : {"
  959. "\"ddns_domains\": [ "
  960. "{ \"name\": \"*\" , "
  961. " \"dns_servers\" : [ "
  962. " { \"ip_address\": \"127.0.0.1\" } "
  963. " ] } "
  964. "] }, "
  965. "\"reverse_ddns\" : {} "
  966. "}";
  967. ASSERT_TRUE(fromJSON(config));
  968. // Verify that we can parse the configuration.
  969. answer_ = cfg_mgr_->parseConfig(config_set_);
  970. ASSERT_TRUE(checkAnswer(0));
  971. // Verify that the D2 context can be retrieved and is not null.
  972. D2CfgContextPtr context;
  973. ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
  974. // Verify that wild card domain is returned for any FQDN.
  975. DdnsDomainPtr match;
  976. EXPECT_TRUE(cfg_mgr_->matchForward("tmark.org", match));
  977. EXPECT_EQ("*", match->getName());
  978. EXPECT_TRUE(cfg_mgr_->matchForward("shouldbe.wildcard", match));
  979. EXPECT_EQ("*", match->getName());
  980. // Verify that an attempt to match an empty FQDN still throws.
  981. ASSERT_THROW(cfg_mgr_->matchReverse("", match), D2CfgError);
  982. }
  983. /// @brief Tests the basics of the D2CfgMgr reverse FQDN-domain matching
  984. /// This test uses a valid configuration to exercise the D2CfgMgr's
  985. /// reverse FQDN-to-domain matching.
  986. /// It verifies that:
  987. /// 1. Given an FQDN which exactly matches a domain's name, that domain is
  988. /// returned as match.
  989. /// 2. Given a FQDN for sub-domain in the list, returns the proper match.
  990. /// 3. Given a FQDN that matches no domain name, returns the wild card domain
  991. /// as a match.
  992. TEST_F(D2CfgMgrTest, matchReverse) {
  993. std::string config = "{ "
  994. "\"interface\" : \"eth1\" , "
  995. "\"ip_address\" : \"192.168.1.33\" , "
  996. "\"port\" : 88 , "
  997. "\"tsig_keys\": [] ,"
  998. "\"forward_ddns\" : {}, "
  999. "\"reverse_ddns\" : {"
  1000. "\"ddns_domains\": [ "
  1001. "{ \"name\": \"5.100.168.192.in-addr.arpa.\" , "
  1002. " \"dns_servers\" : [ "
  1003. " { \"ip_address\": \"127.0.0.1\" } "
  1004. " ] }, "
  1005. "{ \"name\": \"100.200.192.in-addr.arpa.\" , "
  1006. " \"dns_servers\" : [ "
  1007. " { \"ip_address\": \"127.0.0.1\" } "
  1008. " ] }, "
  1009. "{ \"name\": \"170.192.in-addr.arpa.\" , "
  1010. " \"dns_servers\" : [ "
  1011. " { \"ip_address\": \"127.0.0.1\" } "
  1012. " ] }, "
  1013. // Note mixed case to test case insensitivity.
  1014. "{ \"name\": \"2.0.3.0.8.b.d.0.1.0.0.2.IP6.ARPA.\" , "
  1015. " \"dns_servers\" : [ "
  1016. " { \"ip_address\": \"127.0.0.1\" } "
  1017. " ] },"
  1018. "{ \"name\": \"*\" , "
  1019. " \"dns_servers\" : [ "
  1020. " { \"ip_address\": \"127.0.0.1\" } "
  1021. " ] } "
  1022. "] } }";
  1023. ASSERT_TRUE(fromJSON(config));
  1024. // Verify that we can parse the configuration.
  1025. answer_ = cfg_mgr_->parseConfig(config_set_);
  1026. ASSERT_TRUE(checkAnswer(0));
  1027. // Verify that the D2 context can be retrieved and is not null.
  1028. D2CfgContextPtr context;
  1029. ASSERT_NO_THROW(context = cfg_mgr_->getD2CfgContext());
  1030. // Test directional update flags.
  1031. EXPECT_FALSE(cfg_mgr_->forwardUpdatesEnabled());
  1032. EXPECT_TRUE(cfg_mgr_->reverseUpdatesEnabled());
  1033. DdnsDomainPtr match;
  1034. // Verify an exact match.
  1035. EXPECT_TRUE(cfg_mgr_->matchReverse("192.168.100.5", match));
  1036. EXPECT_EQ("5.100.168.192.in-addr.arpa.", match->getName());
  1037. // Verify a sub-domain match.
  1038. EXPECT_TRUE(cfg_mgr_->matchReverse("192.200.100.27", match));
  1039. EXPECT_EQ("100.200.192.in-addr.arpa.", match->getName());
  1040. // Verify a sub-domain match.
  1041. EXPECT_TRUE(cfg_mgr_->matchReverse("192.170.50.30", match));
  1042. EXPECT_EQ("170.192.in-addr.arpa.", match->getName());
  1043. // Verify a wild card match.
  1044. EXPECT_TRUE(cfg_mgr_->matchReverse("1.1.1.1", match));
  1045. EXPECT_EQ("*", match->getName());
  1046. // Verify a IPv6 match.
  1047. EXPECT_TRUE(cfg_mgr_->matchReverse("2001:db8:302:99::",match));
  1048. EXPECT_EQ("2.0.3.0.8.b.d.0.1.0.0.2.IP6.ARPA.", match->getName());
  1049. // Verify a IPv6 wild card match.
  1050. EXPECT_TRUE(cfg_mgr_->matchReverse("2001:db8:99:302::",match));
  1051. EXPECT_EQ("*", match->getName());
  1052. // Verify that an attempt to match an invalid IP address throws.
  1053. ASSERT_THROW(cfg_mgr_->matchReverse("", match), D2CfgError);
  1054. }
  1055. } // end of anonymous namespace