Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
3fb6d907
Commit
3fb6d907
authored
Dec 17, 2014
by
Marcin Siodelski
Browse files
[3539] Iface configuration allows for specifying IPv4 address to listen on.
parent
32f06c29
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/iface_mgr.cc
View file @
3fb6d907
...
...
@@ -40,6 +40,7 @@
using
namespace
std
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
util
;
using
namespace
isc
::
util
::
io
::
internal
;
namespace
isc
{
...
...
@@ -149,7 +150,7 @@ void Iface::setMac(const uint8_t* mac, size_t len) {
bool
Iface
::
delAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
for
(
AddressCollection
::
iterator
a
=
addrs_
.
begin
();
a
!=
addrs_
.
end
();
++
a
)
{
if
(
*
a
==
addr
)
{
if
(
a
->
get
()
==
addr
)
{
addrs_
.
erase
(
a
);
return
(
true
);
}
...
...
@@ -216,12 +217,12 @@ IfaceMgr::IfaceMgr()
void
Iface
::
addUnicast
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
for
(
Iface
::
AddressCollection
::
const_iterator
i
=
unicasts_
.
begin
();
i
!=
unicasts_
.
end
();
++
i
)
{
if
(
*
i
==
addr
)
{
if
(
i
->
get
()
==
addr
)
{
isc_throw
(
BadValue
,
"Address "
<<
addr
<<
" already defined on the "
<<
name_
<<
" interface."
);
}
}
unicasts_
.
push_back
(
addr
);
unicasts_
.
push_back
(
OptionalValue
<
IOAddress
>
(
addr
,
true
)
);
}
bool
...
...
@@ -233,8 +234,8 @@ Iface::getAddress4(isc::asiolink::IOAddress& address) const {
addr
!=
addrs
.
end
();
++
addr
)
{
// If address is IPv4, we assign it to the function argument
// and return true.
if
(
addr
->
isV4
())
{
address
=
*
addr
;
if
(
addr
->
get
().
isV4
())
{
address
=
addr
->
get
()
;
return
(
true
);
}
}
...
...
@@ -247,13 +248,39 @@ Iface::hasAddress(const isc::asiolink::IOAddress& address) const {
const
AddressCollection
&
addrs
=
getAddresses
();
for
(
AddressCollection
::
const_iterator
addr
=
addrs
.
begin
();
addr
!=
addrs
.
end
();
++
addr
)
{
if
(
address
==
*
addr
)
{
if
(
address
==
addr
->
get
()
)
{
return
(
true
);
}
}
return
(
false
);
}
void
Iface
::
addAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
addrs_
.
push_back
(
OptionalValue
<
IOAddress
>
(
addr
,
OptionalValueState
(
false
)));
}
void
Iface
::
setActive
(
const
IOAddress
&
address
,
const
bool
active
)
{
for
(
AddressCollection
::
iterator
addr_it
=
addrs_
.
begin
();
addr_it
!=
addrs_
.
end
();
++
addr_it
)
{
if
(
address
==
addr_it
->
get
())
{
addr_it
->
specify
(
active
);
return
;
}
}
isc_throw
(
BadValue
,
"specified address "
<<
address
<<
" was not"
" found on the interface "
<<
getName
());
}
void
Iface
::
setActive
(
const
bool
active
)
{
for
(
AddressCollection
::
iterator
addr_it
=
addrs_
.
begin
();
addr_it
!=
addrs_
.
end
();
++
addr_it
)
{
addr_it
->
specify
(
active
);
}
}
void
IfaceMgr
::
closeSockets
()
{
for
(
IfaceCollection
::
iterator
iface
=
ifaces_
.
begin
();
iface
!=
ifaces_
.
end
();
++
iface
)
{
...
...
@@ -393,7 +420,7 @@ IfaceMgr::hasOpenSocket(const IOAddress& addr) const {
iface
->
getAddresses
().
begin
();
addr_it
!=
iface
->
getAddresses
().
end
();
++
addr_it
)
{
if
(
addr
==
*
addr_it
)
{
if
(
addr
==
addr_it
->
get
()
)
{
return
(
true
);
}
}
...
...
@@ -488,7 +515,7 @@ IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
++
addr
)
{
// Skip all but V4 addresses.
if
(
!
addr
->
isV4
())
{
if
(
!
addr
->
get
().
isV4
())
{
continue
;
}
...
...
@@ -616,7 +643,7 @@ IfaceMgr::openSockets6(const uint16_t port,
++
addr
)
{
// Skip all but V6 addresses.
if
(
!
addr
->
isV6
())
{
if
(
!
addr
->
get
().
isV6
())
{
continue
;
}
...
...
@@ -625,7 +652,7 @@ IfaceMgr::openSockets6(const uint16_t port,
// with interface with 2 global addresses, we would bind 3 sockets
// (one for link-local and two for global). That would result in
// getting each message 3 times.
if
(
!
addr
->
isV6LinkLocal
()){
if
(
!
addr
->
get
().
isV6LinkLocal
()){
continue
;
}
...
...
@@ -663,7 +690,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
for
(
Iface
::
AddressCollection
::
const_iterator
addr
=
addrs
.
begin
();
addr
!=
addrs
.
end
();
++
addr
)
{
out
<<
" "
<<
addr
->
toText
();
out
<<
" "
<<
addr
->
get
().
toText
();
}
out
<<
endl
;
}
...
...
@@ -743,7 +770,7 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
Iface
::
AddressCollection
addrs
=
iface
->
getAddresses
();
Iface
::
AddressCollection
::
iterator
addr_it
=
addrs
.
begin
();
while
(
addr_it
!=
addrs
.
end
())
{
if
(
addr_it
->
getFamily
()
==
family
)
{
if
(
addr_it
->
get
().
getFamily
()
==
family
)
{
// We have interface and address so let's open socket.
// This may cause isc::Unexpected exception.
return
(
openSocket
(
iface
->
getName
(),
*
addr_it
,
port
,
false
));
...
...
@@ -787,7 +814,7 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
// on detected interfaces. If it does, we have
// address and interface detected so we can open
// socket.
if
(
*
addr_it
==
addr
)
{
if
(
addr_it
->
get
()
==
addr
)
{
// Open socket using local interface, address and port.
// This may cause isc::Unexpected exception.
return
(
openSocket
(
iface
->
getName
(),
*
addr_it
,
port
,
false
));
...
...
src/lib/dhcp/iface_mgr.h
View file @
3fb6d907
...
...
@@ -22,6 +22,7 @@
#include
<dhcp/pkt6.h>
#include
<dhcp/pkt_filter.h>
#include
<dhcp/pkt_filter6.h>
#include
<util/optional_value.h>
#include
<boost/function.hpp>
#include
<boost/noncopyable.hpp>
...
...
@@ -150,7 +151,8 @@ public:
static
const
unsigned
int
MAX_MAC_LEN
=
20
;
/// Type that defines list of addresses
typedef
std
::
vector
<
isc
::
asiolink
::
IOAddress
>
AddressCollection
;
typedef
std
::
list
<
util
::
OptionalValue
<
asiolink
::
IOAddress
>
>
AddressCollection
;
/// @brief Type that holds a list of socket information.
///
...
...
@@ -291,9 +293,30 @@ public:
/// configure address on actual network interface.
///
/// @param addr address to be added
void
addAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
addrs_
.
push_back
(
addr
);
}
void
addAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
);
/// @brief Activates or deactivates address for the interface.
///
/// This method marks a specified address on the interface active or
/// inactive. If the address is marked inactive, the
/// @c IfaceMgr::openSockets4 method will NOT open socket for this address.
///
/// @param address An address which should be activated, deactivated.
/// @param active A boolean flag which indicates that the specified address
/// should be active (if true) or inactive (if false).
///
/// @throw BadValue if specified address doesn't exist for the interface.
void
setActive
(
const
isc
::
asiolink
::
IOAddress
&
address
,
const
bool
active
);
/// @brief Activates or deactivates all addresses for the interface.
///
/// This method marks all addresses on the interface active or inactive.
/// If the address is marked inactive, the @c IfaceMgr::openSockets4
/// method will NOT open socket for this address.
///
/// @param active A boolean flag which indicates that the addresses
/// should be active (if true) or inactive (if false).
void
setActive
(
const
bool
active
);
/// @brief Deletes an address from an interface.
///
...
...
src/lib/dhcp/tests/iface_mgr_test_config.cc
View file @
3fb6d907
...
...
@@ -107,6 +107,7 @@ IfaceMgrTestConfig::createIfaces() {
// eth1
addIface
(
"eth1"
,
2
);
addAddress
(
"eth1"
,
IOAddress
(
"192.0.2.3"
));
addAddress
(
"eth1"
,
IOAddress
(
"192.0.2.5"
));
addAddress
(
"eth1"
,
IOAddress
(
"fe80::3a60:77ff:fed5:abcd"
));
}
...
...
@@ -143,7 +144,7 @@ IfaceMgrTestConfig::setIfaceFlags(const std::string& name,
bool
IfaceMgrTestConfig
::
socketOpen
(
const
std
::
string
&
iface_name
,
const
int
family
)
const
{
const
int
family
)
const
{
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
iface_name
);
if
(
iface
==
NULL
)
{
isc_throw
(
Unexpected
,
"No such interface '"
<<
iface_name
<<
"'"
);
...
...
@@ -159,6 +160,25 @@ IfaceMgrTestConfig::socketOpen(const std::string& iface_name,
return
(
false
);
}
bool
IfaceMgrTestConfig
::
socketOpen
(
const
std
::
string
&
iface_name
,
const
std
::
string
&
address
)
const
{
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
iface_name
);
if
(
iface
==
NULL
)
{
isc_throw
(
Unexpected
,
"No such interface '"
<<
iface_name
<<
"'"
);
}
const
Iface
::
SocketCollection
&
sockets
=
iface
->
getSockets
();
for
(
Iface
::
SocketCollection
::
const_iterator
sock
=
sockets
.
begin
();
sock
!=
sockets
.
end
();
++
sock
)
{
if
((
sock
->
family_
==
AF_INET
)
&&
(
sock
->
addr_
==
IOAddress
(
address
)))
{
return
(
true
);
}
}
return
(
false
);
}
bool
IfaceMgrTestConfig
::
unicastOpen
(
const
std
::
string
&
iface_name
)
const
{
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
iface_name
);
...
...
src/lib/dhcp/tests/iface_mgr_test_config.h
View file @
3fb6d907
...
...
@@ -235,6 +235,14 @@ public:
/// @param family One of: AF_INET or AF_INET6
bool
socketOpen
(
const
std
::
string
&
iface_name
,
const
int
family
)
const
;
/// @brief Checks is socket is opened on the interface and bound to a
/// specified address.
///
/// @param iface_name Interface name.
/// @param address Address to which the socket is bound.
bool
socketOpen
(
const
std
::
string
&
iface_name
,
const
std
::
string
&
address
)
const
;
/// @brief Checks if unicast socket is opened on interface.
///
/// @param iface_name Interface name.
...
...
src/lib/dhcp/tests/iface_mgr_unittest.cc
View file @
3fb6d907
...
...
@@ -289,7 +289,7 @@ public:
iface
->
getAddresses
().
begin
();
addr_it
!=
iface
->
getAddresses
().
end
();
++
addr_it
)
{
if
(
*
addr_it
==
IOAddress
(
addr
))
{
if
(
addr_it
->
get
()
==
IOAddress
(
addr
))
{
return
(
true
);
}
}
...
...
@@ -1501,7 +1501,7 @@ TEST_F(IfaceMgrTest, openSockets4IfaceDown) {
// Expecting that the socket is open on eth1 because it was up, running
// and active.
EXPECT_EQ
(
1
,
IfaceMgr
::
instance
().
getIface
(
"eth1"
)
->
getSockets
().
size
());
EXPECT_EQ
(
2
,
IfaceMgr
::
instance
().
getIface
(
"eth1"
)
->
getSockets
().
size
());
// Never open socket on loopback interface.
EXPECT_TRUE
(
IfaceMgr
::
instance
().
getIface
(
"lo"
)
->
getSockets
().
empty
());
...
...
@@ -2072,7 +2072,7 @@ TEST_F(IfaceMgrTest, iface) {
addrs
=
iface
->
getAddresses
();
ASSERT_EQ
(
1
,
addrs
.
size
());
EXPECT_EQ
(
"192.0.2.6"
,
addrs
.
a
t
(
0
).
toText
());
EXPECT_EQ
(
"192.0.2.6"
,
addrs
.
begin
()
->
ge
t
().
toText
());
// No such address, should return false.
EXPECT_FALSE
(
iface
->
delAddress
(
IOAddress
(
"192.0.8.9"
)));
...
...
@@ -2332,7 +2332,7 @@ checkIfAddrs(const Iface & iface, struct ifaddrs *& ifptr) {
for
(
Iface
::
AddressCollection
::
const_iterator
a
=
iface
.
getAddresses
().
begin
();
a
!=
iface
.
getAddresses
().
end
();
++
a
)
{
if
(
a
->
isV4
()
&&
(
*
a
)
==
addrv4
)
{
if
(
a
->
get
().
isV4
()
&&
(
a
->
get
()
)
==
addrv4
)
{
return
(
true
);
}
}
...
...
@@ -2349,7 +2349,7 @@ checkIfAddrs(const Iface & iface, struct ifaddrs *& ifptr) {
for
(
Iface
::
AddressCollection
::
const_iterator
a
=
iface
.
getAddresses
().
begin
();
a
!=
iface
.
getAddresses
().
end
();
++
a
)
{
if
(
a
->
isV6
()
&&
(
*
a
)
==
addrv6
)
{
if
(
a
->
get
().
isV6
()
&&
(
a
->
get
(
)
==
addrv6
)
)
{
return
(
true
);
}
}
...
...
src/lib/dhcpsrv/cfg_iface.cc
View file @
3fb6d907
...
...
@@ -37,7 +37,7 @@ CfgIface::closeSockets() const {
bool
CfgIface
::
equals
(
const
CfgIface
&
other
)
const
{
return
(
iface_set_
==
other
.
iface_set_
&&
unicast
_map_
==
other
.
unicast
_map_
&&
address
_map_
==
other
.
address
_map_
&&
wildcard_used_
==
other
.
wildcard_used_
);
}
...
...
@@ -70,6 +70,10 @@ CfgIface::openSockets(const uint16_t family, const uint16_t port,
}
else
if
(
family
==
AF_INET
)
{
iface
->
inactive4_
=
false
;
ExplicitAddressMap
::
const_iterator
addr
=
address_map_
.
find
(
iface
->
getName
());
if
(
addr
!=
address_map_
.
end
())
{
iface
->
setActive
(
addr
->
second
,
true
);
}
}
else
{
iface
->
inactive6_
=
false
;
...
...
@@ -79,8 +83,8 @@ CfgIface::openSockets(const uint16_t family, const uint16_t port,
// Select unicast sockets. It works only for V6. Ignore for V4.
if
(
family
==
AF_INET6
)
{
for
(
Unicast
Map
::
const_iterator
unicast
=
unicast
_map_
.
begin
();
unicast
!=
unicast
_map_
.
end
();
++
unicast
)
{
for
(
ExplicitAddress
Map
::
const_iterator
unicast
=
address
_map_
.
begin
();
unicast
!=
address
_map_
.
end
();
++
unicast
)
{
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
unicast
->
first
);
if
(
iface
==
NULL
)
{
isc_throw
(
Unexpected
,
...
...
@@ -130,13 +134,23 @@ CfgIface::setState(const uint16_t family, const bool inactive,
for
(
IfaceMgr
::
IfaceCollection
::
iterator
iface
=
ifaces
.
begin
();
iface
!=
ifaces
.
end
();
++
iface
)
{
Iface
*
iface_ptr
=
IfaceMgr
::
instance
().
getIface
(
iface
->
getName
());
bool
iface_inactive
=
iface_ptr
->
flag_loopback_
?
loopback_inactive
:
inactive
;
if
(
family
==
AF_INET
)
{
iface_ptr
->
inactive4_
=
iface_ptr
->
flag_loopback_
?
loopback_inactive
:
inactive
;
iface_ptr
->
inactive4_
=
iface_inactive
;
}
else
{
iface_ptr
->
inactive6_
=
iface_ptr
->
flag_loopback_
?
loopback_inactive
:
inactive
;
iface_ptr
->
inactive6_
=
iface_inactive
;
}
// Activate/deactivate all addresses.
const
Iface
::
AddressCollection
addresses
=
iface_ptr
->
getAddresses
();
for
(
Iface
::
AddressCollection
::
const_iterator
addr_it
=
addresses
.
begin
();
addr_it
!=
addresses
.
end
();
++
addr_it
)
{
if
(
addr_it
->
get
().
getFamily
()
==
family
)
{
iface_ptr
->
setActive
(
addr_it
->
get
(),
!
iface_inactive
);
}
}
}
}
...
...
@@ -169,18 +183,6 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
<<
"' doesn't exist in the system"
);
}
// If interface has already been specified.
if
(
iface_set_
.
find
(
name
)
!=
iface_set_
.
end
())
{
isc_throw
(
DuplicateIfaceName
,
"interface '"
<<
name
<<
"' has already been specified"
);
}
// All ok, add interface.
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_ADD_IFACE
)
.
arg
(
name
);
iface_set_
.
insert
(
name
);
}
else
if
(
wildcard_used_
)
{
isc_throw
(
DuplicateIfaceName
,
"the wildcard interface '"
<<
ALL_IFACES_KEYWORD
<<
"' can only be specified once"
);
...
...
@@ -192,14 +194,10 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
}
}
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"
);
}
else
{
// The interface name includes the unicast addr_stress, so we split
// interface name and the unicast addr_stress to two variables.
// The interface name includes the address on which the socket should
// be opened, we we need to split interface name and the address to
// two variables.
name
=
util
::
str
::
trim
(
iface_name
.
substr
(
0
,
pos
));
addr_str
=
util
::
str
::
trim
(
iface_name
.
substr
(
pos
+
1
));
...
...
@@ -210,10 +208,10 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
" interface configuration"
);
}
//
Unicast addr_st
ress following the interface name must not be empty.
//
An add
ress following the interface name must not be empty.
if
(
addr_str
.
empty
())
{
isc_throw
(
InvalidIfaceName
,
"empty
unicast addr_st
ress specified in the interface"
"empty
add
ress specified in the interface"
<<
" configuration"
);
}
...
...
@@ -222,8 +220,8 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
if
(
name
==
ALL_IFACES_KEYWORD
)
{
isc_throw
(
InvalidIfaceName
,
"wildcard interface name '"
<<
ALL_IFACES_KEYWORD
<<
"' must not be used in conjunction with a"
"
unicast addr_st
ress"
);
<<
"' must not be used in conjunction with a
n
"
"
add
ress"
);
}
...
...
@@ -239,17 +237,26 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
// is invalid.
IOAddress
addr
(
addr_str
);
// Check that the address is a valid unicast address.
if
(
!
addr
.
isV6
()
||
addr
.
isV6LinkLocal
()
||
addr
.
isV6Multicast
())
{
isc_throw
(
InvalidIfaceName
,
"address '"
<<
addr
<<
"' is not"
" a valid IPv6 unicast address"
);
}
// Validate V6 address.
if
(
family
==
AF_INET6
)
{
// Check that the address is a valid unicast address.
if
(
!
addr
.
isV6
()
||
addr
.
isV6LinkLocal
()
||
addr
.
isV6Multicast
())
{
isc_throw
(
InvalidIfaceName
,
"address '"
<<
addr
<<
"' is not"
" a valid IPv6 unicast address"
);
}
// There are valid cases where link local address can be specified to
// receive unicast traffic, e.g. sent by relay agent.
if
(
addr
.
isV6LinkLocal
())
{
LOG_WARN
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_UNICAST_LINK_LOCAL
)
.
arg
(
addr
.
toText
()).
arg
(
name
);
// There are valid cases where link local address can be specified to
// receive unicast traffic, e.g. sent by relay agent.
if
(
addr
.
isV6LinkLocal
())
{
LOG_WARN
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_UNICAST_LINK_LOCAL
)
.
arg
(
addr
.
toText
()).
arg
(
name
);
}
}
else
{
if
(
!
addr
.
isV4
())
{
isc_throw
(
InvalidIfaceName
,
"address '"
<<
addr
<<
"' is not"
" a valid IPv4 address"
);
}
}
// Interface must have this address assigned.
...
...
@@ -261,17 +268,41 @@ CfgIface::use(const uint16_t family, const std::string& iface_name) {
// Insert address and the interface to the collection of unicast
// addresses.
if
(
unicast
_map_
.
find
(
name
)
!=
unicast
_map_
.
end
())
{
if
(
address
_map_
.
find
(
name
)
!=
address
_map_
.
end
())
{
isc_throw
(
DuplicateIfaceName
,
"must not specify unicast address '"
<<
addr
<<
"' for interface '"
<<
name
<<
"' "
"because other unicast address has already been"
" specified for this interface"
);
}
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_ADD_UNICAST
)
.
arg
(
addr
.
toText
()).
arg
(
name
);
unicast_map_
.
insert
(
std
::
pair
<
std
::
string
,
IOAddress
>
(
name
,
addr
));
if
(
family
==
AF_INET6
)
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_ADD_UNICAST
)
.
arg
(
addr
.
toText
()).
arg
(
name
);
}
else
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_USE_ADDRESS
)
.
arg
(
addr
.
toText
()).
arg
(
name
);
}
address_map_
.
insert
(
std
::
pair
<
std
::
string
,
IOAddress
>
(
name
,
addr
));
}
// If interface name was explicitly specified and we're not parsing
// a unicast IPv6 address, add the interface to the interface set.
if
((
name
!=
ALL_IFACES_KEYWORD
)
&&
((
family
==
AF_INET
)
||
((
family
==
AF_INET6
)
&&
addr_str
.
empty
())))
{
// If interface has already been specified.
if
(
iface_set_
.
find
(
name
)
!=
iface_set_
.
end
())
{
isc_throw
(
DuplicateIfaceName
,
"interface '"
<<
name
<<
"' has already been specified"
);
}
// Log that we're listening on the specific interface and that the
// address is not explicitly specified.
if
(
addr_str
.
empty
())
{
LOG_INFO
(
dhcpsrv_logger
,
DHCPSRV_CFGMGR_ADD_IFACE
).
arg
(
name
);
}
iface_set_
.
insert
(
name
);
}
}
}
// end of isc::dhcp namespace
...
...
src/lib/dhcpsrv/cfg_iface.h
View file @
3fb6d907
...
...
@@ -193,14 +193,13 @@ private:
/// @brief A set of interface names specified by the user.
IfaceSet
iface_set_
;
/// @brief A map of interfaces and unicast addresses.
typedef
std
::
map
<
std
::
string
,
asiolink
::
IOAddress
>
UnicastMap
;
/// @brief A map of interfaces and addresses to which the server
/// should bind sockets.
typedef
std
::
map
<
std
::
string
,
asiolink
::
IOAddress
>
ExplicitAddressMap
;
/// @brief A map which holds the pairs of interface names and unicast
/// addresses for which the unicast sockets should be opened.
///
/// This is only used for V6 family.
UnicastMap
unicast_map_
;
/// @brief A map which holds the pairs of interface names and addresses
/// for which the sockets should be opened.
ExplicitAddressMap
address_map_
;
/// @brief A booolean value which indicates that the wildcard interface name
/// has been specified (*).
...
...
src/lib/dhcpsrv/dhcpsrv_messages.mes
View file @
3fb6d907
...
...
@@ -142,6 +142,10 @@ This warning message is logged when user specified a link-local address to
receive unicast traffic. The warning message is issued because it is an
uncommon use.
% DHCPSRV_CFGMGR_USE_ADDRESS listening on address %1, on interface %2
A message issued when server is configured to listen on the explicitly specified
IP address on the given interface.
% DHCPSRV_CLOSE_DB closing currently open %1 database
This is a debug message, issued when the DHCP server closes the currently
open lease database. It is issued at program shutdown and whenever
...
...
src/lib/dhcpsrv/tests/cfg_iface_unittest.cc
View file @
3fb6d907
...
...
@@ -42,6 +42,14 @@ public:
/// @param family One of: AF_INET or AF_INET6
bool
socketOpen
(
const
std
::
string
&
iface_name
,
const
int
family
)
const
;
/// @brief Checks if socket is opened on the specified interface and bound
/// to a specific IPv4 address.
///
/// @param iface_name Interface name.
/// @param address Address that the socket should be bound to.
bool
socketOpen
(
const
std
::
string
&
iface_name
,
const
std
::
string
&
address
)
const
;
/// @brief Checks if unicast socket is opened on interface.
///
/// @param iface_name Interface name.
...
...
@@ -57,6 +65,15 @@ CfgIfaceTest::socketOpen(const std::string& iface_name,
const
int
family
)
const
{
return
(
iface_mgr_test_config_
.
socketOpen
(
iface_name
,
family
));
}
bool
CfgIfaceTest
::
socketOpen
(
const
std
::
string
&
iface_name
,
const
std
::
string
&
address
)
const
{
return
(
iface_mgr_test_config_
.
socketOpen
(
iface_name
,
address
));
}
bool
CfgIfaceTest
::
unicastOpen
(
const
std
::
string
&
iface_name
)
const
{
return
(
iface_mgr_test_config_
.
unicastOpen
(
iface_name
));
...
...
@@ -99,7 +116,38 @@ TEST_F(CfgIfaceTest, explicitNamesV4) {
EXPECT_FALSE
(
socketOpen
(
"eth0"
,
AF_INET
));
EXPECT_TRUE
(
socketOpen
(
"eth1"
,
AF_INET
));
EXPECT_FALSE
(
socketOpen
(
"lo"
,
AF_INET
));
}
// This test checks that it is possible to specify an interface and address
// on this interface to which the socket should be bound. The sockets should
// not be opened on other addresses on this interface.
TEST_F
(
CfgIfaceTest
,
explicitNamesAndAddressesV4
)
{
CfgIface
cfg
;
ASSERT_NO_THROW
(
cfg
.
use
(
AF_INET
,
"eth0/10.0.0.1"
));
ASSERT_NO_THROW
(
cfg
.
use
(
AF_INET
,
"eth1/192.0.2.3"
));
ASSERT_THROW
(
cfg
.
use
(
AF_INET
,
"eth1/192.0.2.5"
),
DuplicateIfaceName
);
// Open sockets on specified interfaces and addresses.
cfg
.
openSockets
(
AF_INET
,
DHCP4_SERVER_PORT
);
EXPECT_TRUE
(
socketOpen
(
"eth0"
,
"10.0.0.1"
));
EXPECT_TRUE
(
socketOpen
(
"eth1"
,
"192.0.2.3"
));
EXPECT_FALSE
(
socketOpen
(
"eth1"
,
"192.0.2.5"
));
// Close all sockets and make sure they are really closed.
cfg
.
closeSockets
();
ASSERT_FALSE
(
socketOpen
(
"eth0"
,
"10.0.0.1"
));
ASSERT_FALSE
(
socketOpen
(
"eth1"
,
"192.0.2.3"
));
ASSERT_FALSE
(
socketOpen
(
"eth1"
,
"192.0.2.5"
));
// Now check that the socket can be bound to a different address on
// eth1.
ASSERT_NO_THROW
(
cfg
.
use
(
AF_INET
,
"eth1/192.0.2.5"
));
ASSERT_THROW
(
cfg
.
use
(
AF_INET
,
"eth1/192.0.2.3"
),
DuplicateIfaceName
);
EXPECT_FALSE
(
socketOpen
(
"eth0"
,
"10.0.0.1"
));
EXPECT_FALSE
(
socketOpen
(
"eth1"
,
"192.0.2.3"
));
EXPECT_TRUE
(
socketOpen
(
"eth1"
,
"192.0.2.5"
));
}
// This test checks that the interface names can be explicitly selected
...
...
@@ -118,7 +166,7 @@ TEST_F(CfgIfaceTest, explicitNamesV6) {
EXPECT_TRUE
(
socketOpen
(
"eth1"
,
AF_INET6
));
EXPECT_FALSE
(
socketOpen
(
"lo"
,
AF_INET6
));
// No IPv4 sockets should be present because we wanted IPv
4
sockets.
// No IPv4 sockets should be present because we wanted IPv
6
sockets.
EXPECT_FALSE
(
socketOpen
(
"eth0"
,
AF_INET
));
EXPECT_FALSE
(
socketOpen
(
"eth1"
,
AF_INET
));
EXPECT_FALSE
(
socketOpen
(
"lo"
,
AF_INET
));
...
...
Write
Preview
Supports
Markdown
0%