cfg_iface_unittest.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright (C) 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 <dhcp/dhcp4.h>
  16. #include <dhcp/tests/iface_mgr_test_config.h>
  17. #include <dhcpsrv/cfg_iface.h>
  18. #include <gtest/gtest.h>
  19. using namespace isc;
  20. using namespace isc::dhcp;
  21. using namespace isc::dhcp::test;
  22. namespace {
  23. /// @brief Test fixture class for testing the @c CfgIface class.
  24. class CfgIfaceTest : public ::testing::Test {
  25. public:
  26. /// @brief Constructor.
  27. ///
  28. /// By initializing the @c IfaceMgrTestConfig object it creates a set of
  29. /// fake interfaces: lo, eth0, eth1.
  30. CfgIfaceTest() :
  31. iface_mgr_test_config_(true) {
  32. }
  33. /// @brief Checks if socket of the specified family is opened on interface.
  34. ///
  35. /// @param iface_name Interface name.
  36. /// @param family One of: AF_INET or AF_INET6
  37. bool socketOpen(const std::string& iface_name, const int family) const;
  38. /// @brief Checks if unicast socket is opened on interface.
  39. ///
  40. /// @param iface_name Interface name.
  41. bool unicastOpen(const std::string& iface_name) const;
  42. /// @brief Holds a fake configuration of the interfaces.
  43. IfaceMgrTestConfig iface_mgr_test_config_;
  44. };
  45. bool
  46. CfgIfaceTest::socketOpen(const std::string& iface_name,
  47. const int family) const {
  48. return (iface_mgr_test_config_.socketOpen(iface_name, family));
  49. }
  50. bool
  51. CfgIfaceTest::unicastOpen(const std::string& iface_name) const {
  52. return (iface_mgr_test_config_.unicastOpen(iface_name));
  53. }
  54. // This test checks that the interface names can be explicitly selected
  55. // by their names and IPv4 sockets are opened on these interfaces.
  56. TEST_F(CfgIfaceTest, explicitNamesV4) {
  57. CfgIface cfg(CfgIface::V4);
  58. // Specify valid interface names. There should be no error.
  59. ASSERT_NO_THROW(cfg.use("eth0"));
  60. ASSERT_NO_THROW(cfg.use("eth1"));
  61. // Open sockets on specified interfaces.
  62. cfg.openSockets(DHCP4_SERVER_PORT);
  63. // Sockets should be now open on eth0 and eth1, but not on loopback.
  64. EXPECT_TRUE(socketOpen("eth0", AF_INET));
  65. EXPECT_TRUE(socketOpen("eth1", AF_INET));
  66. EXPECT_FALSE(socketOpen("lo", AF_INET));
  67. // No IPv6 sockets should be present because we wanted IPv4 sockets.
  68. EXPECT_FALSE(socketOpen("eth0", AF_INET6));
  69. EXPECT_FALSE(socketOpen("eth1", AF_INET6));
  70. EXPECT_FALSE(socketOpen("lo", AF_INET6));
  71. // Close all sockets and make sure they are really closed.
  72. cfg.closeSockets();
  73. ASSERT_FALSE(socketOpen("eth0", AF_INET));
  74. ASSERT_FALSE(socketOpen("eth1", AF_INET));
  75. ASSERT_FALSE(socketOpen("lo", AF_INET));
  76. // Reset configuration and select only one interface this time.
  77. cfg.reset();
  78. ASSERT_NO_THROW(cfg.use("eth1"));
  79. cfg.openSockets(DHCP4_SERVER_PORT);
  80. // Socket should be open on eth1 only.
  81. EXPECT_FALSE(socketOpen("eth0", AF_INET));
  82. EXPECT_TRUE(socketOpen("eth1", AF_INET));
  83. EXPECT_FALSE(socketOpen("lo", AF_INET));
  84. }
  85. // This test checks that the interface names can be explicitly selected
  86. // by their names and IPv6 sockets are opened on these interfaces.
  87. TEST_F(CfgIfaceTest, explicitNamesV6) {
  88. CfgIface cfg(CfgIface::V6);
  89. // Specify valid interface names. There should be no error.
  90. ASSERT_NO_THROW(cfg.use("eth0"));
  91. ASSERT_NO_THROW(cfg.use("eth1"));
  92. // Open sockets on specified interfaces.
  93. cfg.openSockets(DHCP6_SERVER_PORT);
  94. // Sockets should be now open on eth0 and eth1, but not on loopback.
  95. EXPECT_TRUE(socketOpen("eth0", AF_INET6));
  96. EXPECT_TRUE(socketOpen("eth1", AF_INET6));
  97. EXPECT_FALSE(socketOpen("lo", AF_INET6));
  98. // No IPv4 sockets should be present because we wanted IPv4 sockets.
  99. EXPECT_FALSE(socketOpen("eth0", AF_INET));
  100. EXPECT_FALSE(socketOpen("eth1", AF_INET));
  101. EXPECT_FALSE(socketOpen("lo", AF_INET));
  102. // Close all sockets and make sure they are really closed.
  103. cfg.closeSockets();
  104. ASSERT_FALSE(socketOpen("eth0", AF_INET6));
  105. ASSERT_FALSE(socketOpen("eth1", AF_INET6));
  106. ASSERT_FALSE(socketOpen("lo", AF_INET6));
  107. // Reset configuration and select only one interface this time.
  108. cfg.reset();
  109. ASSERT_NO_THROW(cfg.use("eth1"));
  110. cfg.openSockets(DHCP6_SERVER_PORT);
  111. // Socket should be open on eth1 only.
  112. EXPECT_FALSE(socketOpen("eth0", AF_INET6));
  113. EXPECT_TRUE(socketOpen("eth1", AF_INET6));
  114. EXPECT_FALSE(socketOpen("lo", AF_INET6));
  115. }
  116. // This test checks that the wildcard interface name can be specified to
  117. // select all interfaces to open IPv4 sockets.
  118. TEST_F(CfgIfaceTest, wildcardV4) {
  119. CfgIface cfg(CfgIface::V4);
  120. ASSERT_NO_THROW(cfg.use("*"));
  121. cfg.openSockets(DHCP4_SERVER_PORT);
  122. // Sockets should be now open on eth0 and eth1, but not on loopback.
  123. EXPECT_TRUE(socketOpen("eth0", AF_INET));
  124. EXPECT_TRUE(socketOpen("eth1", AF_INET));
  125. EXPECT_FALSE(socketOpen("lo", AF_INET));
  126. // No IPv6 sockets should be present because we wanted IPv4 sockets.
  127. EXPECT_FALSE(socketOpen("eth0", AF_INET6));
  128. EXPECT_FALSE(socketOpen("eth1", AF_INET6));
  129. EXPECT_FALSE(socketOpen("lo", AF_INET6));
  130. }
  131. // This test checks that the wildcard interface name can be specified to
  132. // select all interfaces to open IPv6 sockets.
  133. TEST_F(CfgIfaceTest, wildcardV6) {
  134. CfgIface cfg(CfgIface::V6);
  135. ASSERT_NO_THROW(cfg.use("*"));
  136. cfg.openSockets(DHCP4_SERVER_PORT);
  137. // Sockets should be now open on eth0 and eth1, but not on loopback.
  138. EXPECT_TRUE(socketOpen("eth0", AF_INET6));
  139. EXPECT_TRUE(socketOpen("eth1", AF_INET6));
  140. EXPECT_FALSE(socketOpen("lo", AF_INET6));
  141. // No IPv6 sockets should be present because we wanted IPv6 sockets.
  142. EXPECT_FALSE(socketOpen("eth0", AF_INET));
  143. EXPECT_FALSE(socketOpen("eth1", AF_INET));
  144. EXPECT_FALSE(socketOpen("lo", AF_INET));
  145. }
  146. // Test that unicast address can be specified for the socket to be opened on
  147. // the interface on which the socket bound to link local address is also
  148. // opened.
  149. TEST_F(CfgIfaceTest, validUnicast) {
  150. CfgIface cfg(CfgIface::V6);
  151. // One socket will be opened on link-local address, one on unicast but
  152. // on the same interface.
  153. ASSERT_NO_THROW(cfg.use("eth0"));
  154. ASSERT_NO_THROW(cfg.use("eth0/2001:db8:1::1"));
  155. cfg.openSockets(DHCP6_SERVER_PORT);
  156. EXPECT_TRUE(socketOpen("eth0", AF_INET6));
  157. EXPECT_TRUE(unicastOpen("eth0"));
  158. }
  159. // Test that when invalid interface names are specified an exception is thrown.
  160. TEST_F(CfgIfaceTest, invalidValues) {
  161. CfgIface cfg(CfgIface::V4);
  162. ASSERT_THROW(cfg.use(""), InvalidIfaceName);
  163. ASSERT_THROW(cfg.use(" "), InvalidIfaceName);
  164. ASSERT_THROW(cfg.use("bogus"), NoSuchIface);
  165. ASSERT_NO_THROW(cfg.use("eth0"));
  166. ASSERT_THROW(cfg.use("eth0"), DuplicateIfaceName);
  167. ASSERT_THROW(cfg.use("eth0/2001:db8:1::1"), InvalidIfaceName);
  168. cfg.setFamily(CfgIface::V6);
  169. ASSERT_THROW(cfg.use("eth0/"), InvalidIfaceName);
  170. ASSERT_THROW(cfg.use("/2001:db8:1::1"), InvalidIfaceName);
  171. ASSERT_THROW(cfg.use("*/2001:db8:1::1"), InvalidIfaceName);
  172. ASSERT_THROW(cfg.use("bogus/2001:db8:1::1"), NoSuchIface);
  173. ASSERT_THROW(cfg.use("eth0/fe80::3a60:77ff:fed5:cdef"), InvalidIfaceName);
  174. ASSERT_THROW(cfg.use("eth0/fe80::3a60:77ff:fed5:cdef"), InvalidIfaceName);
  175. ASSERT_THROW(cfg.use("eth0/2001:db8:1::2"), NoSuchAddress);
  176. ASSERT_NO_THROW(cfg.use("*"));
  177. ASSERT_THROW(cfg.use("*"), DuplicateIfaceName);
  178. }
  179. } // end of anonymous namespace