Commit 4ecee3c0 authored by Marcin Siodelski's avatar Marcin Siodelski

[master] Merge branch 'trac3534'

Conflicts:
	src/lib/dhcpsrv/tests/daemon_unittest.cc
parents a3bcf292 1bab6f8b
......@@ -1391,7 +1391,6 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/bin/dhcp6/tests/test_data_files_config.h
src/bin/dhcp6/tests/test_libraries.h
src/bin/keactrl/Makefile
src/bin/keactrl/kea.conf
src/bin/keactrl/keactrl
src/bin/keactrl/keactrl.conf
src/bin/keactrl/tests/Makefile
......
......@@ -18,7 +18,7 @@
#include <d2/d_controller.h>
#include <exceptions/exceptions.h>
#include <log/logger_support.h>
#include <dhcpsrv/configuration.h>
#include <dhcpsrv/cfgmgr.h>
#include <sstream>
#include <unistd.h>
......@@ -59,6 +59,16 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
throw; // rethrow it
}
// It is important that we set a default logger name because this name
// will be used when the user doesn't provide the logging configuration
// in the Kea configuration file.
isc::dhcp::CfgMgr::instance().setDefaultLoggerName(bin_name_);
// Logger's default configuration depends on whether we are in the
// verbose mode or not. CfgMgr manages the logger configuration so
// the verbose mode is set for CfgMgr.
isc::dhcp::CfgMgr::instance().setVerbose(verbose_);
// Do not initialize logger here if we are running unit tests. It would
// replace an instance of unit test specific logger.
if (!test_mode) {
......@@ -218,8 +228,13 @@ DControllerBase::initProcess() {
isc::data::ConstElementPtr
DControllerBase::configFromFile() {
// Rollback any previous staging configuration. For D2, only a
// logger configuration is used here.
isc::dhcp::CfgMgr::instance().rollback();
// Will hold configuration.
isc::data::ConstElementPtr module_config;
// Will receive configuration result.
isc::data::ConstElementPtr answer;
try {
std::string config_file = getConfigFile();
if (config_file.empty()) {
......@@ -236,11 +251,12 @@ DControllerBase::configFromFile() {
// so we can log things during configuration process.
// Temporary storage for logging configuration
isc::dhcp::ConfigurationPtr storage(new isc::dhcp::Configuration());
isc::dhcp::SrvConfigPtr storage =
isc::dhcp::CfgMgr::instance().getStagingCfg();
// Get 'Logging' element from the config and use it to set up
// logging. If there's no such element, we'll just pass NULL.
Daemon::configureLogger(whole_config->get("Logging"), storage, verbose_);
Daemon::configureLogger(whole_config->get("Logging"), storage);
// Extract derivation-specific portion of the configuration.
module_config = whole_config->get(getAppName());
......@@ -249,7 +265,20 @@ DControllerBase::configFromFile() {
" does not include '" <<
getAppName() << "' entry.");
}
answer = updateConfig(module_config);
int rcode = 0;
isc::config::parseAnswer(rcode, answer);
if (!rcode) {
// Configuration successful, so apply the logging configuration
// to log4cplus.
isc::dhcp::CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
isc::dhcp::CfgMgr::instance().commit();
}
} catch (const std::exception& ex) {
// Rollback logging configuration.
isc::dhcp::CfgMgr::instance().rollback();
// build an error result
isc::data::ConstElementPtr error =
isc::config::createAnswer(1,
......@@ -257,7 +286,7 @@ DControllerBase::configFromFile() {
return (error);
}
return (updateConfig(module_config));
return (answer);
}
......
......@@ -177,7 +177,7 @@ void ControlledDhcpv4Srv::init(const std::string& config_file) {
// Configuration may disable or enable interfaces so we have to
// reopen sockets according to new configuration.
CfgMgr::instance().getConfiguration()->cfg_iface_
CfgMgr::instance().getCurrentCfg()->cfg_iface_
.openSockets(getPort(), useBroadcast());
} catch (const std::exception& ex) {
......
......@@ -145,18 +145,16 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
}
// Configuration may change active interfaces. Therefore, we have to reopen
// sockets according to new configuration. This operation is not exception
// safe and we really don't want to emit exceptions to whoever called this
// method. Instead, catch an exception and create appropriate answer.
try {
CfgMgr::instance().getConfiguration()->cfg_iface_
.openSockets(srv->getPort(), getInstance()->useBroadcast());
// sockets according to new configuration. It is possible that this
// operation will fail for some interfaces but the openSockets function
// guards against exceptions and invokes a callback function to
// 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
// of the interfaces.
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET, srv->getPort(),
getInstance()->useBroadcast());
} catch (std::exception& ex) {
err << "failed to open sockets after server reconfiguration: "
<< ex.what();
answer = isc::config::createAnswer(1, err.str());
}
return (answer);
}
......@@ -176,7 +174,7 @@ void ControlledDhcpv4Srv::shutdown() {
ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
cleanup();
server_ = NULL; // forget this instance. Noone should call any handlers at
// this stage.
}
......
......@@ -443,7 +443,7 @@ namespace dhcp {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
} else if (config_id.compare("interfaces") == 0) {
parser = new InterfaceListConfigParser(config_id);
parser = new InterfaceListConfigParser(config_id, globalContext());
} else if (config_id.compare("subnet4") == 0) {
parser = new Subnets4ListConfigParser(config_id);
} else if (config_id.compare("option-data") == 0) {
......@@ -619,9 +619,8 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
subnet_parser->commit();
}
if (iface_parser) {
iface_parser->commit();
}
// No need to commit interface names as this is handled by the
// CfgMgr::commit() function.
// Apply global options
commitGlobalOptions();
......@@ -653,8 +652,8 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
}
LOG_INFO(dhcp4_logger, DHCP4_CONFIG_COMPLETE)
.arg(CfgMgr::instance().getConfiguration()->
getConfigSummary(Configuration::CFGSEL_ALL4));
.arg(CfgMgr::instance().getCurrentCfg()->
getConfigSummary(SrvConfig::CFGSEL_ALL4));
// Everything was fine. Configuration is successful.
answer = isc::config::createAnswer(0, "Configuration successful.");
......
......@@ -41,6 +41,11 @@ void configure(const std::string& file_name) {
// This is a configuration backend implementation that reads the
// configuration from a JSON file.
// We are starting the configuration process so we should remove any
// staging configuration that has been created during previous
// configuration attempts.
CfgMgr::instance().rollback();
isc::data::ConstElementPtr json;
isc::data::ConstElementPtr dhcp4;
isc::data::ConstElementPtr logger;
......@@ -60,14 +65,10 @@ void configure(const std::string& file_name) {
isc_throw(isc::BadValue, "no configuration found");
}
// Let's configure logging before applying the configuration,
// so we can log things during configuration process.
// If there's no logging element, we'll just pass NULL pointer,
// which will be handled by configureLogger().
Daemon::configureLogger(json->get("Logging"),
CfgMgr::instance().getConfiguration(),
ControlledDhcpv4Srv::getInstance()->getVerbose());
CfgMgr::instance().getStagingCfg());
// Get Dhcp4 component from the config
dhcp4 = json->get("Dhcp4");
......@@ -97,7 +98,19 @@ void configure(const std::string& file_name) {
isc_throw(isc::BadValue, reason);
}
// If configuration was parsed successfully, apply the new logger
// configuration to log4cplus. It is done before commit in case
// something goes wrong.
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
// Use new configuration.
CfgMgr::instance().commit();
} catch (const std::exception& ex) {
// If configuration failed at any stage, we drop the staging
// configuration and continue to use the previous one.
CfgMgr::instance().rollback();
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL)
.arg(file_name).arg(ex.what());
isc_throw(isc::BadValue, "configuration error using file '"
......
......@@ -16,6 +16,7 @@
#include <dhcp4/ctrl_dhcp4_srv.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcpsrv/cfgmgr.h>
#include <log/logger_support.h>
#include <log/logger_manager.h>
......@@ -122,6 +123,11 @@ main(int argc, char* argv[]) {
int ret = EXIT_SUCCESS;
try {
// It is important that we set a default logger name because this name
// will be used when the user doesn't provide the logging configuration
// in the Kea configuration file.
CfgMgr::instance().setDefaultLoggerName(DHCP4_LOGGER_NAME);
// Initialize logging. If verbose, we'll use maximum verbosity.
Daemon::loggerInit(DHCP4_LOGGER_NAME, verbose_mode);
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO)
......
......@@ -2917,7 +2917,8 @@ TEST_F(Dhcp4ParserTest, selectedInterfaces) {
ASSERT_TRUE(status);
checkResult(status, 0);
CfgMgr::instance().getConfiguration()->cfg_iface_.openSockets(10000);
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET, 10000);
// eth0 and eth1 were explicitly selected. eth2 was not.
EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET));
......@@ -2952,7 +2953,8 @@ TEST_F(Dhcp4ParserTest, allInterfaces) {
ASSERT_TRUE(status);
checkResult(status, 0);
CfgMgr::instance().getConfiguration()->cfg_iface_.openSockets(10000);
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET, 10000);
// All interfaces should be now active.
ASSERT_TRUE(test_config.socketOpen("eth0", AF_INET));
......
......@@ -45,7 +45,7 @@ Dhcpv4SrvTest::Dhcpv4SrvTest()
pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"), IOAddress("192.0.2.110")));
subnet_->addPool(pool_);
CfgMgr::instance().getConfiguration()->cfg_iface_.reset();
CfgMgr::instance().clear();
CfgMgr::instance().deleteSubnets4();
CfgMgr::instance().addSubnet4(subnet_);
......@@ -58,7 +58,7 @@ Dhcpv4SrvTest::Dhcpv4SrvTest()
Dhcpv4SrvTest::~Dhcpv4SrvTest() {
// Make sure that we revert to default value
CfgMgr::instance().getConfiguration()->cfg_iface_.reset();
CfgMgr::instance().clear();
CfgMgr::instance().echoClientId(true);
}
......
......@@ -140,19 +140,14 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
}
// Configuration may change active interfaces. Therefore, we have to reopen
// sockets according to new configuration. This operation is not exception
// safe and we really don't want to emit exceptions to the callback caller.
// Instead, catch an exception and create appropriate answer.
try {
CfgMgr::instance().getConfiguration()->cfg_iface_
.openSockets(srv->getPort());
} catch (const std::exception& ex) {
std::ostringstream err;
err << "failed to open sockets after server reconfiguration: "
<< ex.what();
answer = isc::config::createAnswer(1, err.str());
}
// sockets according to new configuration. It is possible that this
// operation will fail for some interfaces but the openSockets function
// guards against exceptions and invokes a callback function to
// 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
// of the interfaces.
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET6, srv->getPort());
return (answer);
}
......
......@@ -55,6 +55,12 @@ following section applies only to the Bundy backend.
build, the configuration is then applied ("committed") and commit() method is
called.
\note With the implementation of the Kea ticket #3534 we're moving away from
the concept of commit being called for individual parsers. When this ticket
and a couple of followup tickets are implemented, the commit will be a
single operation executed for the whole configuration received from many
parsers.
All parsers are defined in src/bin/dhcp6/config_parser.cc file. Some of them
are generic (e.g. Uint32Parser that is able to handle any
unsigned 32 bit integer), but some are very specialized (e.g.
......
......@@ -150,12 +150,6 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
// Instantiate allocation engine
alloc_engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100));
// We have to point out to the CfgMgr that the we are in the IPv6
// domain, so as the IPv6 sockets are opened rather than IPv4 sockets
// which are the default.
CfgMgr::instance().getConfiguration()
->cfg_iface_.setFamily(CfgIface::V6);
/// @todo call loadLibraries() when handling configuration changes
} catch (const std::exception &e) {
......
......@@ -662,7 +662,7 @@ namespace dhcp {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
} else if (config_id.compare("interfaces") == 0) {
parser = new InterfaceListConfigParser(config_id);
parser = new InterfaceListConfigParser(config_id, globalContext());
} else if (config_id.compare("subnet6") == 0) {
parser = new Subnets6ListConfigParser(config_id);
} else if (config_id.compare("option-data") == 0) {
......@@ -821,9 +821,8 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
subnet_parser->commit();
}
if (iface_parser) {
iface_parser->commit();
}
// No need to commit interface names as this is handled by the
// CfgMgr::commit() function.
// This occurs last as if it succeeds, there is no easy way to
// revert it. As a result, the failure to commit a subsequent
......@@ -854,8 +853,8 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
}
LOG_INFO(dhcp6_logger, DHCP6_CONFIG_COMPLETE)
.arg(CfgMgr::instance().getConfiguration()->
getConfigSummary(Configuration::CFGSEL_ALL6));
.arg(CfgMgr::instance().getCurrentCfg()->
getConfigSummary(SrvConfig::CFGSEL_ALL6));
// Everything was fine. Configuration is successful.
answer = isc::config::createAnswer(0, "Configuration successful.");
......
......@@ -45,6 +45,11 @@ void configure(const std::string& file_name) {
// This is a configuration backend implementation that reads the
// configuration from a JSON file.
// We are starting the configuration process so we should remove any
// staging configuration that has been created during previous
// configuration attempts.
CfgMgr::instance().rollback();
isc::data::ConstElementPtr json;
isc::data::ConstElementPtr dhcp6;
isc::data::ConstElementPtr logger;
......@@ -69,8 +74,7 @@ void configure(const std::string& file_name) {
// If there's no logging element, we'll just pass NULL pointer,
// which will be handled by configureLogger().
Daemon::configureLogger(json->get("Logging"),
CfgMgr::instance().getConfiguration(),
ControlledDhcpv6Srv::getInstance()->getVerbose());
CfgMgr::instance().getStagingCfg());
// Get Dhcp6 component from the config
dhcp6 = json->get("Dhcp6");
......@@ -101,7 +105,19 @@ void configure(const std::string& file_name) {
isc_throw(isc::BadValue, reason);
}
// If configuration was parsed successfully, apply the new logger
// configuration to log4cplus. It is done before commit in case
// something goes wrong.
CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
// Use new configuration.
CfgMgr::instance().commit();
} catch (const std::exception& ex) {
// If configuration failed at any stage, we drop the staging
// configuration and continue to use the previous one.
CfgMgr::instance().rollback();
LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL)
.arg(file_name).arg(ex.what());
isc_throw(isc::BadValue, "configuration error using file '"
......
// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-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
......@@ -16,6 +16,7 @@
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_log.h>
#include <dhcpsrv/cfgmgr.h>
#include <log/logger_support.h>
#include <log/logger_manager.h>
#include <exceptions/exceptions.h>
......@@ -122,6 +123,11 @@ main(int argc, char* argv[]) {
int ret = EXIT_SUCCESS;
try {
// It is important that we set a default logger name because this name
// will be used when the user doesn't provide the logging configuration
// in the Kea configuration file.
CfgMgr::instance().setDefaultLoggerName(DHCP6_LOGGER_NAME);
// Initialize logging. If verbose, we'll use maximum verbosity.
Daemon::loggerInit(DHCP6_LOGGER_NAME, verbose_mode);
......
......@@ -359,9 +359,7 @@ public:
// properly test interface configuration we disable listening on
// all interfaces before each test and later check that this setting
// has been overriden by the configuration used in the test.
CfgMgr::instance().getConfiguration()->cfg_iface_.reset();
CfgMgr::instance().getConfiguration()->
cfg_iface_.setFamily(CfgIface::V6);
CfgMgr::instance().clear();
// Create fresh context.
globalContext()->copyContext(ParserContext(Option::V6));
}
......@@ -3057,7 +3055,8 @@ TEST_F(Dhcp6ParserTest, selectedInterfaces) {
// as the pool does not belong to that subnet
checkResult(status, 0);
CfgMgr::instance().getConfiguration()->cfg_iface_.openSockets(10000);
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET6, 10000);
// eth0 and eth1 were explicitly selected. eth2 was not.
EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
......@@ -3075,7 +3074,7 @@ TEST_F(Dhcp6ParserTest, allInterfaces) {
ConstElementPtr status;
// This configuration specifies two interfaces on which server should listen
// bu also includes keyword 'all'. This keyword switches server into the
// but also includes '*'. This keyword switches server into the
// mode when it listens on all interfaces regardless of what interface names
// were specified in the "interfaces" parameter.
string config = "{ \"interfaces\": [ \"eth0\", \"eth1\", \"*\" ],"
......@@ -3090,7 +3089,8 @@ TEST_F(Dhcp6ParserTest, allInterfaces) {
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
checkResult(status, 0);
CfgMgr::instance().getConfiguration()->cfg_iface_.openSockets(10000);
CfgMgr::instance().getStagingCfg()->
getCfgIface().openSockets(AF_INET6, 10000);
// All interfaces should be now active.
EXPECT_TRUE(test_config.socketOpen("eth0", AF_INET6));
......
......@@ -8,8 +8,9 @@ sbin_SCRIPTS = keactrl
CONFIGFILES = keactrl.conf kea.conf
man_MANS = keactrl.8
DISTCLEANFILES = keactrl $(CONFIGFILES) $(man_MANS)
EXTRA_DIST = keactrl.in keactrl.conf.in kea.conf.in $(man_MANS) keactrl.xml
DISTCLEANFILES = keactrl keactrl.conf $(man_MANS)
CLEANFILES = kea.conf
EXTRA_DIST = keactrl.in keactrl.conf.in kea.conf.pre $(man_MANS) keactrl.xml
# kea.conf is not really a source used for building other targets, but we need
# this file to be generated before make install is called.
......@@ -28,8 +29,8 @@ $(man_MANS):
endif
kea.conf: kea.conf.in
$(top_srcdir)/tools/path_replacer.sh $< $@
kea.conf: kea.conf.pre
$(top_srcdir)/tools/path_replacer.sh $(top_srcdir)/src/bin/keactrl/kea.conf.pre $@
if INSTALL_CONFIGURATIONS
......
......@@ -45,6 +45,8 @@ libkea_dhcpsrv_la_SOURCES =
libkea_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
libkea_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
libkea_dhcpsrv_la_SOURCES += callout_handle_store.h
libkea_dhcpsrv_la_SOURCES += cfg_iface.cc cfg_iface.h
libkea_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
libkea_dhcpsrv_la_SOURCES += csv_lease_file4.cc csv_lease_file4.h
libkea_dhcpsrv_la_SOURCES += csv_lease_file6.cc csv_lease_file6.h
libkea_dhcpsrv_la_SOURCES += d2_client_cfg.cc d2_client_cfg.h
......@@ -52,16 +54,14 @@ libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h
libkea_dhcpsrv_la_SOURCES += dbaccess_parser.cc dbaccess_parser.h
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 += cfg_iface.cc cfg_iface.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
libkea_dhcpsrv_la_SOURCES += lease_mgr_factory.cc lease_mgr_factory.h
libkea_dhcpsrv_la_SOURCES += logging.cc logging.h
libkea_dhcpsrv_la_SOURCES += configuration.h configuration.cc
libkea_dhcpsrv_la_SOURCES += logging_info.cc logging_info.h
libkea_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
if HAVE_MYSQL
......@@ -72,6 +72,7 @@ libkea_dhcpsrv_la_SOURCES += pgsql_lease_mgr.cc pgsql_lease_mgr.h
endif
libkea_dhcpsrv_la_SOURCES += option_space_container.h
libkea_dhcpsrv_la_SOURCES += pool.cc pool.h
libkea_dhcpsrv_la_SOURCES += srv_config.cc srv_config.h
libkea_dhcpsrv_la_SOURCES += subnet.cc subnet.h
libkea_dhcpsrv_la_SOURCES += triplet.h
libkea_dhcpsrv_la_SOURCES += utils.h
......
......@@ -25,24 +25,31 @@ namespace dhcp {
const char* CfgIface::ALL_IFACES_KEYWORD = "*";
CfgIface::CfgIface(Family family)
: family_(family),
wildcard_used_(false) {
CfgIface::CfgIface()
: wildcard_used_(false) {
}
void
CfgIface::closeSockets() {
CfgIface::closeSockets() const {
IfaceMgr::instance().closeSockets();
}
bool
CfgIface::equals(const CfgIface& other) const {
return (iface_set_ == other.iface_set_ &&
unicast_map_ == other.unicast_map_ &&
wildcard_used_ == other.wildcard_used_);
}
void
CfgIface::openSockets(const uint16_t port, const bool use_bcast) {
CfgIface::openSockets(const uint16_t family, const uint16_t port,
const bool use_bcast) const {
// If wildcard interface '*' was not specified, set all interfaces to
// inactive state. We will later enable them selectively using the
// interface names specified by the user. If wildcard interface was
// specified, mark all interfaces active. In all cases, mark loopback
// inactive.
setState(!wildcard_used_, true);
setState(family, !wildcard_used_, true);
// Remove selection of unicast addresses from all interfaces.
IfaceMgr::instance().clearUnicasts();
// If there is no wildcard interface specified, we will have to iterate
......@@ -61,7 +68,7 @@ CfgIface::openSockets(const uint16_t port, const bool use_bcast) {
<< *iface_name << "' as this interface doesn't"
" exist");
} else if (getFamily() == V4) {
} else if (family == AF_INET) {
iface->inactive4_ = false;
} else {
......@@ -71,7 +78,7 @@ CfgIface::openSockets(const uint16_t port, const bool use_bcast) {
}
// Select unicast sockets. It works only for V6. Ignore for V4.
if (getFamily() == V6) {
if (family == AF_INET6) {
for (UnicastMap::const_iterator unicast = unicast_map_.begin();
unicast != unicast_map_.end(); ++unicast) {
Iface* iface = IfaceMgr::instance().getIface(unicast->first);
......@@ -95,7 +102,7 @@ CfgIface::openSockets(const uint16_t port, const bool use_bcast) {
IfaceMgrErrorMsgCallback error_callback =
boost::bind(&CfgIface::socketOpenErrorHandler, _1);
bool sopen;
if (getFamily() == V4) {
if (family == AF_INET) {
sopen = IfaceMgr::instance().openSockets4(port, use_bcast,
error_callback);
} else {
......@@ -117,12 +124,13 @@ CfgIface::reset() {
}
void
CfgIface::setState(const bool inactive, const bool loopback_inactive) {
CfgIface::setState(const uint16_t family, const bool inactive,
const bool loopback_inactive) const {
IfaceMgr::IfaceCollection ifaces = IfaceMgr::instance().getIfaces();
for (IfaceMgr::IfaceCollection::iterator iface = ifaces.begin();
iface != ifaces.end(); ++iface) {
Iface* iface_ptr = IfaceMgr::instance().getIface(iface->getName());
if (getFamily() == V4) {
if (family == AF_INET) {
iface_ptr->inactive4_ = iface_ptr->flag_loopback_ ?
loopback_inactive : inactive;
} else {
......@@ -138,7 +146,7 @@ CfgIface::socketOpenErrorHandler(const std::string& errmsg) {
}
void
CfgIface::use(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.:
// - eth0
// - eth0/2001:db8:1::1.
......@@ -184,7 +192,7 @@ CfgIface::use(const std::string& iface_name) {
}
} else if (getFamily() == V4) {
} else if (family == AF_INET) {
isc_throw(InvalidIfaceName, "unicast addresses in the format of: "
"iface-name/unicast-addr_stress can only be specified for"
" IPv6 addr_stress family");
......
......@@ -64,6 +64,11 @@ public:
///
/// Once interfaces have been specified the sockets (either IPv4 or IPv6)
/// can be opened by calling @c CfgIface::openSockets function.
///
/// @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
/// parameter is equal to one of them. It is a callers responsibility to
/// guarantee that the address family value is correct.
class CfgIface {
public:
/// @brief Keyword used to enable all interfaces.
......@@ -72,26 +77,18 @@ public:
/// that DHCP server should listen on all interfaces.
static const char* ALL_IFACES_KEYWORD;
/// @brief Protocol family: IPv4 or IPv6.
///
/// Depending on the family specified, the IPv4 or IPv6 sockets are
/// opened.
enum Family {
V4, V6
};
/// @brief Constructor.
///
/// @param family Protocol family (default is V4).
CfgIface(Family family = V4);
CfgIface();
/// @brief Convenience function which closes all open sockets.
void closeSockets();
void closeSockets() const;
/// @brief Returns protocol family used by the @c CfgIface.
Family getFamily() const {
return (family_);
}
/// @brief Compares two @c CfgIface objects for equality.
///
/// @param other An object to be compared with this object.
///
/// @return true if objects are equal, false otherwise.
bool equals(const CfgIface& other) const;
/// @brief Tries to open sockets on selected interfaces.
///
......@@ -100,24 +97,19 @@ public:
/// documentation for details how to specify interfaces and unicast
/// addresses to bind the sockets to.
///
/// @param family Address family (AF_INET or AF_INET6).
/// @param port Port number to be used to bind sockets to.