Commit f8487b56 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3195] Initial support for unicast added.

parent 5eede0e0
......@@ -450,6 +450,9 @@ This debug message indicates that a shutdown of the IPv6 server has
been requested via a call to the 'shutdown' method of the core Dhcpv6Srv
object.
% DHCP6_SOCKET_UNICAST server is about to open socket on address %1 on interface %2
This is a debug message that inform that a unicast socket will be opened.
% DHCP6_SRV_CONSTRUCT_ERROR error creating Dhcpv6Srv object, reason: %1
This error message indicates that during startup, the construction of a
core component within the IPv6 DHCP server (the Dhcpv6 server object)
......
......@@ -2242,6 +2242,16 @@ Dhcpv6Srv::openActiveSockets(const uint16_t port) {
iface_ptr->inactive6_ = true;
}
iface_ptr->clearUnicasts();
const IOAddress* unicast = CfgMgr::instance().getUnicast(iface->getName());
if (unicast) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, 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.
......
......@@ -368,6 +368,20 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
continue;
}
// Open unicast sockets if there are any unicast addresses defined
Iface::AddressCollection unicasts = iface->getUnicasts();
for (Iface::AddressCollection::iterator addr = unicasts.begin();
addr != unicasts.end(); ++addr) {
sock = openSocket(iface->getName(), *addr, port);
if (sock < 0) {
isc_throw(SocketConfigError, "failed to open unicast socket");
}
count++;
}
Iface::AddressCollection addrs = iface->getAddresses();
for (Iface::AddressCollection::iterator addr = addrs.begin();
addr != addrs.end();
......
......@@ -264,6 +264,18 @@ public:
/// @return collection of sockets added to interface
const SocketCollection& getSockets() const { return sockets_; }
void clearUnicasts() {
unicasts_.clear();
}
void addUnicast(const isc::asiolink::IOAddress& addr) {
unicasts_.push_back(addr);
}
const AddressCollection& getUnicasts() const {
return unicasts_;
}
protected:
/// Socket used to send data.
SocketCollection sockets_;
......@@ -277,6 +289,9 @@ protected:
/// List of assigned addresses.
AddressCollection addrs_;
/// List of unicast addresses the server should listen on
AddressCollection unicasts_;
/// Link-layer address.
uint8_t mac_[MAX_MAC_LEN];
......
......@@ -16,6 +16,7 @@
#include <dhcp/libdhcp++.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <string>
using namespace isc::asiolink;
using namespace isc::util;
......@@ -268,7 +269,23 @@ std::string CfgMgr::getDataDir() {
}
void
CfgMgr::addActiveIface(const std::string& iface) {
CfgMgr::addActiveIface(std::string iface) {
size_t pos = iface.find("/");
if (pos != std::string::npos) {
std::string addr_string = iface.substr(pos + 1);
try {
IOAddress addr(addr_string);
iface = iface.substr(0,pos);
unicast_addrs_.insert(make_pair(iface, addr));
} catch (...) {
isc_throw(BadValue, "Can't convert '" << addr_string
<< "' into address in interface defition ('"
<< iface << "')");
}
}
if (isIfaceListedActive(iface)) {
isc_throw(DuplicateListeningIface,
"attempt to add duplicate interface '" << iface << "'"
......@@ -292,6 +309,8 @@ CfgMgr::deleteActiveIfaces() {
DHCPSRV_CFGMGR_CLEAR_ACTIVE_IFACES);
active_ifaces_.clear();
all_ifaces_active_ = false;
unicast_addrs_.clear();
}
bool
......@@ -319,6 +338,15 @@ CfgMgr::isIfaceListedActive(const std::string& iface) const {
return (false);
}
const isc::asiolink::IOAddress*
CfgMgr::getUnicast(const std::string& iface) const {
UnicastIfacesCollection::const_iterator addr = unicast_addrs_.find(iface);
if (addr == unicast_addrs_.end()) {
return (NULL);
}
return (&(*addr).second);
}
CfgMgr::CfgMgr()
: datadir_(DHCP_DATA_DIR),
all_ifaces_active_(false) {
......
......@@ -272,7 +272,7 @@ public:
/// server should listen.
///
/// @param iface A name of the interface being added to the listening set.
void addActiveIface(const std::string& iface);
void addActiveIface(std::string iface);
/// @brief Sets the flag which indicates that server is supposed to listen
/// on all available interfaces.
......@@ -305,6 +305,15 @@ public:
/// interfaces on which server is configured to listen.
bool isActiveIface(const std::string& iface) const;
/// @brief returns unicast a given interface should listen on (or NULL)
///
/// This method will return an address for a specified interface, if the
/// server is supposed to listen on.
///
/// @return IOAddress pointer (or NULL if none)
const isc::asiolink::IOAddress*
getUnicast(const std::string& iface) const;
protected:
/// @brief Protected constructor.
......@@ -372,6 +381,12 @@ private:
std::list<std::string> active_ifaces_;
//@}
/// @name a collection of unicast addresses and the interfaces names the
// server is supposed to listen on
//@{
typedef std::map<std::string, isc::asiolink::IOAddress> UnicastIfacesCollection;
UnicastIfacesCollection unicast_addrs_;
/// A flag which indicates that server should listen on all available
/// interfaces.
bool all_ifaces_active_;
......
......@@ -231,6 +231,7 @@ InterfaceListConfigParser::commit() {
bool
InterfaceListConfigParser::isIfaceAdded(const std::string& iface) const {
for (IfaceListStorage::const_iterator it = interfaces_.begin();
it != interfaces_.end(); ++it) {
if (iface == *it) {
......
......@@ -593,6 +593,41 @@ TEST_F(CfgMgrTest, addActiveIface) {
EXPECT_FALSE(cfg_mgr.isActiveIface("eth2"));
}
// This test verifies that it is possible to specify interfaces that server
// should listen on.
TEST_F(CfgMgrTest, addUnicastAddresses) {
CfgMgr& cfg_mgr = CfgMgr::instance();
cfg_mgr.addActiveIface("eth1/2001:db8::1");
cfg_mgr.addActiveIface("eth2/2001:db8::2");
cfg_mgr.addActiveIface("eth3");
EXPECT_TRUE(cfg_mgr.isActiveIface("eth1"));
EXPECT_TRUE(cfg_mgr.isActiveIface("eth2"));
EXPECT_TRUE(cfg_mgr.isActiveIface("eth3"));
EXPECT_FALSE(cfg_mgr.isActiveIface("eth4"));
ASSERT_TRUE(cfg_mgr.getUnicast("eth1"));
EXPECT_EQ("2001:db8::1", cfg_mgr.getUnicast("eth1")->toText());
EXPECT_EQ("2001:db8::2", cfg_mgr.getUnicast("eth2")->toText());
EXPECT_FALSE(cfg_mgr.getUnicast("eth3"));
EXPECT_FALSE(cfg_mgr.getUnicast("eth4"));
cfg_mgr.deleteActiveIfaces();
EXPECT_FALSE(cfg_mgr.isActiveIface("eth1"));
EXPECT_FALSE(cfg_mgr.isActiveIface("eth2"));
EXPECT_FALSE(cfg_mgr.isActiveIface("eth3"));
EXPECT_FALSE(cfg_mgr.isActiveIface("eth4"));
ASSERT_FALSE(cfg_mgr.getUnicast("eth1"));
ASSERT_FALSE(cfg_mgr.getUnicast("eth2"));
EXPECT_FALSE(cfg_mgr.getUnicast("eth3"));
EXPECT_FALSE(cfg_mgr.getUnicast("eth4"));
}
// This test verifies that it is possible to set the flag which configures the
// server to listen on all interfaces.
TEST_F(CfgMgrTest, activateAllIfaces) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment