mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 04:57:52 +00:00
[4106] Ported DHCPv4-over-DHCPv6 IPC code from fd4o6 private branch
This commit is contained in:
parent
104187287c
commit
89c8c17a16
@ -62,6 +62,7 @@ libdhcp4_la_SOURCES += ctrl_dhcp4_srv.cc ctrl_dhcp4_srv.h
|
||||
libdhcp4_la_SOURCES += json_config_parser.cc json_config_parser.h
|
||||
libdhcp4_la_SOURCES += dhcp4_log.cc dhcp4_log.h
|
||||
libdhcp4_la_SOURCES += dhcp4_srv.cc dhcp4_srv.h
|
||||
libdhcp4_la_SOURCES += dhcp4_dhcp4o6_ipc.cc dhcp4_dhcp4o6_ipc.h
|
||||
|
||||
libdhcp4_la_SOURCES += kea_controller.cc
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <cc/data.h>
|
||||
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||
#include <dhcp4/dhcp4_log.h>
|
||||
#include <dhcp4/dhcp4_dhcp4o6_ipc.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
#include <dhcp4/json_config_parser.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
@ -185,6 +186,16 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
|
||||
return (isc::config::createAnswer(1, err.str()));
|
||||
}
|
||||
|
||||
// Setup DHCPv4-over-DHCPv6 IPC
|
||||
try {
|
||||
Dhcp4o6Ipc::instance().open();
|
||||
} catch (const std::exception& ex) {
|
||||
std::ostringstream err;
|
||||
err << "error starting DHCPv4-over-DHCPv6 IPC "
|
||||
" after server reconfiguration: " << ex.what();
|
||||
return (isc::config::createAnswer(1, err.str()));
|
||||
}
|
||||
|
||||
// Configuration may change active interfaces. Therefore, we have to reopen
|
||||
// sockets according to new configuration. It is possible that this
|
||||
// operation will fail for some interfaces but the openSockets function
|
||||
|
76
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc
Normal file
76
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <util/buffer.h>
|
||||
#include <dhcp/iface_mgr.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <dhcp4/dhcp4_dhcp4o6_ipc.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
Dhcp4o6Ipc::Dhcp4o6Ipc() : Dhcp4o6IpcBase() {}
|
||||
|
||||
Dhcp4o6Ipc& Dhcp4o6Ipc::instance() {
|
||||
static Dhcp4o6Ipc dhcp4o6_ipc;
|
||||
return (dhcp4o6_ipc);
|
||||
}
|
||||
|
||||
void Dhcp4o6Ipc::open() {
|
||||
uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
|
||||
if (port == 0) {
|
||||
Dhcp4o6IpcBase::close();
|
||||
return;
|
||||
}
|
||||
if (port > 65534) {
|
||||
isc_throw(OutOfRange, "DHCP4o6 port " << port);
|
||||
}
|
||||
|
||||
int old_fd = socket_fd_;
|
||||
socket_fd_ = Dhcp4o6IpcBase::open(static_cast<uint16_t>(port), 4);
|
||||
if ((old_fd == -1) && (socket_fd_ != old_fd)) {
|
||||
IfaceMgr::instance().addExternalSocket(socket_fd_, Dhcp4o6Ipc::handler);
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcp4o6Ipc::handler() {
|
||||
Dhcp4o6Ipc& ipc = Dhcp4o6Ipc::instance();
|
||||
Pkt6Ptr pkt = ipc.receive();
|
||||
if (!pkt) {
|
||||
return;
|
||||
}
|
||||
|
||||
pkt->unpack();
|
||||
OptionCollection msgs = pkt->getOptions(D6O_DHCPV4_MSG);
|
||||
if (msgs.size() != 1) {
|
||||
return;
|
||||
}
|
||||
OptionPtr msg = pkt->getOption(D6O_DHCPV4_MSG);
|
||||
if (!msg) {
|
||||
isc_throw(Unexpected, "Can't get DHCPv4 message option");
|
||||
}
|
||||
instance().received_.reset(new Pkt4o6(msg->getData(), pkt));
|
||||
}
|
||||
|
||||
Pkt4o6Ptr& Dhcp4o6Ipc::getReceived() {
|
||||
return (received_);
|
||||
}
|
||||
|
||||
}; // namespace dhcp
|
||||
|
||||
}; // namespace isc
|
74
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h
Normal file
74
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCP4_DHCP4O6_IPC_H
|
||||
#define DHCP4_DHCP4O6_IPC_H
|
||||
|
||||
/// @file dhcp4_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class.
|
||||
/// This file defines the class Kea uses to act as the DHCPv4 server
|
||||
/// side of DHCPv4-over-DHCPv6 communication between servers.
|
||||
///
|
||||
|
||||
#include <dhcp/pkt4o6.h>
|
||||
#include <dhcpsrv/dhcp4o6_ipc.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side
|
||||
class Dhcp4o6Ipc : public Dhcp4o6IpcBase {
|
||||
protected:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// Default constructor
|
||||
Dhcp4o6Ipc();
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~Dhcp4o6Ipc() { }
|
||||
|
||||
public:
|
||||
/// @brief Returns pointer to the sole instance of Dhcp4o6Ipc
|
||||
///
|
||||
/// Dhcp4o6Ipc is a singleton class
|
||||
///
|
||||
/// @return the only existing instance of DHCP4o6 IPC
|
||||
static Dhcp4o6Ipc& instance();
|
||||
|
||||
/// @brief Open communication socket
|
||||
///
|
||||
/// Call base open method and sets the handler/callback when needed
|
||||
virtual void open();
|
||||
|
||||
/// @brief On receive handler
|
||||
///
|
||||
/// The handler processes the DHCPv4-query DHCPv6 packet and
|
||||
/// sends the DHCPv4-response DHCPv6 packet back to the DHCPv6 server
|
||||
static void handler();
|
||||
|
||||
/// @brief Returns last received packet
|
||||
///
|
||||
/// @return a reference to a shared pointer to the last received packet
|
||||
/// @note This reference should be cleared after use
|
||||
Pkt4o6Ptr& getReceived();
|
||||
|
||||
private:
|
||||
/// @brief last received packet
|
||||
Pkt4o6Ptr received_;
|
||||
};
|
||||
|
||||
} // namespace isc
|
||||
} // namespace dhcp
|
||||
|
||||
#endif
|
@ -373,15 +373,16 @@ namespace dhcp {
|
||||
/// @return parser for specified global DHCPv4 parameter
|
||||
/// @throw NotImplemented if trying to create a parser for unknown
|
||||
/// config element
|
||||
DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
|
||||
ConstElementPtr element) {
|
||||
DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
|
||||
ConstElementPtr element) {
|
||||
DhcpConfigParser* parser = NULL;
|
||||
if ((config_id.compare("valid-lifetime") == 0) ||
|
||||
(config_id.compare("renew-timer") == 0) ||
|
||||
(config_id.compare("rebind-timer") == 0) ||
|
||||
(config_id.compare("decline-probation-period") == 0) ) {
|
||||
(config_id.compare("decline-probation-period") == 0) ||
|
||||
(config_id.compare("dhcp4o6-port") == 0) ) {
|
||||
parser = new Uint32Parser(config_id,
|
||||
globalContext()->uint32_values_);
|
||||
globalContext()->uint32_values_);
|
||||
} else if (config_id.compare("interfaces-config") == 0) {
|
||||
parser = new IfacesConfigParser4();
|
||||
} else if (config_id.compare("subnet4") == 0) {
|
||||
@ -423,6 +424,7 @@ namespace dhcp {
|
||||
///
|
||||
/// - echo-client-id
|
||||
/// - decline-probation-period
|
||||
/// - dhcp4o6-port
|
||||
void setGlobalParameters4() {
|
||||
// Although the function is modest for now, it is certain that the number
|
||||
// of global switches will increase over time, hence the name.
|
||||
@ -445,6 +447,15 @@ void setGlobalParameters4() {
|
||||
} catch (...) {
|
||||
// That's not really needed.
|
||||
}
|
||||
|
||||
// Set the DHCPv4-over-DHCPv6 interserver port.
|
||||
try {
|
||||
uint32_t dhcp4o6_port = globalContext()->uint32_values_
|
||||
->getOptionalParam("dhcp4o6-port", 0);
|
||||
CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(dhcp4o6_port);
|
||||
} catch (...) {
|
||||
// Ignore errors. This flag is optional
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
|
@ -63,6 +63,7 @@ libdhcp6_la_SOURCES += dhcp6_log.cc dhcp6_log.h
|
||||
libdhcp6_la_SOURCES += dhcp6_srv.cc dhcp6_srv.h
|
||||
libdhcp6_la_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
|
||||
libdhcp6_la_SOURCES += json_config_parser.cc json_config_parser.h
|
||||
libdhcp6_la_SOURCES += dhcp6_dhcp4o6_ipc.cc dhcp6_dhcp4o6_ipc.h
|
||||
|
||||
libdhcp6_la_SOURCES += kea_controller.cc
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <config/command_mgr.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||
#include <dhcp6/dhcp6_dhcp4o6_ipc.h>
|
||||
#include <dhcp6/dhcp6_log.h>
|
||||
#include <dhcp6/json_config_parser.h>
|
||||
#include <hooks/hooks_manager.h>
|
||||
@ -183,6 +184,16 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
|
||||
return (isc::config::createAnswer(1, err.str()));
|
||||
}
|
||||
|
||||
// Setup DHCPv4-over-DHCPv6 IPC
|
||||
try {
|
||||
Dhcp4o6Ipc::instance().open();
|
||||
} catch (const std::exception& ex) {
|
||||
std::ostringstream err;
|
||||
err << "error starting DHCPv4-over-DHCPv6 IPC "
|
||||
" after server reconfiguration: " << ex.what();
|
||||
return (isc::config::createAnswer(1, err.str()));
|
||||
}
|
||||
|
||||
// Configuration may change active interfaces. Therefore, we have to reopen
|
||||
// sockets according to new configuration. It is possible that this
|
||||
// operation will fail for some interfaces but the openSockets function
|
||||
|
71
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc
Normal file
71
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <util/buffer.h>
|
||||
#include <dhcp/iface_mgr.h>
|
||||
#include <dhcpsrv/cfgmgr.h>
|
||||
#include <dhcp6/dhcp6_dhcp4o6_ipc.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
Dhcp4o6Ipc::Dhcp4o6Ipc() : Dhcp4o6IpcBase() {}
|
||||
|
||||
Dhcp4o6Ipc& Dhcp4o6Ipc::instance() {
|
||||
static Dhcp4o6Ipc dhcp4o6_ipc;
|
||||
return (dhcp4o6_ipc);
|
||||
}
|
||||
|
||||
void Dhcp4o6Ipc::open() {
|
||||
uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
|
||||
if (port == 0) {
|
||||
Dhcp4o6IpcBase::close();
|
||||
return;
|
||||
}
|
||||
if (port > 65534) {
|
||||
isc_throw(OutOfRange, "DHCP4o6 port " << port);
|
||||
}
|
||||
|
||||
int old_fd = socket_fd_;
|
||||
socket_fd_ = Dhcp4o6IpcBase::open(static_cast<uint16_t>(port), 6);
|
||||
if ((old_fd == -1) && (socket_fd_ != old_fd)) {
|
||||
IfaceMgr::instance().addExternalSocket(socket_fd_, Dhcp4o6Ipc::handler);
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcp4o6Ipc::handler() {
|
||||
Dhcp4o6Ipc& ipc = Dhcp4o6Ipc::instance();
|
||||
Pkt6Ptr pkt = ipc.receive();
|
||||
if (!pkt) {
|
||||
return;
|
||||
}
|
||||
isc::util::OutputBuffer& buf = pkt->getBuffer();
|
||||
pkt->repack();
|
||||
uint8_t msg_type = buf[0];
|
||||
if ((msg_type == DHCPV6_RELAY_FORW) || (msg_type == DHCPV6_RELAY_REPL)) {
|
||||
pkt->setRemotePort(DHCP6_SERVER_PORT);
|
||||
} else {
|
||||
pkt->setRemotePort(DHCP6_CLIENT_PORT);
|
||||
}
|
||||
IfaceMgr::instance().send(pkt);
|
||||
// processStatsSent(pkt);
|
||||
}
|
||||
|
||||
}; // namespace dhcp
|
||||
|
||||
}; // namespace isc
|
61
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h
Normal file
61
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCP6_DHCP4O6_IPC_H
|
||||
#define DHCP6_DHCP4O6_IPC_H
|
||||
|
||||
/// @file dhcp6_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class.
|
||||
/// This file defines the class Kea uses to act as the DHCPv6 server
|
||||
/// side of DHCPv4-over-DHCPv6 communication between servers.
|
||||
///
|
||||
#include <dhcpsrv/dhcp4o6_ipc.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv6 server side
|
||||
class Dhcp4o6Ipc : public Dhcp4o6IpcBase {
|
||||
protected:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// Default constructor
|
||||
Dhcp4o6Ipc();
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~Dhcp4o6Ipc() { }
|
||||
|
||||
public:
|
||||
/// @brief Returns pointer to the sole instance of Dhcp4o6Ipc
|
||||
///
|
||||
/// Dhcp4o6Ipc is a singleton class
|
||||
///
|
||||
/// @return the only existing instance of DHCP4o6 IPC
|
||||
static Dhcp4o6Ipc& instance();
|
||||
|
||||
/// @brief Open communication socket
|
||||
///
|
||||
/// Call base open method and sets the handler/callback when needed
|
||||
virtual void open();
|
||||
|
||||
/// @brief On receive handler
|
||||
///
|
||||
/// The handler sends the DHCPv6 packet back to the remote address
|
||||
static void handler();
|
||||
};
|
||||
|
||||
} // namespace isc
|
||||
} // namespace dhcp
|
||||
|
||||
#endif
|
@ -32,6 +32,7 @@
|
||||
#include <dhcp/option_vendor_class.h>
|
||||
#include <dhcp/option_int_array.h>
|
||||
#include <dhcp/pkt6.h>
|
||||
#include <dhcp6/dhcp6_dhcp4o6_ipc.h>
|
||||
#include <dhcp6/dhcp6_log.h>
|
||||
#include <dhcp6/dhcp6_srv.h>
|
||||
#include <dhcpsrv/callout_handle_store.h>
|
||||
@ -239,6 +240,13 @@ Dhcpv6Srv::~Dhcpv6Srv() {
|
||||
LOG_ERROR(dhcp6_logger, DHCP6_SRV_D2STOP_ERROR).arg(ex.what());
|
||||
}
|
||||
|
||||
try {
|
||||
Dhcp4o6Ipc::instance().close();
|
||||
} catch(const std::exception& ex) {
|
||||
// Highly unlikely, but lets Report it but go on
|
||||
// LOG_ERROR(dhcp6_logger, DHCP6_SRV_DHCP4O6_ERROR).arg(ex.what());
|
||||
}
|
||||
|
||||
IfaceMgr::instance().closeSockets();
|
||||
|
||||
LeaseMgrFactory::destroy();
|
||||
|
@ -672,7 +672,8 @@ namespace dhcp {
|
||||
(config_id.compare("valid-lifetime") == 0) ||
|
||||
(config_id.compare("renew-timer") == 0) ||
|
||||
(config_id.compare("rebind-timer") == 0) ||
|
||||
(config_id.compare("decline-probation-period") == 0) ) {
|
||||
(config_id.compare("decline-probation-period") == 0) ||
|
||||
(config_id.compare("dhcp4o6-port") == 0) ) {
|
||||
parser = new Uint32Parser(config_id,
|
||||
globalContext()->uint32_values_);
|
||||
} else if (config_id.compare("interfaces-config") == 0) {
|
||||
@ -715,6 +716,7 @@ namespace dhcp {
|
||||
/// Currently this method sets the following global parameters:
|
||||
///
|
||||
/// - decline-probation-period
|
||||
/// - dhcp4o6-port
|
||||
void setGlobalParameters6() {
|
||||
|
||||
// Set the probation period for decline handling.
|
||||
@ -726,6 +728,15 @@ void setGlobalParameters6() {
|
||||
} catch (...) {
|
||||
// That's not really needed.
|
||||
}
|
||||
|
||||
// Set the DHCPv4-over-DHCPv6 interserver port.
|
||||
try {
|
||||
uint32_t dhcp4o6_port = globalContext()->uint32_values_
|
||||
->getOptionalParam("dhcp4o6-port", 0);
|
||||
CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(dhcp4o6_port);
|
||||
} catch (...) {
|
||||
// Ignore errors. This flag is optional
|
||||
}
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
|
25
src/lib/dhcp/dhcp4o6.h
Normal file
25
src/lib/dhcp/dhcp4o6.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCP4O6_H
|
||||
#define DHCP4O6_H
|
||||
|
||||
/* Offsets and sizes into interserver messages. */
|
||||
#define DHCP4O6_IFNAME_OFFSET 0
|
||||
#define DHCP4O6_IFNAME_SIZE 16
|
||||
#define DHCP4O6_RADDR_OFFSET 16
|
||||
#define DHCP4O6_RADDR_SIZE 16
|
||||
#define DHCP4O6_DHCP6_OFFSET 32
|
||||
|
||||
#endif /* DHCP4O6_H */
|
@ -94,6 +94,7 @@ libkea_dhcpsrv_la_SOURCES += d2_client_cfg.cc d2_client_cfg.h
|
||||
libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
|
||||
libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h
|
||||
libkea_dhcpsrv_la_SOURCES += database_connection.cc database_connection.h
|
||||
libkea_dhcpsrv_la_SOURCES += dhcp4o6_ipc.cc dhcp4o6_ipc.h
|
||||
libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h
|
||||
libkea_dhcpsrv_la_SOURCES += host.cc host.h
|
||||
libkea_dhcpsrv_la_SOURCES += host_container.h
|
||||
|
206
src/lib/dhcpsrv/dhcp4o6_ipc.cc
Normal file
206
src/lib/dhcpsrv/dhcp4o6_ipc.cc
Normal file
@ -0,0 +1,206 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dhcp/dhcp4o6.h>
|
||||
#include <dhcp/iface_mgr.h>
|
||||
#include <dhcpsrv/dhcp4o6_ipc.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <string>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::util;
|
||||
using namespace std;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
Dhcp4o6IpcBase::Dhcp4o6IpcBase() : port_(0), socket_fd_(-1) {}
|
||||
|
||||
Dhcp4o6IpcBase::~Dhcp4o6IpcBase() {
|
||||
close();
|
||||
}
|
||||
|
||||
int Dhcp4o6IpcBase::open(uint16_t port, int side) {
|
||||
if (port == port_) {
|
||||
// No change: nothing to do
|
||||
return (socket_fd_);
|
||||
}
|
||||
|
||||
// Port 0: closing
|
||||
if (port == 0) {
|
||||
port_ = 0;
|
||||
if (socket_fd_ != -1) {
|
||||
IfaceMgr::instance().deleteExternalSocket(socket_fd_);
|
||||
::close(socket_fd_);
|
||||
socket_fd_ = -1;
|
||||
}
|
||||
return (socket_fd_);
|
||||
}
|
||||
|
||||
// Open socket
|
||||
int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock < 0) {
|
||||
isc_throw(Unexpected, "Failed to create DHCP4o6 socket.");
|
||||
}
|
||||
|
||||
// Set reuse address
|
||||
int flag = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&flag, sizeof(flag)) < 0) {
|
||||
::close(sock);
|
||||
isc_throw(Unexpected, "Failed to set SO_REUSEADDR on DHCP4o6 socket.");
|
||||
}
|
||||
|
||||
// Set no blocking
|
||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
|
||||
::close(sock);
|
||||
isc_throw(Unexpected, "Failed to set O_NONBLOCK on DHCP4o6 socket.");
|
||||
}
|
||||
|
||||
// Bind to the local address
|
||||
struct sockaddr_in6 local6;
|
||||
memset(&local6, 0, sizeof(local6));
|
||||
local6.sin6_family = AF_INET6;
|
||||
#ifdef HAVE_SA_LEN
|
||||
local6.sin6_len = sizeof(local6);
|
||||
#endif
|
||||
if (side == 6) {
|
||||
local6.sin6_port = htons(port);
|
||||
} else {
|
||||
local6.sin6_port = htons(port + 1);
|
||||
}
|
||||
if (bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) {
|
||||
::close(sock);
|
||||
isc_throw(Unexpected, "Failed to bind DHCP4o6 socket.");
|
||||
}
|
||||
|
||||
// Connect to the remote address
|
||||
struct sockaddr_in6 remote6;
|
||||
memset(&remote6, 0, sizeof(remote6));
|
||||
remote6.sin6_family = AF_INET6;
|
||||
#ifdef HAVE_SA_LEN
|
||||
remote6.sin6_len = sizeof(remote6);
|
||||
#endif
|
||||
if (side == 6) {
|
||||
remote6.sin6_port = htons(port + 1);
|
||||
} else {
|
||||
remote6.sin6_port = htons(port);
|
||||
}
|
||||
if (connect(sock, (struct sockaddr *)&remote6, sizeof(remote6)) < 0) {
|
||||
::close(sock);
|
||||
isc_throw(Unexpected, "Failed to connect DHCP4o6 socket.");
|
||||
}
|
||||
|
||||
if (socket_fd_ != -1) {
|
||||
if (dup2(sock, socket_fd_) == -1) {
|
||||
::close(sock);
|
||||
isc_throw(Unexpected, "Failed to duplicate DHCP4o6 socket.");
|
||||
}
|
||||
if (sock != socket_fd_) {
|
||||
::close(sock);
|
||||
sock = socket_fd_;
|
||||
}
|
||||
}
|
||||
|
||||
// Success
|
||||
port_ = port;
|
||||
socket_fd_ = sock;
|
||||
return (socket_fd_);
|
||||
}
|
||||
|
||||
void Dhcp4o6IpcBase::close() {
|
||||
static_cast<void>(open(0, 0));
|
||||
}
|
||||
|
||||
Pkt6Ptr Dhcp4o6IpcBase::receive() {
|
||||
uint8_t buf[65536];
|
||||
ssize_t cc = recv(socket_fd_, buf, sizeof(buf), 0);
|
||||
if (cc < 0) {
|
||||
isc_throw(Unexpected, "Failed to receive on DHCP4o6 socket.");
|
||||
}
|
||||
if (cc < DHCP4O6_DHCP6_OFFSET + Pkt6::DHCPV6_PKT_HDR_LEN) {
|
||||
// Ignore too short messages
|
||||
return (Pkt6Ptr());
|
||||
}
|
||||
char name[DHCP4O6_IFNAME_SIZE + 1];
|
||||
memcpy(name, buf, DHCP4O6_IFNAME_SIZE);
|
||||
IfacePtr iface = IfaceMgr::instance().getIface(string(name));
|
||||
if (!iface) {
|
||||
// Can't get the interface: ignore
|
||||
return (Pkt6Ptr());
|
||||
}
|
||||
uint8_t raddr[DHCP4O6_RADDR_SIZE];
|
||||
memcpy(raddr, buf + DHCP4O6_RADDR_OFFSET, DHCP4O6_RADDR_SIZE);
|
||||
IOAddress from = IOAddress::fromBytes(AF_INET6, raddr);
|
||||
Pkt6Ptr pkt;
|
||||
pkt = Pkt6Ptr(new Pkt6(buf + DHCP4O6_DHCP6_OFFSET,
|
||||
cc - DHCP4O6_DHCP6_OFFSET));
|
||||
pkt->updateTimestamp();
|
||||
pkt->setRemoteAddr(from);
|
||||
pkt->setIface(iface->getName());
|
||||
pkt->setIndex(iface->getIndex());
|
||||
return (pkt);
|
||||
}
|
||||
|
||||
void Dhcp4o6IpcBase::send(Pkt6Ptr pkt) {
|
||||
// No packet: nothing to send
|
||||
if (!pkt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disabled: nowhere to send
|
||||
if (socket_fd_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get interface name
|
||||
string name = pkt->getIface();
|
||||
if (name.empty() || name.size() > DHCP4O6_IFNAME_SIZE) {
|
||||
// Bad interface name: ignore
|
||||
return;
|
||||
}
|
||||
name.resize(DHCP4O6_IFNAME_SIZE);
|
||||
|
||||
// Get remote address
|
||||
IOAddress from = pkt->getRemoteAddr();
|
||||
vector<uint8_t> raddr = from.toBytes();
|
||||
if (raddr.size() != DHCP4O6_RADDR_SIZE) {
|
||||
// Bad remote address: ignore
|
||||
return;
|
||||
}
|
||||
|
||||
// Get packet content
|
||||
OutputBuffer& pbuf = pkt->getBuffer();
|
||||
if (!pbuf.getLength()) {
|
||||
// Empty buffer: content is not (yet) here, get it
|
||||
pkt->repack();
|
||||
}
|
||||
|
||||
// Fill buffer
|
||||
vector<uint8_t> buf(DHCP4O6_DHCP6_OFFSET + pbuf.getLength());
|
||||
memcpy(&buf[0], name.c_str(), DHCP4O6_IFNAME_SIZE);
|
||||
memcpy(&buf[0] + DHCP4O6_RADDR_OFFSET, &raddr[0], DHCP4O6_RADDR_SIZE);
|
||||
memcpy(&buf[0] + DHCP4O6_DHCP6_OFFSET, pbuf.getData(), pbuf.getLength());
|
||||
|
||||
// Send
|
||||
static_cast<void>(::send(socket_fd_, &buf[0], buf.size(), 0));
|
||||
return;
|
||||
}
|
||||
|
||||
}; // namespace dhcp
|
||||
|
||||
}; // namespace isc
|
81
src/lib/dhcpsrv/dhcp4o6_ipc.h
Normal file
81
src/lib/dhcpsrv/dhcp4o6_ipc.h
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (C) 2015 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
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef DHCP4O6_IPC_H
|
||||
#define DHCP4O6_IPC_H
|
||||
|
||||
/// @file dhcp4o6_ipc.h Defines the Dhcp4o6IpcBase class.
|
||||
/// This file defines the class Kea uses as a base for
|
||||
/// DHCPv4-over-DHCPv6 communication between servers.
|
||||
///
|
||||
#include <dhcp/pkt6.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief
|
||||
///
|
||||
class Dhcp4o6IpcBase : public boost::noncopyable {
|
||||
protected:
|
||||
/// @brief Constructor
|
||||
///
|
||||
/// Default constructor
|
||||
Dhcp4o6IpcBase();
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~Dhcp4o6IpcBase();
|
||||
|
||||
/// @brief Open communication socket (from base class)
|
||||
///
|
||||
/// @param port port number to use (0 for disabled)
|
||||
/// @param side side of the server (4 or 6)
|
||||
///
|
||||
/// @return new socket descriptor
|
||||
int open(uint16_t port, int side);
|
||||
|
||||
public:
|
||||
/// @brief Open communication socket (for derived classes)
|
||||
virtual void open() = 0;
|
||||
|
||||
/// @brief Close communication socket
|
||||
void close();
|
||||
|
||||
/// @brief Receive IPC message
|
||||
///
|
||||
/// @return a pointer to a DHCPv6 message with interface and remote
|
||||
/// address set from the IPC message
|
||||
Pkt6Ptr receive();
|
||||
|
||||
/// @brief Send IPC message
|
||||
///
|
||||
/// @param a pointer to a DHCPv6 message with interface and remote
|
||||
/// address set for the IPC message
|
||||
void send(Pkt6Ptr pkt);
|
||||
|
||||
protected:
|
||||
/// @brief Port number
|
||||
uint16_t port_;
|
||||
|
||||
/// @brief Socket descriptor
|
||||
int socket_fd_;
|
||||
};
|
||||
|
||||
} // namespace isc
|
||||
} // namespace dhcp
|
||||
|
||||
#endif
|
@ -32,7 +32,7 @@ SrvConfig::SrvConfig()
|
||||
cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
|
||||
cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
|
||||
cfg_expiration_(new CfgExpiration()),
|
||||
decline_timer_(0) {
|
||||
decline_timer_(0), dhcp4o6_port_(0) {
|
||||
}
|
||||
|
||||
SrvConfig::SrvConfig(const uint32_t sequence)
|
||||
@ -41,7 +41,7 @@ SrvConfig::SrvConfig(const uint32_t sequence)
|
||||
cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
|
||||
cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
|
||||
cfg_expiration_(new CfgExpiration()),
|
||||
decline_timer_(0) {
|
||||
decline_timer_(0), dhcp4o6_port_(0) {
|
||||
}
|
||||
|
||||
std::string
|
||||
|
@ -407,6 +407,24 @@ public:
|
||||
return (decline_timer_);
|
||||
}
|
||||
|
||||
/// @brief Sets DHCP4o6 IPC port
|
||||
///
|
||||
/// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication,
|
||||
/// this socket is bound and connected to this port and port + 1
|
||||
///
|
||||
/// @param port port and port + 1 to use
|
||||
void setDhcp4o6Port(uint32_t port) {
|
||||
dhcp4o6_port_ = port;
|
||||
}
|
||||
|
||||
/// @brief Returns DHCP4o6 IPC port
|
||||
///
|
||||
/// See @ref setDhcp4o6Port or brief discussion.
|
||||
/// @return value of DHCP4o6 IPC port
|
||||
uint32_t getDhcp4o6Port() {
|
||||
return (dhcp4o6_port_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// @brief Sequence number identifying the configuration.
|
||||
@ -466,6 +484,12 @@ private:
|
||||
/// This timer specifies decline probation period, the time after a declined
|
||||
/// lease is recovered back to available state. Expressed in seconds.
|
||||
uint32_t decline_timer_;
|
||||
|
||||
/// @brief DHCP4o6 IPC port
|
||||
///
|
||||
/// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication,
|
||||
/// this socket is bound and connected to this port and port + 1
|
||||
uint32_t dhcp4o6_port_;
|
||||
};
|
||||
|
||||
/// @name Pointers to the @c SrvConfig object.
|
||||
|
Loading…
x
Reference in New Issue
Block a user