ControlledDhcpv4Srv::commandInterfaceListHandler(const std::string&,
ConstElementPtr) {
ElementPtr ifaces = Element::createMap();
+ bool error = false;
std::string message;
try {
ifaces->set("interfaces", IfaceMgr::instance().ifacesToElement());
- } catch (std::exception& ex) {
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
msg << IfaceMgr::instance().getIfaces().size()
<< " interfaces detected.";
return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS, msg.str(), ifaces));
ConstElementPtr
ControlledDhcpv4Srv::commandInterfaceRedetectHandler(const std::string&,
ConstElementPtr args) {
+ bool error = false;
std::string message;
try {
IfaceMgr::instance().detectIfaces(true);
- } catch (std::exception& ex) {
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
return (ControlledDhcpv4Srv::commandInterfaceListHandler("", args));
} else {
msg << "Unexpected error while retrieving the list of detected interfaces: " << message;
ConstElementPtr
ControlledDhcpv4Srv::commandInterfaceUseHandler(const std::string&,
ConstElementPtr args) {
+ bool error = false;
string message;
ConstElementPtr ifaces_config;
if (!args) {
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, message));
}
try {
- ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(args);
- mutable_cfg->set("re-detect", Element::create(false));
+ CfgIfacePtr running_cfg_iface = CfgMgr::instance().getCurrentCfg()->getCfgIface();
+ ElementPtr mutable_running_cfg = running_cfg_iface->toElement();
+ merge(mutable_running_cfg, args);
IfacesConfigParser parser(AF_INET, true);
CfgIfacePtr cfg_iface(new CfgIface());
- parser.parse(cfg_iface, args);
- CfgIfacePtr running_cfg_iface = CfgMgr::instance().getCurrentCfg()->getCfgIface();
- if (running_cfg_iface->merge(*cfg_iface, AF_INET)) {
- running_cfg_iface->triggerOpenSocketsWithRetry(AF_INET, getServerPort(), useBroadcast());
- }
- } catch (std::exception& ex) {
+ parser.parseInterfacesList(cfg_iface, mutable_running_cfg->get("interfaces"));
+ CfgMgr::instance().getCurrentCfg()->getCfgIface()->update(*cfg_iface);
+ running_cfg_iface->triggerOpenSocketsWithRetry(AF_INET, getServerPort(), useBroadcast());
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful."));
} else {
msg << "Unexpected error while updating used interfaces: " << message;
#include <dhcp/dhcp4.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
+#include <dhcp/testutils/pkt_filter_test_stub.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/lease.h>
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
#include <dhcp/dhcp4.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
+#include <dhcp/testutils/pkt_filter_test_stub.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/lease.h>
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
std::string command = "{ \"command\": \"interface-list\" }";
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilterPtr filter(new PktFilterTestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
ControlledDhcpv6Srv::commandInterfaceListHandler(const std::string&,
ConstElementPtr) {
ElementPtr ifaces = Element::createMap();
+ bool error = false;
std::string message;
try {
ifaces->set("interfaces", IfaceMgr::instance().ifacesToElement());
- } catch (std::exception& ex) {
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
msg << IfaceMgr::instance().getIfaces().size()
<< " interfaces detected.";
return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS, msg.str(), ifaces));
ConstElementPtr
ControlledDhcpv6Srv::commandInterfaceRedetectHandler(const std::string&,
ConstElementPtr args) {
+ bool error = false;
std::string message;
try {
IfaceMgr::instance().detectIfaces(true);
- } catch (std::exception& ex) {
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
return (ControlledDhcpv6Srv::commandInterfaceListHandler("", args));
} else {
msg << "Unexpected error while retrieving the list of detected interfaces: " << message;
ConstElementPtr
ControlledDhcpv6Srv::commandInterfaceUseHandler(const std::string&,
ConstElementPtr args) {
+ bool error = false;
string message;
ConstElementPtr ifaces_config;
if (!args) {
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, message));
}
try {
- ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(args);
- mutable_cfg->set("re-detect", Element::create(false));
+ CfgIfacePtr running_cfg_iface = CfgMgr::instance().getCurrentCfg()->getCfgIface();
+ ElementPtr mutable_running_cfg = running_cfg_iface->toElement();
+ merge(mutable_running_cfg, args);
IfacesConfigParser parser(AF_INET6, true);
CfgIfacePtr cfg_iface(new CfgIface());
- parser.parse(cfg_iface, args);
- CfgIfacePtr running_cfg_iface = CfgMgr::instance().getCurrentCfg()->getCfgIface();
- if (running_cfg_iface->merge(*cfg_iface, AF_INET6)) {
- running_cfg_iface->triggerOpenSocketsWithRetry(AF_INET6, getServerPort());
- }
- } catch (std::exception& ex) {
+ parser.parseInterfacesList(cfg_iface, mutable_running_cfg->get("interfaces"));
+ CfgMgr::instance().getCurrentCfg()->getCfgIface()->update(*cfg_iface);
+ running_cfg_iface->triggerOpenSocketsWithRetry(AF_INET6, getServerPort());
+ } catch (const std::exception& ex) {
+ error = true;
message = ex.what();
} catch (...) {
+ error = true;
message = "unknown error";
}
ostringstream msg;
- if (message.empty()) {
+ if (!error) {
return (isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful."));
} else {
msg << "Unexpected error while updating used interfaces: " << message;
#include <config/unix_command_mgr.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
+#include <dhcp/testutils/pkt_filter6_test_stub.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/lease.h>
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createUnixChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
SKIP_IF(skipped_);
std::string response;
#include <database/database_connection.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
+#include <dhcp/testutils/pkt_filter6_test_stub.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/lease.h>
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
std::string command = "{ \"command\": \"interface-list\" }";
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
createHttpChannelServer();
+ PktFilter6Ptr filter(new PktFilter6TestStub());
+ IfaceMgr::instance().setPacketFilter(filter);
std::string response;
std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
<< "' has already been specified");
}
- // Log that we're listening on the specific interface and that the
- // address is not explicitly specified.
LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_ADD_IFACE).arg(name);
iface_set_.insert(name);
}
}
-bool
-CfgIface::merge(const CfgIface& other, const uint16_t family) {
- bool updated = false;
- if (other.wildcard_used_) {
- wildcard_used_ = true;
- updated = true;
- } else {
- // Use a copy of the containers so that no change is applied until everything is checked.
- auto address_map = address_map_;
- auto iface_set = iface_set_;
- for (auto const& addr_key : other.address_map_) {
- // For the IPv4, if the interface name was specified (instead of the interface-
- // address tuple) all addresses are already activated. Adding an explicit address
- // for the interface should result in error.
- if ((family == AF_INET) && (iface_set.find(addr_key.first) != iface_set.end())) {
- isc_throw(DuplicateIfaceName, "interface '" << addr_key.first
- << "' has already been selected");
- }
- // Check if the address hasn't been selected already.
- std::pair<const std::string, IOAddress> iface_address_tuple(addr_key.first, addr_key.second);
- if (std::find(address_map.begin(), address_map.end(),
- iface_address_tuple) != address_map.end()) {
- isc_throw(DuplicateAddress, "must not select address '"
- << addr_key.second << "' for interface '" << addr_key.first << "' "
- "because this address is already selected");
- }
- address_map.insert(addr_key);
- }
- for (auto const& name : other.iface_set_) {
- if ((name != ALL_IFACES_KEYWORD)) {
- // An interface has been selected or an IPv4 address on this interface
- // has been selected it is not allowed to select the whole interface.
- if ((iface_set.find(name) != iface_set.end()) ||
- ((family == AF_INET) && address_map.count(name) > 0)) {
- isc_throw(DuplicateIfaceName, "interface '" << name
- << "' has already been specified");
- }
- iface_set.insert(name);
- }
- }
- // Ready to apply the changes.
- for (auto const& addr_key : other.address_map_) {
- address_map_.insert(addr_key);
- updated = true;
- }
- for (auto const& name : other.iface_set_) {
- if ((name != ALL_IFACES_KEYWORD)) {
- // Log that we're listening on the specific interface and that the
- // address is not explicitly specified.
- LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE).arg(name);
- iface_set_.insert(name);
- updated = true;
- }
- }
- }
-
- return (updated);
-}
-
void
CfgIface::useSocketType(const uint16_t family,
const SocketType& socket_type) {
return (result);
}
+void
+CfgIface::update(CfgIface& other) {
+ iface_set_ = other.iface_set_;
+ address_map_ = other.address_map_;
+ wildcard_used_ = other.wildcard_used_;
+}
+
} // end of isc::dhcp namespace
} // end of isc namespace
/// @c CfgIface::use has been already called for this interface.
void use(const uint16_t family, const std::string& iface_name);
- /// @brief Merge the interface list and address list.
+ /// @brief Update runtime mutable members.
///
- /// @param other The object from which the lists are updated.
- /// @param family Address family (AF_INET or AF_INET6).
+ /// @note Currently supported members are @ref iface_set_,
+ /// @ref address_map_ and @ref wildcard_used_.
///
- /// @return true if any change has been done, false otherwise.
- bool merge(const CfgIface& other, const uint16_t family);
+ /// @param other The other object to update members from.
+ void update(CfgIface& other);
/// @brief Sets the specified socket type to be used by the server.
///
namespace dhcp {
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE = "DHCPSRV_CFGMGR_ADD_IFACE";
-extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE = "DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE";
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET4 = "DHCPSRV_CFGMGR_ADD_SUBNET4";
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET6 = "DHCPSRV_CFGMGR_ADD_SUBNET6";
extern const isc::log::MessageID DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE = "DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE";
const char* values[] = {
"DHCPSRV_CFGMGR_ADD_IFACE", "listening on interface %1",
- "DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE", "listening on interface %1",
"DHCPSRV_CFGMGR_ADD_SUBNET4", "adding subnet %1",
"DHCPSRV_CFGMGR_ADD_SUBNET6", "adding subnet %1",
"DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE", "enabling listening on all interfaces",
namespace dhcp {
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE;
-extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE;
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET4;
extern const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET6;
extern const isc::log::MessageID DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE;
An info message issued when a new interface is being added to the collection of
interfaces on which the server listens to DHCP messages.
-% DHCPSRV_CFGMGR_ADD_IFACE_ON_MERGE listening on interface %1
-An info message issued when a new interface is being added to the collection of
-interfaces on which the server listens to DHCP messages.
-
% DHCPSRV_CFGMGR_ADD_SUBNET4 adding subnet %1
Logged at debug log level 40.
A debug message reported when the DHCP configuration manager is adding the
/// are invalid.
void parse(const CfgIfacePtr& config, const isc::data::ConstElementPtr& values);
-private:
/// @brief parses interfaces-list structure
///
/// This method goes through all the interfaces-specified in
void parseInterfacesList(const CfgIfacePtr& cfg_iface,
isc::data::ConstElementPtr ifaces_list);
+private:
+
/// @brief AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
int protocol_;
#include <dhcp/testutils/pkt_filter_test_stub.h>
#include <dhcp/testutils/pkt_filter6_test_stub.h>
#include <dhcpsrv/cfg_iface.h>
-#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <asiolink/io_service.h>
#include <asiolink/asio_wrapper.h>
#include <asiolink/interval_timer.h>
EXPECT_EQ(second_port_calls, 2);
}
-// Test that merge CfgIface works properly.
-TEST_F(CfgIfaceTest, mergeV4CfgIface) {
- CfgIfacePtr left(new CfgIface());
- CfgIfacePtr right(new CfgIface());
- std::string left_txt("{ \"interfaces\": [\"eth0\", \"eth1/192.0.2.3\"], \"re-detect\": false }");
- std::string right_txt("{ \"interfaces\": [\"eth0/10.0.0.1\", \"eth1961\"], \"re-detect\": false }");
- ConstElementPtr left_cfg = Element::fromJSON(left_txt);
- ConstElementPtr right_cfg = Element::fromJSON(right_txt);
- IfacesConfigParser parser(AF_INET, true);
- EXPECT_NO_THROW(parser.parse(left, left_cfg));
- auto lift_before = left->toElement()->str();
- EXPECT_NO_THROW(parser.parse(right, right_cfg));
- auto right_before = right->toElement()->str();
- EXPECT_THROW(left->merge(*right, AF_INET), DuplicateIfaceName);
- EXPECT_EQ(lift_before, left->toElement()->str());
- EXPECT_THROW(right->merge(*left, AF_INET), DuplicateIfaceName);
- EXPECT_EQ(right_before, right->toElement()->str());
-}
-
-// Test that merge CfgIface works properly.
-TEST_F(CfgIfaceTest, mergeV6CfgIface) {
- CfgIfacePtr left(new CfgIface());
- CfgIfacePtr right(new CfgIface());
- std::string left_txt("{ \"interfaces\": [\"eth0/2001:db8:1::1\", \"eth1\"], \"re-detect\": false }");
- std::string right_txt("{ \"interfaces\": [\"eth0/2001:db8:1::1\", \"eth1961\"], \"re-detect\": false }");
- ConstElementPtr left_cfg = Element::fromJSON(left_txt);
- ConstElementPtr right_cfg = Element::fromJSON(right_txt);
- IfacesConfigParser parser(AF_INET6, true);
- EXPECT_NO_THROW(parser.parse(left, left_cfg));
- auto lift_before = left->toElement()->str();
- EXPECT_NO_THROW(parser.parse(right, right_cfg));
- auto right_before = right->toElement()->str();
- EXPECT_THROW(left->merge(*right, AF_INET6), DuplicateAddress);
- EXPECT_EQ(lift_before, left->toElement()->str());
- EXPECT_THROW(right->merge(*left, AF_INET6), DuplicateAddress);
- EXPECT_EQ(right_before, right->toElement()->str());
-}
-
// This test verifies that it is possible to specify the socket
// type to be used by the DHCPv4 server.
// This test is enabled on LINUX and BSD only, because the
{
"access": "read",
- "avail": "3.1.8",
+ "avail": "3.1.9",
"brief": [
"This command retrieves the list of detected interfaces.",
"This command does not take any parameters."
{
"access": "write",
- "avail": "3.1.8",
+ "avail": "3.1.9",
"brief": [
"This command retrieves the list of detected interfaces after performing",
"a re-detect procedure.",
{
"access": "write",
- "avail": "3.1.8",
+ "avail": "3.1.9",
"brief": [
"This command updates the list of interfaces used to process DHCP traffic.",
"This command takes as parameter the list of interfaces with respective",