Browse Source

[3512] Bare bones implementation of the iface selecting class.

Marcin Siodelski 10 years ago
parent
commit
d40f97625e

+ 1 - 0
src/lib/dhcpsrv/Makefile.am

@@ -55,6 +55,7 @@ libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
 libkea_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
 libkea_dhcpsrv_la_SOURCES += dhcp_config_parser.h
 libkea_dhcpsrv_la_SOURCES += dhcp_parsers.cc dhcp_parsers.h
+libkea_dhcpsrv_la_SOURCES += iface_cfg.cc iface_cfg.h
 libkea_dhcpsrv_la_SOURCES += key_from_key.h
 libkea_dhcpsrv_la_SOURCES += lease.cc lease.h
 libkea_dhcpsrv_la_SOURCES += lease_mgr.cc lease_mgr.h

+ 110 - 0
src/lib/dhcpsrv/iface_cfg.cc

@@ -0,0 +1,110 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <dhcp/iface_mgr.h>
+#include <dhcpsrv/iface_cfg.h>
+#include <util/strutil.h>
+
+namespace isc {
+namespace dhcp {
+
+const char* IfaceCfg::ALL_IFACES_KEYWORD = "*";
+
+IfaceCfg::IfaceCfg(Family family)
+    : family_(family),
+      wildcard_used_(false) {
+}
+
+void
+IfaceCfg::closeSockets() {
+    IfaceMgr::instance().closeSockets();
+}
+
+void
+IfaceCfg::openSockets(const uint16_t /* port */) {
+    if (!wildcard_used_) {
+        setState(true);
+        for (IfaceSet::const_iterator iface_name = iface_set_.begin();
+             iface_name != iface_set_.end(); ++iface_name) {
+            Iface* iface = IfaceMgr::instance().getIface(*iface_name);
+            if (iface == NULL) {
+                isc_throw(Unexpected,
+                          "fail to open socket on interface '"
+                          << *iface_name << "' as this interface doesn't"
+                          " exist");
+
+            } else if (getFamily() == V4) {
+                iface->inactive4_ = false;
+
+            } else {
+                iface->inactive6_ = false;
+            }
+        }
+
+    } else {
+        setState(false);
+    }
+
+    // @todo open sockets here.
+
+}
+
+void
+IfaceCfg::setState(const bool inactive) {
+    const IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
+    for (IfaceCollection::iterator iface = ifaces.begin();
+         iface != ifaces.end(); ++iface) {
+        if (getFamily() == V4) {
+            (*iface)->inactive4_ = inactive;
+        } else {
+            (*iface)->inactive6_ = inactive;
+        }
+    }
+}
+
+void
+IfaceCfg::use(const std::string& iface_name) {
+    // In theory the configuration parser should strip extraneous spaces but
+    // since this is a common library it may be better to make sure that it
+    // is really the case.
+    std::string name = util::str::trim(iface_name);
+    if (name.empty()) {
+        isc_throw(InvalidIfaceName,
+                  "empty interface name used in configuration");
+    }
+
+    if (name != ALL_IFACES_KEYWORD) {
+        if (IfaceMgr::instance().getIface(name) == NULL) {
+            isc_throw(NoSuchIface, "interface '" << name
+                      << "' doesn't exist in the system");
+        }
+
+        std::pair<IfaceSet::iterator, bool> res = iface_set_.insert(name);
+        if (!res.second) {
+            isc_throw(DuplicateIfaceName, "interface '" << name
+                      << "' has already been specified");
+        }
+
+    } else if (wildcard_used_) {
+        isc_throw(DuplicateIfaceName, "the wildcard interface '"
+                  << ALL_IFACES_KEYWORD << "' can only be specified once");
+
+    } else {
+        wildcard_used_ = true;
+
+    }
+}
+
+} // end of isc::dhcp namespace
+} // end of isc namespace

+ 77 - 0
src/lib/dhcpsrv/iface_cfg.h

@@ -0,0 +1,77 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef IFACE_CFG_H
+#define IFACE_CFG_H
+
+#include <set>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Exception thrown when duplicated interface names specified.
+class DuplicateIfaceName : public Exception {
+public:
+    DuplicateIfaceName(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when specified interface name is invalid.
+class InvalidIfaceName : public Exception {
+public:
+    InvalidIfaceName(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception thrown when specified interface doesn't exist in a system.
+class NoSuchIface : public Exception {
+public:
+    NoSuchIface(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
+class IfaceCfg {
+public:
+    static const char* ALL_IFACES_KEYWORD;
+
+    enum Family {
+        V4, V6
+    };
+
+    IfaceCfg(Family family);
+
+    void closeSockets();
+
+    Family getFamily() const {
+        return (family_);
+    }
+
+    void openSockets(const uint16_t port);
+
+    void use(const std::string& iface_name);
+
+private:
+
+    void setState(const bool inactive);
+
+    Family family_;
+    typedef std::set<std::string> IfaceSet;
+    IfaceSet iface_set_;
+    bool wildcard_used_;
+};
+
+}
+}
+
+#endif // IFACE_CFG_H

+ 1 - 0
src/lib/dhcpsrv/tests/Makefile.am

@@ -63,6 +63,7 @@ libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
 libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
 libdhcpsrv_unittests_SOURCES += daemon_unittest.cc
 libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
+libdhcpsrv_unittests_SOURCES += iface_cfg_unittest.cc
 libdhcpsrv_unittests_SOURCES += lease_file_io.cc lease_file_io.h
 libdhcpsrv_unittests_SOURCES += lease_unittest.cc
 libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc

+ 49 - 0
src/lib/dhcpsrv/tests/iface_cfg_unittest.cc

@@ -0,0 +1,49 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <dhcp/tests/iface_mgr_test_config.h>
+#include <dhcpsrv/iface_cfg.h>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::dhcp::test;
+
+namespace {
+
+/// @brief Test fixture class for testing the @c IfaceCfg class.
+class IfaceCfgTest : public ::testing::Test {
+public:
+
+    /// @brief Constructor.
+    ///
+    /// By initializing the @c IfaceMgrTestConfig object it creates a set of
+    /// fake interfaces: lo, eth0, eth1.
+    IfaceCfgTest() :
+        iface_mgr_test_config_(true) {
+    }
+
+    /// @brief Holds a fake configuration of the interfaces.
+    IfaceMgrTestConfig iface_mgr_test_config_;
+
+};
+
+TEST_F(IfaceCfgTest, explicitNames) {
+    IfaceCfg cfg;
+    ASSERT_NO_THROW(cfg.use("eth0"));
+    ASSERT_NO_THROW(cfg.use("eth1"));
+}
+
+} // end of anonymous namespace