Skip to content
GitLab
Menu
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
7d36aebe
Commit
7d36aebe
authored
Jun 30, 2016
by
Francis Dupont
Browse files
[master] Merge trac4110a (DHCP4o6 v4 server part)
parents
dedda6a3
923242ca
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/dhcp4_messages.mes
View file @
7d36aebe
...
...
@@ -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
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
7d36aebe
...
...
@@ -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
src/bin/dhcp4/dhcp4_srv.h
View file @
7d36aebe
...
...
@@ -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
...
...
src/bin/dhcp4/dhcp4to6_ipc.cc
View file @
7d36aebe
...
...
@@ -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
...
...
src/bin/dhcp4/dhcp4to6_ipc.h
View file @
7d36aebe
...
...
@@ -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:
/// @brief last received packet