Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Adam Osuchowski
Kea
Commits
c3b0803c
Commit
c3b0803c
authored
Aug 20, 2014
by
Marcin Siodelski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[3512] DHCP servers now use the IfaceCfg class for selecting interfaces.
parent
230e6813
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
198 additions
and
558 deletions
+198
-558
src/bin/dhcp4/bundy_controller.cc
src/bin/dhcp4/bundy_controller.cc
+2
-1
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/ctrl_dhcp4_srv.cc
+5
-2
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.cc
+0
-49
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp4/dhcp4_srv.h
+0
-16
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/config_parser_unittest.cc
+17
-13
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+2
-22
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp4/tests/dhcp4_test_utils.cc
+2
-1
src/bin/dhcp4/tests/dora_unittest.cc
src/bin/dhcp4/tests/dora_unittest.cc
+2
-2
src/bin/dhcp4/tests/inform_unittest.cc
src/bin/dhcp4/tests/inform_unittest.cc
+2
-2
src/bin/dhcp6/ctrl_dhcp6_srv.cc
src/bin/dhcp6/ctrl_dhcp6_srv.cc
+6
-2
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.cc
+6
-58
src/bin/dhcp6/dhcp6_srv.h
src/bin/dhcp6/dhcp6_srv.h
+0
-16
src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/config_parser_unittest.cc
+23
-21
src/bin/dhcp6/tests/confirm_unittest.cc
src/bin/dhcp6/tests/confirm_unittest.cc
+2
-2
src/bin/dhcp6/tests/d2_unittest.cc
src/bin/dhcp6/tests/d2_unittest.cc
+1
-1
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+3
-3
src/bin/dhcp6/tests/rebind_unittest.cc
src/bin/dhcp6/tests/rebind_unittest.cc
+6
-6
src/bin/dhcp6/tests/sarr_unittest.cc
src/bin/dhcp6/tests/sarr_unittest.cc
+1
-1
src/lib/dhcp/tests/iface_mgr_test_config.cc
src/lib/dhcp/tests/iface_mgr_test_config.cc
+36
-0
src/lib/dhcp/tests/iface_mgr_test_config.h
src/lib/dhcp/tests/iface_mgr_test_config.h
+12
-0
src/lib/dhcpsrv/cfgmgr.cc
src/lib/dhcpsrv/cfgmgr.cc
+1
-82
src/lib/dhcpsrv/cfgmgr.h
src/lib/dhcpsrv/cfgmgr.h
+0
-78
src/lib/dhcpsrv/configuration.h
src/lib/dhcpsrv/configuration.h
+8
-0
src/lib/dhcpsrv/dhcp_parsers.cc
src/lib/dhcpsrv/dhcp_parsers.cc
+8
-42
src/lib/dhcpsrv/dhcp_parsers.h
src/lib/dhcpsrv/dhcp_parsers.h
+1
-1
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/dhcpsrv_messages.mes
+5
-1
src/lib/dhcpsrv/iface_cfg.cc
src/lib/dhcpsrv/iface_cfg.cc
+18
-9
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
+0
-80
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
+27
-17
src/lib/dhcpsrv/tests/iface_cfg_unittest.cc
src/lib/dhcpsrv/tests/iface_cfg_unittest.cc
+2
-30
No files found.
src/bin/dhcp4/bundy_controller.cc
View file @
c3b0803c
...
...
@@ -177,7 +177,8 @@ void ControlledDhcpv4Srv::init(const std::string& config_file) {
// Configuration may disable or enable interfaces so we have to
// reopen sockets according to new configuration.
openActiveSockets
(
getPort
(),
useBroadcast
());
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
getPort
(),
useBroadcast
());
}
catch
(
const
std
::
exception
&
ex
)
{
LOG_ERROR
(
dhcp4_logger
,
DHCP4_CONFIG_LOAD_FAIL
).
arg
(
ex
.
what
());
...
...
src/bin/dhcp4/ctrl_dhcp4_srv.cc
View file @
c3b0803c
...
...
@@ -18,6 +18,7 @@
#include <dhcp4/dhcp4_log.h>
#include <hooks/hooks_manager.h>
#include <dhcp4/json_config_parser.h>
#include <dhcpsrv/cfgmgr.h>
using
namespace
isc
::
data
;
using
namespace
isc
::
hooks
;
...
...
@@ -117,7 +118,7 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
err
<<
"Server object not initialized, can't process config."
;
return
(
isc
::
config
::
createAnswer
(
1
,
err
.
str
()));
}
ConstElementPtr
answer
=
configureDhcp4Server
(
*
srv
,
config
);
...
...
@@ -148,7 +149,9 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
// safe and we really don't want to emit exceptions to whoever called this
// method. Instead, catch an exception and create appropriate answer.
try
{
srv
->
openActiveSockets
(
srv
->
getPort
(),
getInstance
()
->
useBroadcast
());
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
srv
->
getPort
(),
getInstance
()
->
useBroadcast
());
}
catch
(
std
::
exception
&
ex
)
{
err
<<
"failed to open sockets after server reconfiguration: "
<<
ex
.
what
();
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
c3b0803c
...
...
@@ -1795,55 +1795,6 @@ Dhcpv4Srv::sanityCheck(const Pkt4Ptr& pkt, RequirementLevel serverid) {
}
}
void
Dhcpv4Srv
::
openActiveSockets
(
const
uint16_t
port
,
const
bool
use_bcast
)
{
IfaceMgr
::
instance
().
closeSockets
();
// Get the reference to the collection of interfaces. This reference should
// be valid as long as the program is run because IfaceMgr is a singleton.
// Therefore we can safely iterate over instances of all interfaces and
// modify their flags. Here we modify flags which indicate whether socket
// should be open for a particular interface or not.
const
IfaceMgr
::
IfaceCollection
&
ifaces
=
IfaceMgr
::
instance
().
getIfaces
();
for
(
IfaceMgr
::
IfaceCollection
::
const_iterator
iface
=
ifaces
.
begin
();
iface
!=
ifaces
.
end
();
++
iface
)
{
Iface
*
iface_ptr
=
IfaceMgr
::
instance
().
getIface
(
iface
->
getName
());
if
(
iface_ptr
==
NULL
)
{
isc_throw
(
isc
::
Unexpected
,
"Interface Manager returned NULL"
<<
" instance of the interface when DHCPv4 server was"
<<
" trying to reopen sockets after reconfiguration"
);
}
// Ignore loopback interfaces.
if
(
iface_ptr
->
flag_loopback_
)
{
iface_ptr
->
inactive4_
=
true
;
}
else
if
(
CfgMgr
::
instance
().
isActiveIface
(
iface
->
getName
()))
{
iface_ptr
->
inactive4_
=
false
;
LOG_INFO
(
dhcp4_logger
,
DHCP4_ACTIVATE_INTERFACE
)
.
arg
(
iface
->
getFullName
());
}
else
{
// For deactivating interface, it should be sufficient to log it
// on the debug level because it is more useful to know what
// interface is activated which is logged on the info level.
LOG_DEBUG
(
dhcp4_logger
,
DBG_DHCP4_BASIC
,
DHCP4_DEACTIVATE_INTERFACE
).
arg
(
iface
->
getName
());
iface_ptr
->
inactive4_
=
true
;
}
}
// Let's reopen active sockets. openSockets4 will check internally whether
// sockets are marked active or inactive.
/// @todo Optimization: we should not reopen all sockets but rather select
/// those that have been affected by the new configuration.
isc
::
dhcp
::
IfaceMgrErrorMsgCallback
error_handler
=
boost
::
bind
(
&
Dhcpv4Srv
::
ifaceMgrSocket4ErrorHandler
,
_1
);
if
(
!
IfaceMgr
::
instance
().
openSockets4
(
port
,
use_bcast
,
error_handler
))
{
LOG_WARN
(
dhcp4_logger
,
DHCP4_NO_SOCKETS_OPEN
);
}
}
size_t
Dhcpv4Srv
::
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
...
...
src/bin/dhcp4/dhcp4_srv.h
View file @
c3b0803c
...
...
@@ -128,11 +128,6 @@ public:
///
/// @name Public accessors returning values required to (re)open sockets.
///
/// These accessors must be public because sockets are reopened from the
/// static configuration callback handler. This callback handler invokes
/// @c ControlledDhcpv4Srv::openActiveSockets which requires parameters
/// which has to be retrieved from the @c ControlledDhcpv4Srv object.
/// They are retrieved using these public functions
//@{
///
/// @brief Get UDP port on which server should listen.
...
...
@@ -154,17 +149,6 @@ public:
}
//@}
/// @brief Open sockets which are marked as active in @c CfgMgr.
///
/// This function reopens sockets according to the current settings in the
/// Configuration Manager. It holds the list of the interfaces which server
/// should listen on. This function will open sockets on these interfaces
/// only. This function is not exception safe.
///
/// @param port UDP port on which server should listen.
/// @param use_bcast should broadcast flags be set on the sockets.
static
void
openActiveSockets
(
const
uint16_t
port
,
const
bool
use_bcast
);
/// @brief Starts DHCP_DDNS client IO if DDNS updates are enabled.
///
/// If updates are enabled, it Instructs the D2ClientMgr singleton to
...
...
src/bin/dhcp4/tests/config_parser_unittest.cc
View file @
c3b0803c
...
...
@@ -25,6 +25,7 @@
#include <dhcp/option_int.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp/classify.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/testutils/config_result_check.h>
...
...
@@ -77,7 +78,6 @@ public:
// deal with sockets here, just check if configuration handling
// is sane.
srv_
.
reset
(
new
Dhcpv4Srv
(
0
));
CfgMgr
::
instance
().
deleteActiveIfaces
();
// Create fresh context.
globalContext
()
->
copyContext
(
ParserContext
(
Option
::
V4
));
}
...
...
@@ -2895,6 +2895,8 @@ TEST_F(Dhcp4ParserTest, LibrariesSpecified) {
// This test verifies that it is possible to select subset of interfaces
// on which server should listen.
TEST_F
(
Dhcp4ParserTest
,
selectedInterfaces
)
{
IfaceMgrTestConfig
test_config
(
true
);
ConstElementPtr
x
;
string
config
=
"{
\"
interfaces
\"
: [
\"
eth0
\"
,
\"
eth1
\"
],"
"
\"
rebind-timer
\"
: 2000, "
...
...
@@ -2907,24 +2909,26 @@ TEST_F(Dhcp4ParserTest, selectedInterfaces) {
// Make sure the config manager is clean and there is no hanging
// interface configuration.
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
EXPECT_FALSE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET
));
EXPECT_FALSE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET
));
// Apply configuration.
EXPECT_NO_THROW
(
status
=
configureDhcp4Server
(
*
srv_
,
json
));
ASSERT_TRUE
(
status
);
checkResult
(
status
,
0
);
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
10000
);
// eth0 and eth1 were explicitly selected. eth2 was not.
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
EXPECT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
EXPECT_TRUE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET
));
EXPECT_TRUE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET
));
}
// This test verifies that it is possible to configure the server in such a way
// that it listens on all interfaces.
TEST_F
(
Dhcp4ParserTest
,
allInterfaces
)
{
IfaceMgrTestConfig
test_config
(
true
);
ConstElementPtr
x
;
// This configuration specifies two interfaces on which server should listen
// but it also includes asterisk. The asterisk switches server into the
...
...
@@ -2940,19 +2944,19 @@ TEST_F(Dhcp4ParserTest, allInterfaces) {
ConstElementPtr
status
;
// Make sure there is no old configuration.
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET
));
// Apply configuration.
EXPECT_NO_THROW
(
status
=
configureDhcp4Server
(
*
srv_
,
json
));
ASSERT_TRUE
(
status
);
checkResult
(
status
,
0
);
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
10000
);
// All interfaces should be now active.
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
ASSERT_TRUE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET
));
ASSERT_TRUE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET
));
}
// This test checks the ability of the server to parse a configuration
...
...
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
c3b0803c
...
...
@@ -420,26 +420,6 @@ TEST_F(Dhcpv4SrvTest, basic) {
ASSERT_NO_THROW
(
naked_srv
.
reset
(
new
NakedDhcpv4Srv
(
0
)));
}
// This test verifies that exception is not thrown when an error occurs during
// opening sockets. This test forces an error by adding a fictious interface
// to the IfaceMgr. An attempt to open socket on this interface must always
// fail. The DHCPv4 installs the error handler function to prevent exceptions
// being thrown from the openSockets4 function.
// @todo The server tests for socket should be extended but currently the
// ability to unit test the sockets code is somewhat limited.
TEST_F
(
Dhcpv4SrvTest
,
openActiveSockets
)
{
ASSERT_NO_THROW
(
CfgMgr
::
instance
().
activateAllIfaces
());
Iface
iface
(
"bogusiface"
,
255
);
iface
.
flag_loopback_
=
false
;
iface
.
flag_up_
=
true
;
iface
.
flag_running_
=
true
;
iface
.
inactive4_
=
false
;
iface
.
addAddress
(
IOAddress
(
"192.0.0.0"
));
IfaceMgr
::
instance
().
addInterface
(
iface
);
ASSERT_NO_THROW
(
Dhcpv4Srv
::
openActiveSockets
(
DHCP4_SERVER_PORT
,
false
));
}
// Verifies that DISCOVER message can be processed correctly,
// that the OFFER message generated in response is valid and
// contains necessary options.
...
...
@@ -2970,7 +2950,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
NakedDhcpv4Srv
srv
(
0
);
ConstElementPtr
x
;
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
option-data
\"
: [ {"
...
...
@@ -3055,7 +3035,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
// src/lib/dhcp/docsis3_option_defs.h.
TEST_F
(
Dhcpv4SrvTest
,
vendorOptionsDocsisDefinitions
)
{
ConstElementPtr
x
;
string
config_prefix
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config_prefix
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
option-data
\"
: [ {"
...
...
src/bin/dhcp4/tests/dhcp4_test_utils.cc
View file @
c3b0803c
...
...
@@ -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
().
deleteActiveIfaces
();
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
reset
();
CfgMgr
::
instance
().
deleteSubnets4
();
CfgMgr
::
instance
().
addSubnet4
(
subnet_
);
...
...
@@ -58,6 +58,7 @@ Dhcpv4SrvTest::Dhcpv4SrvTest()
Dhcpv4SrvTest
::~
Dhcpv4SrvTest
()
{
// Make sure that we revert to default value
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
reset
();
CfgMgr
::
instance
().
echoClientId
(
true
);
}
...
...
src/bin/dhcp4/tests/dora_unittest.cc
View file @
c3b0803c
...
...
@@ -49,7 +49,7 @@ namespace {
/// - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
const
char
*
DORA_CONFIGS
[]
=
{
// Configuration 0
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
10.0.0.0/24
\"
, "
...
...
@@ -86,7 +86,7 @@ const char* DORA_CONFIGS[] = {
"}"
,
// Configuration 1
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
192.0.2.0/24
\"
, "
...
...
src/bin/dhcp4/tests/inform_unittest.cc
View file @
c3b0803c
...
...
@@ -48,7 +48,7 @@ namespace {
/// - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
const
char
*
INFORM_CONFIGS
[]
=
{
// Configuration 0
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
10.0.0.0/24
\"
, "
...
...
@@ -85,7 +85,7 @@ const char* INFORM_CONFIGS[] = {
"}"
,
// Configuration 1
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
valid-lifetime
\"
: 600,"
"
\"
subnet4
\"
: [ { "
"
\"
subnet
\"
:
\"
192.0.2.0/24
\"
, "
...
...
src/bin/dhcp6/ctrl_dhcp6_srv.cc
View file @
c3b0803c
...
...
@@ -14,6 +14,7 @@
#include <config.h>
#include <cc/data.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_log.h>
#include <hooks/hooks_manager.h>
...
...
@@ -143,10 +144,13 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
// safe and we really don't want to emit exceptions to the callback caller.
// Instead, catch an exception and create appropriate answer.
try
{
srv
->
openActiveSockets
(
srv
->
getPort
());
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
srv
->
getPort
());
}
catch
(
const
std
::
exception
&
ex
)
{
std
::
ostringstream
err
;
err
<<
"failed to open sockets after server reconfiguration: "
<<
ex
.
what
();
err
<<
"failed to open sockets after server reconfiguration: "
<<
ex
.
what
();
answer
=
isc
::
config
::
createAnswer
(
1
,
err
.
str
());
}
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
c3b0803c
...
...
@@ -150,6 +150,12 @@ 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
()
->
iface_cfg_
.
setFamily
(
IfaceCfg
::
V6
);
/// @todo call loadLibraries() when handling configuration changes
}
catch
(
const
std
::
exception
&
e
)
{
...
...
@@ -2429,64 +2435,6 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
return
reply
;
}
void
Dhcpv6Srv
::
openActiveSockets
(
const
uint16_t
port
)
{
IfaceMgr
::
instance
().
closeSockets
();
// Get the reference to the collection of interfaces. This reference should be
// valid as long as the program is run because IfaceMgr is a singleton.
// Therefore we can safely iterate over instances of all interfaces and modify
// their flags. Here we modify flags which indicate wheter socket should be
// open for a particular interface or not.
const
IfaceMgr
::
IfaceCollection
&
ifaces
=
IfaceMgr
::
instance
().
getIfaces
();
for
(
IfaceMgr
::
IfaceCollection
::
const_iterator
iface
=
ifaces
.
begin
();
iface
!=
ifaces
.
end
();
++
iface
)
{
Iface
*
iface_ptr
=
IfaceMgr
::
instance
().
getIface
(
iface
->
getName
());
if
(
iface_ptr
==
NULL
)
{
isc_throw
(
isc
::
Unexpected
,
"Interface Manager returned NULL"
<<
" instance of the interface when DHCPv6 server was"
<<
" trying to reopen sockets after reconfiguration"
);
}
// Ignore loopback interfaces.
if
(
iface_ptr
->
flag_loopback_
)
{
iface_ptr
->
inactive6_
=
true
;
}
else
if
(
CfgMgr
::
instance
().
isActiveIface
(
iface
->
getName
()))
{
iface_ptr
->
inactive6_
=
false
;
LOG_INFO
(
dhcp6_logger
,
DHCP6_ACTIVATE_INTERFACE
)
.
arg
(
iface
->
getFullName
());
}
else
{
// For deactivating interface, it should be sufficient to log it
// on the debug level because it is more useful to know what
// interface is activated which is logged on the info level.
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_BASIC
,
DHCP6_DEACTIVATE_INTERFACE
).
arg
(
iface
->
getName
());
iface_ptr
->
inactive6_
=
true
;
}
iface_ptr
->
clearUnicasts
();
const
IOAddress
*
unicast
=
CfgMgr
::
instance
().
getUnicast
(
iface
->
getName
());
if
(
unicast
)
{
LOG_INFO
(
dhcp6_logger
,
DHCP6_SOCKET_UNICAST
).
arg
(
unicast
->
toText
())
.
arg
(
iface
->
getName
());
iface_ptr
->
addUnicast
(
*
unicast
);
}
}
// Let's reopen active sockets. openSockets6 will check internally whether
// sockets are marked active or inactive.
// @todo Optimization: we should not reopen all sockets but rather select
// those that have been affected by the new configuration.
isc
::
dhcp
::
IfaceMgrErrorMsgCallback
error_handler
=
boost
::
bind
(
&
Dhcpv6Srv
::
ifaceMgrSocket6ErrorHandler
,
_1
);
if
(
!
IfaceMgr
::
instance
().
openSockets6
(
port
,
error_handler
))
{
LOG_WARN
(
dhcp6_logger
,
DHCP6_NO_SOCKETS_OPEN
);
}
}
size_t
Dhcpv6Srv
::
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
c3b0803c
...
...
@@ -100,27 +100,11 @@ public:
/// Typically, server listens on UDP port 547. Other ports are only
/// used for testing purposes.
///
/// This accessor must be public because sockets are reopened from the
/// static configuration callback handler. This callback handler invokes
/// @c ControlledDhcpv4Srv::openActiveSockets which requires port parameter
/// which has to be retrieved from the @c ControlledDhcpv4Srv object.
/// They are retrieved using this public function.
///
/// @return UDP port on which server should listen.
uint16_t
getPort
()
const
{
return
(
port_
);
}
/// @brief Open sockets which are marked as active in @c CfgMgr.
///
/// This function reopens sockets according to the current settings in the
/// Configuration Manager. It holds the list of the interfaces which server
/// should listen on. This function will open sockets on these interfaces
/// only. This function is not exception safe.
///
/// @param port UDP port on which server should listen.
static
void
openActiveSockets
(
const
uint16_t
port
);
/// @brief Starts DHCP_DDNS client IO if DDNS updates are enabled.
///
/// If updates are enabled, it Instructs the D2ClientMgr singleton to
...
...
src/bin/dhcp6/tests/config_parser_unittest.cc
View file @
c3b0803c
...
...
@@ -20,6 +20,7 @@
#include <dhcp/iface_mgr.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_int.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp6/json_config_parser.h>
#include <dhcp6/dhcp6_srv.h>
#include <dhcpsrv/addr_utilities.h>
...
...
@@ -74,7 +75,8 @@ public:
// deal with sockets here, just check if configuration handling
// is sane.
const
IfaceMgr
::
IfaceCollection
&
ifaces
=
IfaceMgr
::
instance
().
getIfaces
();
const
IfaceMgr
::
IfaceCollection
&
ifaces
=
IfaceMgr
::
instance
().
getIfaces
();
// There must be some interface detected
if
(
ifaces
.
empty
())
{
...
...
@@ -341,7 +343,7 @@ public:
/// test to make sure that contents of the database do not affect the
/// results of subsequent tests.
void
resetConfiguration
()
{
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
hooks-libraries
\"
: [ ],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
...
...
@@ -357,7 +359,9 @@ 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
().
deleteActiveIfaces
();
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
reset
();
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
setFamily
(
IfaceCfg
::
V6
);
// Create fresh context.
globalContext
()
->
copyContext
(
ParserContext
(
Option
::
V6
));
}
...
...
@@ -2892,7 +2896,7 @@ buildHooksLibrariesConfig(const std::vector<std::string>& libraries) {
// Create the first part of the configuration string.
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
hooks-libraries
\"
: ["
;
// Append the libraries (separated by commas if needed)
...
...
@@ -3030,15 +3034,15 @@ TEST_F(Dhcp6ParserTest, LibrariesSpecified) {
// This test verifies that it is possible to select subset of interfaces on
// which server should listen.
TEST_F
(
Dhcp6ParserTest
,
selectedInterfaces
)
{
IfaceMgrTestConfig
test_config
(
true
);
// Make sure there is no garbage interface configuration in the CfgMgr.
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET6
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET6
));
ConstElementPtr
status
;
string
config
=
"{
\"
interfaces
\"
: [
\"
eth0
\"
,
\"
eth1
\"
],"
string
config
=
"{
\"
interfaces
\"
: [
\"
eth0
\"
],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
...
...
@@ -3053,20 +3057,20 @@ TEST_F(Dhcp6ParserTest, selectedInterfaces) {
// as the pool does not belong to that subnet
checkResult
(
status
,
0
);
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
10000
);
// eth0 and eth1 were explicitly selected. eth2 was not.
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
EXPECT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
EXPECT_TRUE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET6
));
EXPECT_FALSE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET6
));
}
// This test verifies that it is possible to configure the server to listen on
// all interfaces.
TEST_F
(
Dhcp6ParserTest
,
allInterfaces
)
{
IfaceMgrTestConfig
test_config
(
true
);
// Make sure there is no garbage interface configuration in the CfgMgr.
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
ASSERT_FALSE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET6
));
ASSERT_FALSE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET6
));
ConstElementPtr
status
;
...
...
@@ -3084,15 +3088,13 @@ TEST_F(Dhcp6ParserTest, allInterfaces) {
ElementPtr
json
=
Element
::
fromJSON
(
config
);
EXPECT_NO_THROW
(
status
=
configureDhcp6Server
(
srv_
,
json
));
// returned value must be 1 (values error)
// as the pool does not belong to that subnet
checkResult
(
status
,
0
);
CfgMgr
::
instance
().
getConfiguration
()
->
iface_cfg_
.
openSockets
(
10000
);
// All interfaces should be now active.
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth0"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth1"
));
EXPECT_TRUE
(
CfgMgr
::
instance
().
isActiveIface
(
"eth2"
));
EXPECT_TRUE
(
test_config
.
socketOpen
(
"eth0"
,
AF_INET6
));
EXPECT_TRUE
(
test_config
.
socketOpen
(
"eth1"
,
AF_INET6
));
}
...
...
src/bin/dhcp6/tests/confirm_unittest.cc
View file @
c3b0803c
...
...
@@ -42,7 +42,7 @@ namespace {
///
const
char
*
CONFIRM_CONFIGS
[]
=
{
// Configuration 0
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
...
...
@@ -61,7 +61,7 @@ const char* CONFIRM_CONFIGS[] = {
"
\"
valid-lifetime
\"
: 4000 }"
,
// Configuration 1
"{
\"
interfaces
\"
: [
\"
all
\"
],"
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
...
...
src/bin/dhcp6/tests/d2_unittest.cc
View file @
c3b0803c
...
...
@@ -75,7 +75,7 @@ Dhcp6SrvD2Test::buildTestNcr(uint32_t dhcid_id_num) {
void
Dhcp6SrvD2Test
::
reset
()
{
std
::
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
std
::
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
hooks-libraries
\"
: [ ],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
c3b0803c
...
...
@@ -289,7 +289,7 @@ TEST_F(Dhcpv6SrvTest, advertiseOptions) {
IfaceMgrTestConfig
test_config
(
true
);
ConstElementPtr
x
;
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
...
...
@@ -1557,7 +1557,7 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsORO) {
IfaceMgrTestConfig
test_config
(
true
);
string
config
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
...
...
@@ -1642,7 +1642,7 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsORO) {
// src/lib/dhcp/docsis3_option_defs.h.
TEST_F
(
Dhcpv6SrvTest
,
vendorOptionsDocsisDefinitions
)
{
ConstElementPtr
x
;
string
config_prefix
=
"{
\"
interfaces
\"
: [
\"
all
\"
],"
string
config_prefix
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
preferred-lifetime
\"
: 3000,