Commit 7d36aebe authored by Francis Dupont's avatar Francis Dupont
Browse files

[master] Merge trac4110a (DHCP4o6 v4 server part)

parents dedda6a3 923242ca
......@@ -198,6 +198,41 @@ detected as a duplicate (i.e. another device in the network is using this addres
However, the server does not have a record for this address. This may indicate
a client's error or a server's purged database.
% DHCP4_DHCP4O6_BAD_PACKET received malformed DHCPv4o6 packet: %1
A malformed DHCPv4o6 packet was received.
% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv6 server (type %1) for %2 on interface %3
This debug message is printed when the server is receiving a DHCPv4o6
from the DHCPv6 server over inter-process communication.
% DHCP4_DHCP4O6_PACKET_SEND %1: trying to send packet %2 (type %3) to %4 on interface %5 encapsulating %6: %7 (type %8)
The arguments specify the client identification information (HW address
and client identifier), DHCPv6 message name and type, source IPv6
address and interface name, DHCPv4 client identification, message
name and type.
% DHCP4_DHCP4O6_PACKET_SEND_FAIL %1: failed to send DHCPv4o6 packet: %2
This error is output if the IPv4 DHCP server fails to send an
DHCPv4o6 message to the IPv6 DHCP server. The reason for the
error is included in the message.
% DHCP4_DHCP4O6_RECEIVE_FAIL failed to receive DHCPv4o6: %1
This debug message indicates the inter-process communication with the
DHCPv6 server failed. The reason for the error is included in
the message.
% DHCP4_DHCP4O6_RECEIVING receiving DHCPv4o6 packet from DHCPv6 server
This debug message is printed when the server is receiving a DHCPv4o6
from the DHCPv6 server over inter-process communication socket.
% DHCP4_DHCP4O6_RESPONSE_DATA %1: responding with packet %2 (type %3), packet details: %4
A debug message including the detailed data about the packet being
sent to the DHCPv6 server to be forwarded to the client. The first
argument contains the client and the transaction identification
information. The second and third argument contains the packet name
and type respectively. The fourth argument contains detailed packet
information.
% DHCP4_DISCOVER_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPDISCOVER
This debug message means that the server processing that is unique for each
client class has reported a failure. The response packet will not be sent.
......@@ -641,6 +676,12 @@ stopping IO between the DHCPv4 server and the DHCP_DDNS server. This is
probably due to a programmatic error is not likely to impact either server
upon restart. The reason for the failure is given within the message.
% DHCP4_SRV_DHCP4O6_ERROR error stopping IO with DHCPv4o6 during shutdown: %1
This error message indicates that during shutdown, an error occurred while
stopping IO between the DHCPv4 server and the DHCPv6o6 server. This is
probably due to a programmatic error is not likely to impact either server
upon restart. The reason for the failure is given within the message.
% DHCP4_STARTED Kea DHCPv4 server version %1 started
This informational message indicates that the DHCPv4 server has
processed all configuration information and is ready to process
......
......@@ -16,7 +16,10 @@
#include <dhcp/option_vendor.h>
#include <dhcp/option_string.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt4o6.h>
#include <dhcp/pkt6.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp4/dhcp4to6_ipc.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/dhcp4_srv.h>
#include <dhcpsrv/addr_utilities.h>
......@@ -173,7 +176,31 @@ Dhcpv4Exchange::initResponse() {
resp_.reset(new Pkt4(resp_type, getQuery()->getTransid()));
copyDefaultFields();
copyDefaultOptions();
if (getQuery()->isDhcp4o6()) {
initResponse4o6();
}
}
}
void
Dhcpv4Exchange::initResponse4o6() {
Pkt4o6Ptr query = boost::dynamic_pointer_cast<Pkt4o6>(getQuery());
if (!query) {
return;
}
const Pkt6Ptr& query6 = query->getPkt6();
Pkt6Ptr resp6(new Pkt6(DHCPV6_DHCPV4_RESPONSE, query6->getTransid()));
// Don't add client-id or server-id
// But copy relay info
if (!query6->relay_info_.empty()) {
resp6->copyRelayInfo(query6);
}
// Copy interface and remote address
resp6->setIface(query6->getIface());
resp6->setIndex(query6->getIndex());
resp6->setRemoteAddr(query6->getRemoteAddr());
resp_.reset(new Pkt4o6(resp_, resp6));
}
void
......@@ -311,8 +338,7 @@ const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const bool use_bcast,
const bool direct_response_desired)
: shutdown_(true), alloc_engine_(), port_(port),
use_bcast_(use_bcast), hook_index_pkt4_receive_(-1),
hook_index_subnet4_select_(-1), hook_index_pkt4_send_(-1) {
use_bcast_(use_bcast) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_OPEN_SOCKET).arg(port);
try {
......@@ -336,11 +362,6 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const bool use_bcast,
alloc_engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 0,
false /* false = IPv4 */));
// Register hook points
hook_index_pkt4_receive_ = Hooks.hook_index_pkt4_receive_;
hook_index_subnet4_select_ = Hooks.hook_index_subnet4_select_;
hook_index_pkt4_send_ = Hooks.hook_index_pkt4_send_;
/// @todo call loadLibraries() when handling configuration changes
} catch (const std::exception &e) {
......@@ -360,6 +381,13 @@ Dhcpv4Srv::~Dhcpv4Srv() {
LOG_ERROR(dhcp4_logger, DHCP4_SRV_D2STOP_ERROR).arg(ex.what());
}
try {
Dhcp4to6Ipc::instance().close();
} catch(const std::exception& ex) {
// Highly unlikely, but lets Report it but go on
LOG_ERROR(dhcp4_logger, DHCP4_SRV_DHCP4O6_ERROR).arg(ex.what());
}
IfaceMgr::instance().closeSockets();
// The lease manager was instantiated during DHCPv4Srv configuration,
......@@ -379,6 +407,11 @@ Dhcpv4Srv::shutdown() {
isc::dhcp::Subnet4Ptr
Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
// DHCPv4-over-DHCPv6 is a special (and complex) case
if (query->isDhcp4o6()) {
return (selectSubnet4o6(query));
}
Subnet4Ptr subnet;
SubnetSelector selector;
......@@ -428,7 +461,111 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
// Let's execute all callouts registered for subnet4_select
if (HooksManager::calloutsPresent(hook_index_subnet4_select_)) {
if (HooksManager::calloutsPresent(Hooks.hook_index_subnet4_select_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// We're reusing callout_handle from previous calls
callout_handle->deleteAllArguments();
// Set new arguments
callout_handle->setArgument("query4", query);
callout_handle->setArgument("subnet4", subnet);
callout_handle->setArgument("subnet4collection",
cfgmgr.getCurrentCfg()->
getCfgSubnets4()->getAll());
// Call user (and server-side) callouts
HooksManager::callCallouts(Hooks.hook_index_subnet4_select_,
*callout_handle);
// Callouts decided to skip this step. This means that no subnet
// will be selected. Packet processing will continue, but it will
// be severely limited (i.e. only global options will be assigned)
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
DHCP4_HOOK_SUBNET4_SELECT_SKIP)
.arg(query->getLabel());
return (Subnet4Ptr());
}
/// @todo: Add support for DROP status
// Use whatever subnet was specified by the callout
callout_handle->getArgument("subnet4", subnet);
}
if (subnet) {
// Log at higher debug level that subnet has been found.
LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC_DATA, DHCP4_SUBNET_SELECTED)
.arg(query->getLabel())
.arg(subnet->getID());
// Log detailed information about the selected subnet at the
// lower debug level.
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_SUBNET_DATA)
.arg(query->getLabel())
.arg(subnet->toText());
} else {
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL,
DHCP4_SUBNET_SELECTION_FAILED)
.arg(query->getLabel());
}
return (subnet);
}
isc::dhcp::Subnet4Ptr
Dhcpv4Srv::selectSubnet4o6(const Pkt4Ptr& query) const {
Subnet4Ptr subnet;
SubnetSelector selector;
selector.ciaddr_ = query->getCiaddr();
selector.giaddr_ = query->getGiaddr();
selector.local_address_ = query->getLocalAddr();
selector.client_classes_ = query->classes_;
selector.iface_name_ = query->getIface();
// Mark it as DHCPv4-over-DHCPv6
selector.dhcp4o6_ = true;
// Now the DHCPv6 part
selector.remote_address_ = query->getRemoteAddr();
selector.first_relay_linkaddr_ = IOAddress("::");
// Handle a DHCPv6 relayed query
Pkt4o6Ptr query4o6 = boost::dynamic_pointer_cast<Pkt4o6>(query);
if (!query4o6) {
isc_throw(Unexpected, "Can't get DHCP4o6 message");
}
const Pkt6Ptr& query6 = query4o6->getPkt6();
// Initialize fields specific to relayed messages.
if (query6 && !query6->relay_info_.empty()) {
BOOST_REVERSE_FOREACH(Pkt6::RelayInfo relay, query6->relay_info_) {
if (!relay.linkaddr_.isV6Zero() &&
!relay.linkaddr_.isV6LinkLocal()) {
selector.first_relay_linkaddr_ = relay.linkaddr_;
break;
}
}
selector.interface_id_ =
query6->getAnyRelayOption(D6O_INTERFACE_ID,
Pkt6::RELAY_GET_FIRST);
}
// If the Subnet Selection option is present, extract its value.
OptionPtr sbnsel = query->getOption(DHO_SUBNET_SELECTION);
if (sbnsel) {
OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
if (oc) {
selector.option_select_ = oc->readAddress();
}
}
CfgMgr& cfgmgr = CfgMgr::instance();
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
// Let's execute all callouts registered for subnet4_select
if (HooksManager::calloutsPresent(Hooks.hook_index_subnet4_select_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// We're reusing callout_handle from previous calls
......@@ -442,7 +579,7 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
getCfgSubnets4()->getAll());
// Call user (and server-side) callouts
HooksManager::callCallouts(hook_index_subnet4_select_,
HooksManager::callCallouts(Hooks.hook_index_subnet4_select_,
*callout_handle);
// Callouts decided to skip this step. This means that no subnet
......@@ -751,7 +888,7 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
.arg(query->toText());
// Let's execute all callouts registered for pkt4_receive
if (HooksManager::calloutsPresent(hook_index_pkt4_receive_)) {
if (HooksManager::calloutsPresent(Hooks.hook_index_pkt4_receive_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete previously set arguments
......@@ -761,7 +898,7 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
callout_handle->setArgument("query4", query);
// Call callouts
HooksManager::callCallouts(hook_index_pkt4_receive_,
HooksManager::callCallouts(Hooks.hook_index_pkt4_receive_,
*callout_handle);
// Callouts decided to skip the next processing step. The next
......@@ -837,7 +974,7 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
bool skip_pack = false;
// Execute all callouts registered for pkt4_send
if (HooksManager::calloutsPresent(hook_index_pkt4_send_)) {
if (HooksManager::calloutsPresent(Hooks.hook_index_pkt4_send_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete all previous arguments
......@@ -853,7 +990,7 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
callout_handle->setArgument("query4", query);
// Call all installed callouts
HooksManager::callCallouts(hook_index_pkt4_send_,
HooksManager::callCallouts(Hooks.hook_index_pkt4_send_,
*callout_handle);
// Callouts decided to skip the next processing step. The next
......@@ -1641,7 +1778,8 @@ Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) {
// Instead we will need to use the address assigned to the interface
// on which the query has been received. In other cases, we will just
// use this address as a source address for the response.
if (local_addr.isV4Bcast()) {
// Do the same for DHCPv4-over-DHCPv6 exchanges.
if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
local_addr = sock_info.addr_;
}
......@@ -1673,6 +1811,12 @@ Dhcpv4Srv::adjustRemoteAddr(Dhcpv4Exchange& ex) {
Pkt4Ptr query = ex.getQuery();
Pkt4Ptr response = ex.getResponse();
// DHCPv4-over-DHCPv6 is simple
if (query->isDhcp4o6()) {
response->setRemoteAddr(query->getRemoteAddr());
return;
}
// The DHCPINFORM is slightly different than other messages in a sense
// that the server should always unicast the response to the ciaddr.
// It appears however that some clients don't set the ciaddr. We still
......@@ -2194,6 +2338,12 @@ Dhcpv4Srv::acceptDirectRequest(const Pkt4Ptr& pkt) const {
if (pkt->isRelayed()) {
return (true);
}
// Accept all DHCPv4-over-DHCPv6 messages.
if (pkt->isDhcp4o6()) {
return (true);
}
// The source address must not be zero for the DHCPINFORM message from
// the directly connected client because the server will not know where
// to respond if the ciaddr was not present.
......@@ -2624,5 +2774,33 @@ void Dhcpv4Srv::processStatsSent(const Pkt4Ptr& response) {
static_cast<int64_t>(1));
}
int Dhcpv4Srv::getHookIndexBuffer4Receive() {
return (Hooks.hook_index_buffer4_receive_);
}
int Dhcpv4Srv::getHookIndexPkt4Receive() {
return (Hooks.hook_index_pkt4_receive_);
}
int Dhcpv4Srv::getHookIndexSubnet4Select() {
return (Hooks.hook_index_subnet4_select_);
}
int Dhcpv4Srv::getHookIndexLease4Release() {
return (Hooks.hook_index_lease4_release_);
}
int Dhcpv4Srv::getHookIndexPkt4Send() {
return (Hooks.hook_index_pkt4_send_);
}
int Dhcpv4Srv::getHookIndexBuffer4Send() {
return (Hooks.hook_index_buffer4_send_);
}
int Dhcpv4Srv::getHookIndexLease4Decline() {
return (Hooks.hook_index_lease4_decline_);
}
} // namespace dhcp
} // namespace isc
......@@ -81,6 +81,11 @@ public:
/// response is not initialized.
void initResponse();
/// @brief Initializes the DHCPv6 part of the response message
///
/// Called by initResponse() when the query is a DHCP4o6 message
void initResponse4o6();
/// @brief Returns the pointer to the query from the client.
Pkt4Ptr getQuery() const {
return (query_);
......@@ -713,6 +718,12 @@ protected:
/// @return selected subnet (or NULL if no suitable subnet was found)
isc::dhcp::Subnet4Ptr selectSubnet(const Pkt4Ptr& query) const;
/// @brief Selects a subnet for a given client's DHCP4o6 packet.
///
/// @param query client's message
/// @return selected subnet (or NULL if no suitable subnet was found)
isc::dhcp::Subnet4Ptr selectSubnet4o6(const Pkt4Ptr& query) const;
/// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
volatile bool shutdown_;
......@@ -777,21 +788,47 @@ private:
/// @return Option that contains netmask information
static OptionPtr getNetmaskOption(const Subnet4Ptr& subnet);
uint16_t port_; ///< UDP port number on which server listens.
bool use_bcast_; ///< Should broadcast be enabled on sockets (if true).
public:
/// Class methods for DHCPv4-over-DHCPv6 handler
/// @brief Updates statistics for received packets
/// @param query packet received
static void processStatsReceived(const Pkt4Ptr& query);
/// @brief Updates statistics for transmitted packets
/// @param query packet transmitted
/// @param response packet transmitted
static void processStatsSent(const Pkt4Ptr& response);
uint16_t port_; ///< UDP port number on which server listens.
bool use_bcast_; ///< Should broadcast be enabled on sockets (if true).
/// @brief Returns the index for "buffer4_receive" hook point
/// @return the index for "buffer4_receive" hook point
static int getHookIndexBuffer4Receive();
/// @brief Returns the index for "pkt4_receive" hook point
/// @return the index for "pkt4_receive" hook point
static int getHookIndexPkt4Receive();
/// @brief Returns the index for "subnet4_select" hook point
/// @return the index for "subnet4_select" hook point
static int getHookIndexSubnet4Select();
/// @brief Returns the index for "lease4_release" hook point
/// @return the index for "lease4_release" hook point
static int getHookIndexLease4Release();
/// @brief Returns the index for "pkt4_send" hook point
/// @return the index for "pkt4_send" hook point
static int getHookIndexPkt4Send();
/// @brief Returns the index for "buffer4_send" hook point
/// @return the index for "buffer4_send" hook point
static int getHookIndexBuffer4Send();
/// Indexes for registered hook points
int hook_index_pkt4_receive_;
int hook_index_subnet4_select_;
int hook_index_pkt4_send_;
/// @brief Returns the index for "lease4_decline" hook point
/// @return the index for "lease4_decline" hook point
static int getHookIndexLease4Decline();
};
}; // namespace isc::dhcp
......
......@@ -8,10 +8,21 @@
#include <util/buffer.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt4o6.h>
#include <dhcp/pkt6.h>
#include <dhcpsrv/callout_handle_store.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp4/ctrl_dhcp4_srv.h>
#include <dhcp4/dhcp4to6_ipc.h>
#include <dhcp4/dhcp4_log.h>
#include <hooks/callout_handle.h>
#include <hooks/hooks_log.h>
#include <hooks/hooks_manager.h>
using namespace std;
using namespace isc::dhcp;
using namespace isc::hooks;
namespace isc {
namespace dhcp {
......@@ -44,13 +55,25 @@ void Dhcp4to6Ipc::open() {
void Dhcp4to6Ipc::handler() {
Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
Pkt6Ptr pkt;
try {
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_RECEIVING);
// Receive message from the IPC socket.
pkt = ipc.receive();
// from Dhcpv4Srv::run_one() after receivePacket()
if (pkt) {
LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP6_DHCP4O6_PACKET_RECEIVED)
.arg(static_cast<int>(pkt->getType()))
.arg(pkt->getRemoteAddr().toText())
.arg(pkt->getIface());
}
} catch (const std::exception& e) {
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_RECEIVE_FAIL)
.arg(e.what());
}
// Reset received message in case we return from this method before the
// received message pointer is updated.
ipc.received_.reset();
// Receive message from the IPC socket.
Pkt6Ptr pkt = ipc.receive();
if (!pkt) {
return;
}
......@@ -58,25 +81,101 @@ void Dhcp4to6Ipc::handler() {
// Each message must contain option holding DHCPv4 message.
OptionCollection msgs = pkt->getOptions(D6O_DHCPV4_MSG);
if (msgs.empty()) {
isc_throw(Dhcp4o6IpcError, "DHCPv4 message option not present in the"
" DHCPv4o6 message received by the DHCPv4 server");
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
.arg("DHCPv4 message option not present");
return;
} else if (msgs.size() > 1) {
isc_throw(Dhcp4o6IpcError, "expected exactly one DHCPv4 message within"
" DHCPv4 message option received by the DHCPv4 server");
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
.arg("more than one DHCPv4 message option");
return;
}
// Get the DHCPv4 message
OptionPtr msg = msgs.begin()->second;
if (!msg) {
isc_throw(Dhcp4o6IpcError, "null DHCPv4 message option in the"
" DHCPv4o6 message received by the DHCPv4 server");
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
.arg("null DHCPv4 message option");
return;
}
// Record this message.
ipc.received_.reset(new Pkt4o6(msg->getData(), pkt));
}
// Extract the DHCPv4 packet with DHCPv6 packet attached
Pkt4Ptr query(new Pkt4o6(msg->getData(), pkt));
Pkt4o6Ptr& Dhcp4to6Ipc::getReceived() {
return (received_);
// From Dhcpv4Srv::run_one() processing and after
Pkt4Ptr rsp;
ControlledDhcpv4Srv::getInstance()->processPacket(query, rsp);
if (!rsp) {
return;
}
try {
// Now all fields and options are constructed into output wire buffer.
// Option objects modification does not make sense anymore. Hooks
// can only manipulate wire buffer at this stage.
// Let's execute all callouts registered for buffer4_send
if (HooksManager::calloutsPresent(Dhcpv4Srv::getHookIndexBuffer4Send())) {
CalloutHandlePtr callout_handle = getCalloutHandle(query);
// Delete previously set arguments
callout_handle->deleteAllArguments();
// Pass incoming packet as argument
callout_handle->setArgument("response4", rsp);
// Call callouts
HooksManager::callCallouts(Dhcpv4Srv::getHookIndexBuffer4Send(),
*callout_handle);
// Callouts decided to skip the next processing step. The next
// processing step would to parse the packet, so skip at this
// stage means drop.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
DHCP4_HOOK_BUFFER_SEND_SKIP)
.arg(rsp->getLabel());
return;
}
/// @todo: Add support for DROP status.
callout_handle->getArgument("response4", rsp);
}
Pkt4o6Ptr rsp6 = boost::dynamic_pointer_cast<Pkt4o6>(rsp);
// Should not happen
if (!rsp6) {
isc_throw(Unexpected, "Dhcp4o6 packet cast fail");
}
LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP4_DHCP4O6_PACKET_SEND)
.arg(rsp6->getLabel())
.arg(rsp6->getName())
.arg(static_cast<int>(rsp6->getType()))
.arg(rsp6->getRemoteAddr())
.arg(rsp6->getIface())
.arg(rsp->getLabel())
.arg(rsp->getName())
.arg(static_cast<int>(rsp->getType()));
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL_DATA,
DHCP4_DHCP4O6_RESPONSE_DATA)
.arg(rsp6->getLabel())
.arg(rsp6->getName())
.arg(static_cast<int>(rsp6->getType()))
.arg(rsp6->toText());
ipc.send(rsp6->getPkt6());
// Update statistics accordingly for sent packet.
Dhcpv4Srv::processStatsSent(rsp);
} catch (const std::exception& e) {
LOG_ERROR(packet4_logger, DHCP4_DHCP4O6_PACKET_SEND_FAIL)
.arg(rsp->getLabel())
.arg(e.what());
}
}
}; // namespace dhcp
......
......@@ -48,16 +48,6 @@ public:
/// 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: