Browse Source

[3604] The CfgIface is returned by a pointer, not reference.

Marcin Siodelski 10 years ago
parent
commit
263be04a7f

+ 2 - 3
src/bin/dhcp4/ctrl_dhcp4_srv.cc

@@ -151,9 +151,8 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
     // log warnings. Since we allow that this fails for some interfaces there
     // log warnings. Since we allow that this fails for some interfaces there
     // is no need to rollback configuration if socket fails to open on any
     // is no need to rollback configuration if socket fails to open on any
     // of the interfaces.
     // of the interfaces.
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET, srv->getPort(),
-                                  getInstance()->useBroadcast());
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->
+        openSockets(AF_INET, srv->getPort(), getInstance()->useBroadcast());
 
 
     return (answer);
     return (answer);
 }
 }

+ 8 - 6
src/bin/dhcp4/tests/config_parser_unittest.cc

@@ -964,6 +964,7 @@ TEST_F(Dhcp4ParserTest, nextServerSubnet) {
 // Test checks several negative scenarios for next-server configuration: bogus
 // Test checks several negative scenarios for next-server configuration: bogus
 // address, IPv6 adddress and empty string.
 // address, IPv6 adddress and empty string.
 TEST_F(Dhcp4ParserTest, nextServerNegative) {
 TEST_F(Dhcp4ParserTest, nextServerNegative) {
+    IfaceMgrTestConfig test_config(true);
 
 
     ConstElementPtr status;
     ConstElementPtr status;
 
 
@@ -1012,10 +1013,14 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
     checkResult(status, 1);
     checkResult(status, 1);
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 
 
+    CfgMgr::instance().clear();
+
     EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json2));
     EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json2));
     checkResult(status, 1);
     checkResult(status, 1);
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 
 
+    CfgMgr::instance().clear();
+
     EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json3));
     EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json3));
     checkResult(status, 0);
     checkResult(status, 0);
     EXPECT_FALSE(errorContainsPosition(status, "<string>"));
     EXPECT_FALSE(errorContainsPosition(status, "<string>"));
@@ -2970,8 +2975,7 @@ TEST_F(Dhcp4ParserTest, selectedInterfaces) {
     ASSERT_TRUE(status);
     ASSERT_TRUE(status);
     checkResult(status, 0);
     checkResult(status, 0);
 
 
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET, 10000);
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET, 10000);
 
 
     // eth0 and eth1 were explicitly selected. eth2 was not.
     // eth0 and eth1 were explicitly selected. eth2 was not.
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
@@ -3008,8 +3012,7 @@ TEST_F(Dhcp4ParserTest, allInterfaces) {
     ASSERT_TRUE(status);
     ASSERT_TRUE(status);
     checkResult(status, 0);
     checkResult(status, 0);
 
 
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET, 10000);
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET, 10000);
 
 
     // All interfaces should be now active.
     // All interfaces should be now active.
     ASSERT_TRUE(test_config.socketOpen("eth0", AF_INET));
     ASSERT_TRUE(test_config.socketOpen("eth0", AF_INET));
@@ -3044,8 +3047,7 @@ TEST_F(Dhcp4ParserTest, selectedInterfacesAndAddresses) {
     ASSERT_TRUE(status);
     ASSERT_TRUE(status);
     checkResult(status, 0);
     checkResult(status, 0);
 
 
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET, 10000);
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET, 10000);
 
 
     // An address on eth0 was selected
     // An address on eth0 was selected
     EXPECT_TRUE(test_config.socketOpen("eth0", "10.0.0.1"));
     EXPECT_TRUE(test_config.socketOpen("eth0", "10.0.0.1"));

+ 1 - 1
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -3089,7 +3089,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
 TEST_F(Dhcpv4SrvTest, vendorOptionsDocsisDefinitions) {
 TEST_F(Dhcpv4SrvTest, vendorOptionsDocsisDefinitions) {
     ConstElementPtr x;
     ConstElementPtr x;
     string config_prefix = "{ \"interfaces-config\": {"
     string config_prefix = "{ \"interfaces-config\": {"
-        "    \"interfaces\": [ \"*\" ]"
+        "    \"interfaces\": [ ]"
         "},"
         "},"
         "\"rebind-timer\": 2000, "
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"renew-timer\": 1000, "

+ 1 - 2
src/bin/dhcp6/ctrl_dhcp6_srv.cc

@@ -146,8 +146,7 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
     // log warnings. Since we allow that this fails for some interfaces there
     // log warnings. Since we allow that this fails for some interfaces there
     // is no need to rollback configuration if socket fails to open on any
     // is no need to rollback configuration if socket fails to open on any
     // of the interfaces.
     // of the interfaces.
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET6, srv->getPort());
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, srv->getPort());
 
 
     return (answer);
     return (answer);
 }
 }

+ 5 - 5
src/bin/dhcp6/tests/config_parser_unittest.cc

@@ -354,7 +354,9 @@ public:
     /// test to make sure that contents of the database do not affect the
     /// test to make sure that contents of the database do not affect the
     /// results of subsequent tests.
     /// results of subsequent tests.
     void resetConfiguration() {
     void resetConfiguration() {
-        string config = "{ " + genIfaceConfig() + ","
+        string config = "{ \"interfaces-config\": {"
+            "    \"interfaces\": [ ]"
+            "},"
             "\"hooks-libraries\": [ ],"
             "\"hooks-libraries\": [ ],"
             "\"preferred-lifetime\": 3000,"
             "\"preferred-lifetime\": 3000,"
             "\"rebind-timer\": 2000, "
             "\"rebind-timer\": 2000, "
@@ -3104,8 +3106,7 @@ TEST_F(Dhcp6ParserTest, selectedInterfaces) {
     // as the pool does not belong to that subnet
     // as the pool does not belong to that subnet
     checkResult(status, 0);
     checkResult(status, 0);
 
 
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET6, 10000);
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, 10000);
 
 
     // eth0 and eth1 were explicitly selected. eth2 was not.
     // eth0 and eth1 were explicitly selected. eth2 was not.
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
@@ -3140,8 +3141,7 @@ TEST_F(Dhcp6ParserTest, allInterfaces) {
     EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
     EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
     checkResult(status, 0);
     checkResult(status, 0);
 
 
-    CfgMgr::instance().getStagingCfg()->
-        getCfgIface().openSockets(AF_INET6, 10000);
+    CfgMgr::instance().getStagingCfg()->getCfgIface()->openSockets(AF_INET6, 10000);
 
 
     // All interfaces should be now active.
     // All interfaces should be now active.
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));

+ 1 - 1
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1659,7 +1659,7 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsORO) {
 TEST_F(Dhcpv6SrvTest, vendorOptionsDocsisDefinitions) {
 TEST_F(Dhcpv6SrvTest, vendorOptionsDocsisDefinitions) {
     ConstElementPtr x;
     ConstElementPtr x;
     string config_prefix = "{ \"interfaces-config\": {"
     string config_prefix = "{ \"interfaces-config\": {"
-        "  \"interfaces\": [ \"*\" ]"
+        "  \"interfaces\": [ ]"
         "},"
         "},"
         "\"preferred-lifetime\": 3000,"
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
         "\"rebind-timer\": 2000, "

+ 2 - 1
src/lib/dhcp/iface_mgr.cc

@@ -197,7 +197,8 @@ IfaceMgr::IfaceMgr()
     :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
     :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
      control_buf_(new char[control_buf_len_]),
      control_buf_(new char[control_buf_len_]),
      packet_filter_(new PktFilterInet()),
      packet_filter_(new PktFilterInet()),
-     packet_filter6_(new PktFilterInet6())
+     packet_filter6_(new PktFilterInet6()),
+     test_mode_(false)
 {
 {
 
 
     try {
     try {

+ 23 - 0
src/lib/dhcp/iface_mgr.h

@@ -534,6 +534,26 @@ public:
     /// @return the only existing instance of interface manager
     /// @return the only existing instance of interface manager
     static IfaceMgr& instance();
     static IfaceMgr& instance();
 
 
+    /// @brief Sets or clears the test mode for @c IfaceMgr.
+    ///
+    /// Various unit test may set this flag to true, to indicate that the 
+    /// @c IfaceMgr is in the test mode. There are places in the code that
+    /// modify the behavior depending if the @c IfaceMgr is in the test
+    /// mode or not.
+    ///
+    /// @param test_mode A flag which indicates that the @c IfaceMgr is in the
+    /// test mode (if true), or not (if false).
+    void setTestMode(const bool test_mode) {
+        test_mode_ = test_mode;
+    }
+
+    /// @brief Checks if the @c IfaceMgr is in the test mode.
+    ///
+    /// @return true if the @c IfaceMgr is in the test mode, false otherwise.
+    bool isTestMode() const {
+        return (test_mode_);
+    }
+
     /// @brief Check if packet be sent directly to the client having no address.
     /// @brief Check if packet be sent directly to the client having no address.
     ///
     ///
     /// Checks if IfaceMgr can send DHCPv4 packet to the client
     /// Checks if IfaceMgr can send DHCPv4 packet to the client
@@ -1167,6 +1187,9 @@ private:
 
 
     /// @brief Contains list of callbacks for external sockets
     /// @brief Contains list of callbacks for external sockets
     SocketCallbackInfoContainer callbacks_;
     SocketCallbackInfoContainer callbacks_;
+
+    /// @brief Indicates if the IfaceMgr is in the test mode.
+    bool test_mode_;
 };
 };
 
 
 }; // namespace isc::dhcp
 }; // namespace isc::dhcp

+ 2 - 1
src/lib/dhcp/tests/iface_mgr_test_config.cc

@@ -26,6 +26,7 @@ namespace dhcp {
 namespace test {
 namespace test {
 
 
 IfaceMgrTestConfig::IfaceMgrTestConfig(const bool default_config) {
 IfaceMgrTestConfig::IfaceMgrTestConfig(const bool default_config) {
+    IfaceMgr::instance().setTestMode(true);
     IfaceMgr::instance().closeSockets();
     IfaceMgr::instance().closeSockets();
     IfaceMgr::instance().clearIfaces();
     IfaceMgr::instance().clearIfaces();
     packet_filter4_ = PktFilterPtr(new PktFilterTestStub());
     packet_filter4_ = PktFilterPtr(new PktFilterTestStub());
@@ -44,7 +45,7 @@ IfaceMgrTestConfig::~IfaceMgrTestConfig() {
     IfaceMgr::instance().clearIfaces();
     IfaceMgr::instance().clearIfaces();
     IfaceMgr::instance().setPacketFilter(PktFilterPtr(new PktFilterInet()));
     IfaceMgr::instance().setPacketFilter(PktFilterPtr(new PktFilterInet()));
     IfaceMgr::instance().setPacketFilter(PktFilter6Ptr(new PktFilterInet6()));
     IfaceMgr::instance().setPacketFilter(PktFilter6Ptr(new PktFilterInet6()));
-
+    IfaceMgr::instance().setTestMode(false);
     IfaceMgr::instance().detectIfaces();
     IfaceMgr::instance().detectIfaces();
 }
 }
 
 

+ 21 - 7
src/lib/dhcpsrv/cfg_iface.cc

@@ -26,7 +26,7 @@ namespace dhcp {
 const char* CfgIface::ALL_IFACES_KEYWORD = "*";
 const char* CfgIface::ALL_IFACES_KEYWORD = "*";
 
 
 CfgIface::CfgIface()
 CfgIface::CfgIface()
-    : wildcard_used_(false), socket_type_(SOCKET_DEFAULT) {
+    : wildcard_used_(false), socket_type_(SOCKET_DGRAM) {
 }
 }
 
 
 void
 void
@@ -60,7 +60,9 @@ CfgIface::openSockets(const uint16_t family, const uint16_t port,
     // IP address. This should effectively turn on the use of raw
     // IP address. This should effectively turn on the use of raw
     // sockets. However, this may be unsupported on some operating
     // sockets. However, this may be unsupported on some operating
     // systems, so there is no guarantee.
     // systems, so there is no guarantee.
-    if ((family == AF_INET) && (socket_type_ != SOCKET_DEFAULT)) {
+    if ((family == AF_INET) && (!IfaceMgr::instance().isTestMode())) {
+        LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_SELECT)
+            .arg(socketTypeToText());
         iface_mgr.setMatchingPacketFilter(socket_type_ == SOCKET_RAW);
         iface_mgr.setMatchingPacketFilter(socket_type_ == SOCKET_RAW);
         if ((socket_type_ == SOCKET_RAW) &&
         if ((socket_type_ == SOCKET_RAW) &&
             !iface_mgr.isDirectResponseSupported()) {
             !iface_mgr.isDirectResponseSupported()) {
@@ -151,7 +153,7 @@ CfgIface::reset() {
     wildcard_used_ = false;
     wildcard_used_ = false;
     iface_set_.clear();
     iface_set_.clear();
     address_map_.clear();
     address_map_.clear();
-    socket_type_ = SOCKET_DEFAULT;
+    useSocketType(AF_INET, SOCKET_DGRAM);
 }
 }
 
 
 void
 void
@@ -186,6 +188,22 @@ CfgIface::socketOpenErrorHandler(const std::string& errmsg) {
     LOG_WARN(dhcpsrv_logger, DHCPSRV_OPEN_SOCKET_FAIL).arg(errmsg);
     LOG_WARN(dhcpsrv_logger, DHCPSRV_OPEN_SOCKET_FAIL).arg(errmsg);
 }
 }
 
 
+std::string
+CfgIface::socketTypeToText() const {
+    switch (socket_type_) {
+    case SOCKET_RAW:
+        return ("raw");
+
+    case SOCKET_DGRAM:
+        return ("datagram");
+
+    default:
+        ;
+    }
+
+    isc_throw(Unexpected, "unsupported socket type " << socket_type_);
+}
+
 void
 void
 CfgIface::use(const uint16_t family, const std::string& iface_name) {
 CfgIface::use(const uint16_t family, const std::string& iface_name) {
     // The interface name specified may have two formats, e.g.:
     // The interface name specified may have two formats, e.g.:
@@ -338,10 +356,6 @@ CfgIface::useSocketType(const uint16_t family,
     if (family != AF_INET) {
     if (family != AF_INET) {
         isc_throw(InvalidSocketType, "socket type must not be specified for"
         isc_throw(InvalidSocketType, "socket type must not be specified for"
                   " the DHCPv6 server");
                   " the DHCPv6 server");
-    } else if (socket_type == SOCKET_DEFAULT) {
-            isc_throw(InvalidSocketType, "invalid value SOCKET_DEFAULT"
-                      " used to specify the socket type to be used by"
-                      " the DHCPv4 server");
     }
     }
     socket_type_ = socket_type;
     socket_type_ = socket_type;
 }
 }

+ 12 - 8
src/lib/dhcpsrv/cfg_iface.h

@@ -16,8 +16,10 @@
 #define CFG_IFACE_H
 #define CFG_IFACE_H
 
 
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
+#include <boost/shared_ptr.hpp>
 #include <map>
 #include <map>
 #include <set>
 #include <set>
+#include <string>
 
 
 namespace isc {
 namespace isc {
 namespace dhcp {
 namespace dhcp {
@@ -81,12 +83,7 @@ public:
 /// in such case the use of datagram sockets is preferred. The type of the
 /// in such case the use of datagram sockets is preferred. The type of the
 /// sockets to be opened is specified using one of the
 /// sockets to be opened is specified using one of the
 /// @c CfgIface::useSocketType method variants. The @c CfgIface::SocketType
 /// @c CfgIface::useSocketType method variants. The @c CfgIface::SocketType
-/// enumeration specifies the possible values. The @c CfgIface::SOCKET_DEFAULT
-/// is a default setting of the @c CfgIface and it indicates that the
-/// @c IfaceMgr should continue using the currently used sockets' type.
-/// This is mostly used for unit testing to avoid modifying fake
-/// configurations of the @c IfaceMgr. In the real case, one of the
-/// remaining values should be used.
+/// enumeration specifies the possible values.
 ///
 ///
 /// @warning This class makes use of the AF_INET and AF_INET6 family literals,
 /// @warning This class makes use of the AF_INET and AF_INET6 family literals,
 /// but it doesn't verify that the address family value passed as @c uint16_t
 /// but it doesn't verify that the address family value passed as @c uint16_t
@@ -97,8 +94,6 @@ public:
 
 
     /// @brief Socket type used by the DHCPv4 server.
     /// @brief Socket type used by the DHCPv4 server.
     enum SocketType  {
     enum SocketType  {
-        /// Default socket type, mainly used for testing.
-        SOCKET_DEFAULT,
         /// Raw socket, used for direct DHCPv4 traffic.
         /// Raw socket, used for direct DHCPv4 traffic.
         SOCKET_RAW,
         SOCKET_RAW,
         /// Datagram socket, i.e. IP/UDP socket.
         /// Datagram socket, i.e. IP/UDP socket.
@@ -247,6 +242,9 @@ private:
     /// @param errmsg Error message being logged by the function.
     /// @param errmsg Error message being logged by the function.
     static void socketOpenErrorHandler(const std::string& errmsg);
     static void socketOpenErrorHandler(const std::string& errmsg);
 
 
+    /// @brief Returns the socket type in the textual format.
+    std::string socketTypeToText() const;
+
     /// @brief Represents a set of interface names.
     /// @brief Represents a set of interface names.
     typedef std::set<std::string> IfaceSet;
     typedef std::set<std::string> IfaceSet;
 
 
@@ -269,6 +267,12 @@ private:
     SocketType socket_type_;
     SocketType socket_type_;
 };
 };
 
 
+/// @brief A pointer to the @c CfgIface .
+typedef boost::shared_ptr<CfgIface> CfgIfacePtr;
+
+/// @brief A pointer to the const @c CfgIface.
+typedef boost::shared_ptr<const CfgIface> ConstCfgIfacePtr;
+
 }
 }
 }
 }
 
 

+ 9 - 0
src/lib/dhcpsrv/dhcpsrv_messages.mes

@@ -111,6 +111,15 @@ back to use of the datagram IP/UDP sockets. The responses to
 the directly connected clients will be broadcast. The responses
 the directly connected clients will be broadcast. The responses
 to relayed clients will be unicast as usual.
 to relayed clients will be unicast as usual.
 
 
+% DHCPSRV_CFGMGR_SOCKET_TYPE_SELECT trying to use socket type %1
+This informational message is logged when the DHCPv4 server selects the
+socket type to be used for all sockets that will be opened on the
+interfaces. Typically, the socket type is specified by the server
+administrator. If the socket type hasn't been specified, the raw
+socket will be selected. If the raw socket has been selected but
+Kea doesn't support the use of raw sockets on the particular
+OS, it will use a datagram socket instead.
+
 % DHCPSRV_CFGMGR_SUBNET4 retrieved subnet %1 for address hint %2
 % DHCPSRV_CFGMGR_SUBNET4 retrieved subnet %1 for address hint %2
 This is a debug message reporting that the DHCP configuration manager has
 This is a debug message reporting that the DHCP configuration manager has
 returned the specified IPv4 subnet when given the address hint specified
 returned the specified IPv4 subnet when given the address hint specified

+ 10 - 6
src/lib/dhcpsrv/parsers/ifaces_config_parser.cc

@@ -30,19 +30,18 @@ InterfaceListConfigParser::InterfaceListConfigParser(const int protocol)
 
 
 void
 void
 InterfaceListConfigParser::build(ConstElementPtr value) {
 InterfaceListConfigParser::build(ConstElementPtr value) {
-    CfgIface cfg_iface;
+    CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
 
 
     BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
     BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
         std::string iface_name = iface->stringValue();
         std::string iface_name = iface->stringValue();
         try {
         try {
-            cfg_iface.use(protocol_, iface_name);
+            cfg_iface->use(protocol_, iface_name);
 
 
         } catch (const std::exception& ex) {
         } catch (const std::exception& ex) {
             isc_throw(DhcpConfigError, "Failed to select interface: "
             isc_throw(DhcpConfigError, "Failed to select interface: "
                       << ex.what() << " (" << value->getPosition() << ")");
                       << ex.what() << " (" << value->getPosition() << ")");
         }
         }
     }
     }
-    CfgMgr::instance().getStagingCfg()->setCfgIface(cfg_iface);
 }
 }
 
 
 void
 void
@@ -86,12 +85,17 @@ IfacesConfigParser4::IfacesConfigParser4()
 void
 void
 IfacesConfigParser4::build(isc::data::ConstElementPtr ifaces_config) {
 IfacesConfigParser4::build(isc::data::ConstElementPtr ifaces_config) {
     IfacesConfigParser::build(ifaces_config);
     IfacesConfigParser::build(ifaces_config);
+
+    // Get the pointer to the interface configuration.
+    CfgIfacePtr cfg = CfgMgr::instance().getStagingCfg()->getCfgIface();
+    // The default is to use the raw sockets, if the "socket-type" parameter
+    // hasn't been specified.
+    cfg->useSocketType(AF_INET, CfgIface::SOCKET_RAW);
+
     BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
     BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
         try {
         try {
             if (element.first == "socket-type") {
             if (element.first == "socket-type") {
-                CfgIface cfg = CfgMgr::instance().getStagingCfg()->getCfgIface();
-                cfg.useSocketType(AF_INET, element.second->stringValue());
-                CfgMgr::instance().getStagingCfg()->setCfgIface(cfg);
+                cfg->useSocketType(AF_INET, element.second->stringValue());
 
 
             } else if (!isGenericParameter(element.first)) {
             } else if (!isGenericParameter(element.first)) {
                 isc_throw(DhcpConfigError, "usupported parameter '"
                 isc_throw(DhcpConfigError, "usupported parameter '"

+ 11 - 9
src/lib/dhcpsrv/srv_config.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -26,15 +26,17 @@ namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
 SrvConfig::SrvConfig()
 SrvConfig::SrvConfig()
-    : sequence_(0), cfg_option_def_(new CfgOptionDef()),
-      cfg_option_(new CfgOption()), cfg_subnets4_(new CfgSubnets4()),
-      cfg_subnets6_(new CfgSubnets6()), cfg_hosts_(new CfgHosts()) {
+    : sequence_(0), cfg_iface_(new CfgIface()),
+      cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
+      cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
+      cfg_hosts_(new CfgHosts()) {
 }
 }
 
 
 SrvConfig::SrvConfig(const uint32_t sequence)
 SrvConfig::SrvConfig(const uint32_t sequence)
-    : sequence_(sequence), cfg_option_def_(new CfgOptionDef()),
-      cfg_option_(new CfgOption()), cfg_subnets4_(new CfgSubnets4()),
-      cfg_subnets6_(new CfgSubnets6()), cfg_hosts_(new CfgHosts()) {
+    : sequence_(sequence), cfg_iface_(new CfgIface()),
+      cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
+      cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
+      cfg_hosts_(new CfgHosts()) {
 }
 }
 
 
 std::string
 std::string
@@ -92,7 +94,7 @@ SrvConfig::copy(SrvConfig& new_config) const {
         new_config.addLoggingInfo(*it);
         new_config.addLoggingInfo(*it);
     }
     }
     // Replace interface configuration.
     // Replace interface configuration.
-    new_config.setCfgIface(cfg_iface_);
+    new_config.cfg_iface_.reset(new CfgIface(*cfg_iface_));
     // Replace option definitions.
     // Replace option definitions.
     cfg_option_def_->copyTo(*new_config.cfg_option_def_);
     cfg_option_def_->copyTo(*new_config.cfg_option_def_);
     cfg_option_->copyTo(*new_config.cfg_option_);
     cfg_option_->copyTo(*new_config.cfg_option_);
@@ -137,7 +139,7 @@ SrvConfig::equals(const SrvConfig& other) const {
         }
         }
     }
     }
     // Logging information is equal between objects, so check other values.
     // Logging information is equal between objects, so check other values.
-    return ((cfg_iface_ == other.cfg_iface_) &&
+    return ((*cfg_iface_ == *other.cfg_iface_) &&
             (*cfg_option_def_ == *other.cfg_option_def_) &&
             (*cfg_option_def_ == *other.cfg_option_def_) &&
             (*cfg_option_ == *other.cfg_option_));
             (*cfg_option_ == *other.cfg_option_));
 }
 }

+ 14 - 11
src/lib/dhcpsrv/srv_config.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -129,21 +129,24 @@ public:
         logging_info_.push_back(logging_info);
         logging_info_.push_back(logging_info);
     }
     }
 
 
-    /// @brief Returns object which represents selection of interfaces.
+    /// @brief Returns non-const pointer to interface configuration.
     ///
     ///
-    /// This function returns a reference to the object which represents the
-    /// set of interfaces being used to receive DHCP traffic.
+    /// This function returns a non-const pointer to the interface
+    /// configuration.
     ///
     ///
-    /// @return Object representing selection of interfaces.
-    const CfgIface& getCfgIface() const {
+    /// @return Object representing configuration of interfaces.
+    CfgIfacePtr getCfgIface() {
         return (cfg_iface_);
         return (cfg_iface_);
     }
     }
 
 
-    /// @brief Sets the object representing selection of interfaces.
+    /// @brief Returns const pointer to interface configuration.
     ///
     ///
-    /// @param cfg_iface Object representing selection of interfaces.
-    void setCfgIface(const CfgIface& cfg_iface) {
-        cfg_iface_ = cfg_iface;
+    /// This function returns a const pointer to the interface
+    /// configuration.
+    ///
+    /// @return Object representing configuration of interfaces.
+    ConstCfgIfacePtr getCfgIface() const {
+        return (cfg_iface_);
     }
     }
 
 
     /// @brief Return pointer to non-const object representing user-defined
     /// @brief Return pointer to non-const object representing user-defined
@@ -340,7 +343,7 @@ private:
     ///
     ///
     /// Used to select interfaces on which the DHCP server will listen to
     /// Used to select interfaces on which the DHCP server will listen to
     /// queries.
     /// queries.
-    CfgIface cfg_iface_;
+    CfgIfacePtr cfg_iface_;
 
 
     /// @brief Pointer to option definitions configuration.
     /// @brief Pointer to option definitions configuration.
     ///
     ///

+ 0 - 2
src/lib/dhcpsrv/tests/cfg_iface_unittest.cc

@@ -377,8 +377,6 @@ TEST(CfgIfaceNoStubTest, useSocketType) {
     ASSERT_TRUE(IfaceMgr::instance().isDirectResponseSupported());
     ASSERT_TRUE(IfaceMgr::instance().isDirectResponseSupported());
 
 
     // Test invalid values.
     // Test invalid values.
-    EXPECT_THROW(cfg.useSocketType(AF_INET, CfgIface::SOCKET_DEFAULT),
-        InvalidSocketType);
     EXPECT_THROW(cfg.useSocketType(AF_INET, "default"),
     EXPECT_THROW(cfg.useSocketType(AF_INET, "default"),
         InvalidSocketType);
         InvalidSocketType);
     EXPECT_THROW(cfg.useSocketType(AF_INET6, "datagram"),
     EXPECT_THROW(cfg.useSocketType(AF_INET6, "datagram"),

+ 5 - 5
src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc

@@ -70,14 +70,14 @@ TEST_F(IfacesConfigParserTest, interfaces) {
     // Open sockets according to the parsed configuration.
     // Open sockets according to the parsed configuration.
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     ASSERT_TRUE(cfg);
     ASSERT_TRUE(cfg);
-    ASSERT_NO_THROW(cfg->getCfgIface().openSockets(AF_INET, 10000));
+    ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
 
 
     // Only eth0 should have an open socket.
     // Only eth0 should have an open socket.
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
     EXPECT_FALSE(test_config.socketOpen("eth1", AF_INET));
     EXPECT_FALSE(test_config.socketOpen("eth1", AF_INET));
 
 
     // Reset configuration.
     // Reset configuration.
-    cfg->getCfgIface().closeSockets();
+    cfg->getCfgIface()->closeSockets();
     CfgMgr::instance().clear();
     CfgMgr::instance().clear();
 
 
     // Try similar configuration but this time add a wildcard interface
     // Try similar configuration but this time add a wildcard interface
@@ -88,7 +88,7 @@ TEST_F(IfacesConfigParserTest, interfaces) {
     ASSERT_NO_THROW(parser.build(config_element));
     ASSERT_NO_THROW(parser.build(config_element));
 
 
     cfg = CfgMgr::instance().getStagingCfg();
     cfg = CfgMgr::instance().getStagingCfg();
-    ASSERT_NO_THROW(cfg->getCfgIface().openSockets(AF_INET, 10000));
+    ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
 
 
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
     EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
     EXPECT_TRUE(test_config.socketOpen("eth1", AF_INET));
     EXPECT_TRUE(test_config.socketOpen("eth1", AF_INET));
@@ -116,7 +116,7 @@ TEST_F(IfacesConfigParserTest, socketTypeRaw) {
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     ASSERT_TRUE(cfg);
     ASSERT_TRUE(cfg);
     cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_RAW);
     cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_RAW);
-    EXPECT_TRUE(cfg->getCfgIface() == cfg_ref);
+    EXPECT_TRUE(*cfg->getCfgIface() == cfg_ref);
 }
 }
 
 
 // This test verifies that it is possible to select the datagram socket
 // This test verifies that it is possible to select the datagram socket
@@ -141,7 +141,7 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
     ASSERT_TRUE(cfg);
     ASSERT_TRUE(cfg);
     cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_DGRAM);
     cfg_ref.useSocketType(AF_INET, CfgIface::SOCKET_DGRAM);
-    EXPECT_TRUE(cfg->getCfgIface() == cfg_ref);
+    EXPECT_TRUE(*cfg->getCfgIface() == cfg_ref);
 }
 }
 
 
 // Test that the configuration rejects the invalid socket type.
 // Test that the configuration rejects the invalid socket type.

+ 1 - 1
src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc

@@ -94,7 +94,7 @@ public:
     ///
     ///
     template<typename LeaseObjectType, typename LeaseFileType,
     template<typename LeaseObjectType, typename LeaseFileType,
              typename StorageType>
              typename StorageType>
-    void writeLeases(LeaseFileType lease_file,
+    void writeLeases(LeaseFileType& lease_file,
                      const StorageType& storage,
                      const StorageType& storage,
                      const std::string& compare) {
                      const std::string& compare) {
         // Prepare for a new file, close and remove the old
         // Prepare for a new file, close and remove the old

+ 4 - 12
src/lib/dhcpsrv/tests/srv_config_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -254,11 +254,8 @@ TEST_F(SrvConfigTest, copy) {
     info.destinations_.push_back(LoggingDestination());
     info.destinations_.push_back(LoggingDestination());
 
 
     // Set interface configuration for conf1.
     // Set interface configuration for conf1.
-    CfgIface cfg_iface;
-    cfg_iface.use(AF_INET, "eth0");
-
+    conf1.getCfgIface()->use(AF_INET, "eth0");
     conf1.addLoggingInfo(info);
     conf1.addLoggingInfo(info);
-    conf1.setCfgIface(cfg_iface);
 
 
     // Add option definition.
     // Add option definition.
     OptionDefinitionPtr def(new OptionDefinition("option-foo", 5, "string"));
     OptionDefinitionPtr def(new OptionDefinition("option-foo", 5, "string"));
@@ -310,17 +307,12 @@ TEST_F(SrvConfigTest, equality) {
     EXPECT_FALSE(conf1 != conf2);
     EXPECT_FALSE(conf1 != conf2);
 
 
     // Differ by interface configuration.
     // Differ by interface configuration.
-    CfgIface cfg_iface1;
-    CfgIface cfg_iface2;
-
-    cfg_iface1.use(AF_INET, "eth0");
-    conf1.setCfgIface(cfg_iface1);
+    conf1.getCfgIface()->use(AF_INET, "eth0");
 
 
     EXPECT_FALSE(conf1 == conf2);
     EXPECT_FALSE(conf1 == conf2);
     EXPECT_TRUE(conf1 != conf2);
     EXPECT_TRUE(conf1 != conf2);
 
 
-    cfg_iface2.use(AF_INET, "eth0");
-    conf2.setCfgIface(cfg_iface2);
+    conf2.getCfgIface()->use(AF_INET, "eth0");
 
 
     EXPECT_TRUE(conf1 == conf2);
     EXPECT_TRUE(conf1 == conf2);
     EXPECT_FALSE(conf1 != conf2);
     EXPECT_FALSE(conf1 != conf2);