ifaces_config_parser_unittest.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <cc/data.h>
  8. #include <dhcp/tests/iface_mgr_test_config.h>
  9. #include <dhcpsrv/cfgmgr.h>
  10. #include <dhcpsrv/parsers/ifaces_config_parser.h>
  11. #include <gtest/gtest.h>
  12. using namespace isc::data;
  13. using namespace isc::dhcp;
  14. using namespace isc::dhcp::test;
  15. namespace {
  16. /// @brief Test fixture class for @c IfacesConfigParser
  17. class IfacesConfigParserTest : public ::testing::Test {
  18. protected:
  19. /// @brief Setup for each test.
  20. ///
  21. /// Clears the configuration in the @c CfgMgr.
  22. virtual void SetUp();
  23. /// @brief Cleans up after each test.
  24. ///
  25. /// Clears the configuration in the @c CfgMgr.
  26. virtual void TearDown();
  27. };
  28. void
  29. IfacesConfigParserTest::SetUp() {
  30. CfgMgr::instance().clear();
  31. }
  32. void
  33. IfacesConfigParserTest::TearDown() {
  34. CfgMgr::instance().clear();
  35. }
  36. // This test checks that the parser correctly parses the list of interfaces
  37. // on which the server should listen.
  38. TEST_F(IfacesConfigParserTest, interfaces) {
  39. // Creates fake interfaces with fake addresses.
  40. IfaceMgrTestConfig test_config(true);
  41. // Configuration with one interface.
  42. std::string config = "{ ""\"interfaces\": [ \"eth0\" ] }";
  43. ElementPtr config_element = Element::fromJSON(config);
  44. // Parse the configuration.
  45. IfacesConfigParser parser(AF_INET);
  46. CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
  47. ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
  48. // Open sockets according to the parsed configuration.
  49. SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
  50. ASSERT_TRUE(cfg);
  51. ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
  52. // Only eth0 should have an open socket.
  53. EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
  54. EXPECT_FALSE(test_config.socketOpen("eth1", AF_INET));
  55. // Reset configuration.
  56. cfg->getCfgIface()->closeSockets();
  57. CfgMgr::instance().clear();
  58. // Try similar configuration but this time add a wildcard interface
  59. // to see if sockets will open on all interfaces.
  60. config = "{ \"interfaces\": [ \"eth0\", \"*\" ] }";
  61. config_element = Element::fromJSON(config);
  62. cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
  63. ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
  64. cfg = CfgMgr::instance().getStagingCfg();
  65. ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
  66. EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
  67. EXPECT_TRUE(test_config.socketOpen("eth1", AF_INET));
  68. }
  69. // This test verifies that it is possible to select the raw socket
  70. // use in the configuration for interfaces.
  71. TEST_F(IfacesConfigParserTest, socketTypeRaw) {
  72. // Create the reference configuration, which we will compare
  73. // the parsed configuration to.
  74. CfgIface cfg_ref;
  75. // Configuration with a raw socket selected.
  76. std::string config = "{ ""\"interfaces\": [ ],"
  77. " \"dhcp-socket-type\": \"raw\" }";
  78. ElementPtr config_element = Element::fromJSON(config);
  79. // Parse the configuration.
  80. IfacesConfigParser parser(AF_INET);
  81. CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
  82. ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
  83. // Compare the resulting configuration with a reference
  84. // configuration using the raw socket.
  85. SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
  86. ASSERT_TRUE(cfg);
  87. cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_RAW);
  88. EXPECT_TRUE(*cfg->getCfgIface() == cfg_ref);
  89. }
  90. // This test verifies that it is possible to select the datagram socket
  91. // use in the configuration for interfaces.
  92. TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
  93. // Create the reference configuration, which we will compare
  94. // the parsed configuration to.
  95. CfgIface cfg_ref;
  96. // Configuration with a datagram socket selected.
  97. std::string config = "{ ""\"interfaces\": [ ],"
  98. " \"dhcp-socket-type\": \"udp\" }";
  99. ElementPtr config_element = Element::fromJSON(config);
  100. // Parse the configuration.
  101. IfacesConfigParser parser(AF_INET);
  102. CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
  103. ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
  104. // Compare the resulting configuration with a reference
  105. // configuration using the raw socket.
  106. SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
  107. ASSERT_TRUE(cfg);
  108. cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_UDP);
  109. EXPECT_TRUE(*cfg->getCfgIface() == cfg_ref);
  110. }
  111. // Test that the configuration rejects the invalid socket type.
  112. TEST_F(IfacesConfigParserTest, socketTypeInvalid) {
  113. // For DHCPv4 we only accept the raw socket or datagram socket.
  114. IfacesConfigParser parser4(AF_INET);
  115. CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
  116. std::string config = "{ \"interfaces\": [ ],"
  117. "\"dhcp-socket-type\": \"default\" }";
  118. ElementPtr config_element = Element::fromJSON(config);
  119. ASSERT_THROW(parser4.parse(cfg_iface, config_element), DhcpConfigError);
  120. // For DHCPv6 we don't accept any socket type.
  121. IfacesConfigParser parser6(AF_INET6);
  122. config = "{ \"interfaces\": [ ],"
  123. " \"dhcp-socket-type\": \"udp\" }";
  124. config_element = Element::fromJSON(config);
  125. ASSERT_THROW(parser6.parse(cfg_iface, config_element), DhcpConfigError);
  126. }
  127. } // end of anonymous namespace