Kea: dhcp4to6_ipc.cc Source File

| Kea 1.5.0

dhcp4to6_ipc.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <util/buffer.h>
10#include <dhcp/iface_mgr.h>
11#include <dhcp/pkt4.h>
12#include <dhcp/pkt4o6.h>
13#include <dhcp/pkt6.h>
14#include <dhcpsrv/callout_handle_store.h>
15#include <dhcpsrv/cfgmgr.h>
16#include <dhcp4/ctrl_dhcp4_srv.h>
17#include <dhcp4/dhcp4to6_ipc.h>
18#include <dhcp4/dhcp4_log.h>
19#include <hooks/callout_handle.h>
20#include <hooks/hooks_log.h>
21#include <hooks/hooks_manager.h>
22
23using namespace std;
24using namespace isc::dhcp;
25using namespace isc::hooks;
26
27namespace isc {
28namespace dhcp {
29
30Dhcp4to6Ipc::Dhcp4to6Ipc() : Dhcp4o6IpcBase() {}
31
32 Dhcp4to6Ipc& Dhcp4to6Ipc::instance() {
33 static Dhcp4to6Ipc dhcp4to6_ipc;
34 return (dhcp4to6_ipc);
35}
36
37 void Dhcp4to6Ipc::open() {
38 uint16_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
39 if (port == 0) {
40 Dhcp4o6IpcBase::close();
41 return;
42 }
43 if (port > 65534) {
44 isc_throw(OutOfRange, "DHCP4o6 port " << port);
45 }
46
47 int old_fd = socket_fd_;
48 socket_fd_ = Dhcp4o6IpcBase::open(port, ENDPOINT_TYPE_V4);
49 if ((old_fd == -1) && (socket_fd_ != old_fd)) {
50 IfaceMgr::instance().addExternalSocket(socket_fd_,
51 Dhcp4to6Ipc::handler);
52 }
53}
54
55 void Dhcp4to6Ipc::handler() {
56 Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
57 Pkt6Ptr pkt;
58
59 try {
60 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_RECEIVING);
61 // Receive message from the IPC socket.
62 pkt = ipc.receive();
63
64 // from Dhcpv4Srv::run_one() after receivePacket()
65 if (pkt) {
66 LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP4_DHCP4O6_PACKET_RECEIVED)
67 .arg(static_cast<int>(pkt->getType()))
68 .arg(pkt->getRemoteAddr().toText())
69 .arg(pkt->getRemotePort())
70 .arg(pkt->getIface());
71 }
72 } catch (const std::exception& e) {
73 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_RECEIVE_FAIL)
74 .arg(e.what());
75 }
76
77 if (!pkt) {
78 return;
79 }
80
81 // Each message must contain option holding DHCPv4 message.
82 OptionCollection msgs = pkt->getOptions(D6O_DHCPV4_MSG);
83 if (msgs.empty()) {
84 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
85 .arg("DHCPv4 message option not present");
86 return;
87 } else if (msgs.size() > 1) {
88 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
89 .arg("more than one DHCPv4 message option");
90 return;
91 }
92
93 // Get the DHCPv4 message.
94 OptionPtr msg = msgs.begin()->second;
95 if (!msg) {
96 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
97 .arg("null DHCPv4 message option");
98 return;
99 }
100
101 // Extract the DHCPv4 packet with DHCPv6 packet attached
102 Pkt4Ptr query(new Pkt4o6(msg->getData(), pkt));
103
104 // From Dhcpv4Srv::run_one() processing and after
105 Pkt4Ptr rsp;
106
107 ControlledDhcpv4Srv::getInstance()->processPacket(query, rsp, false);
108
109 if (!rsp) {
110 return;
111 }
112
113 try {
114 // Now all fields and options are constructed into output wire buffer.
115 // Option objects modification does not make sense anymore. Hooks
116 // can only manipulate wire buffer at this stage.
117 // Let's execute all callouts registered for buffer4_send
118 if (HooksManager::calloutsPresent(Dhcpv4Srv::getHookIndexBuffer4Send())) {
119 CalloutHandlePtr callout_handle = getCalloutHandle(query);
120
121 // Delete previously set arguments
122 callout_handle->deleteAllArguments();
123
124 // Enable copying options from the packet within hook library.
125 ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
126
127 // Pass incoming packet as argument
128 callout_handle->setArgument("response4", rsp);
129
130 // Call callouts
131 HooksManager::callCallouts(Dhcpv4Srv::getHookIndexBuffer4Send(),
132 *callout_handle);
133
134 // Callouts decided to skip the next processing step. The next
135 // processing step would to parse the packet, so skip at this
136 // stage means drop.
137 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
138 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
139 LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
140 DHCP4_HOOK_BUFFER_SEND_SKIP)
141 .arg(rsp->getLabel());
142 return;
143 }
144
145 callout_handle->getArgument("response4", rsp);
146 }
147
148 Pkt4o6Ptr rsp6 = boost::dynamic_pointer_cast<Pkt4o6>(rsp);
149 // Should not happen
150 if (!rsp6) {
151 isc_throw(Unexpected, "Dhcp4o6 packet cast fail");
152 }
153
154 LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP4_DHCP4O6_PACKET_SEND)
155 .arg(rsp6->getLabel())
156 .arg(rsp6->getName())
157 .arg(static_cast<int>(rsp6->getType()))
158 .arg(rsp6->getRemoteAddr())
159 .arg(rsp6->getRemotePort())
160 .arg(rsp6->getIface())
161 .arg(rsp->getLabel())
162 .arg(rsp->getName())
163 .arg(static_cast<int>(rsp->getType()));
164
165 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL_DATA,
166 DHCP4_DHCP4O6_RESPONSE_DATA)
167 .arg(rsp6->getLabel())
168 .arg(rsp6->getName())
169 .arg(static_cast<int>(rsp6->getType()))
170 .arg(rsp6->toText());
171
172 ipc.send(rsp6->getPkt6());
173
174 // Update statistics accordingly for sent packet.
175 Dhcpv4Srv::processStatsSent(rsp);
176
177 } catch (const std::exception& e) {
178 LOG_ERROR(packet4_logger, DHCP4_DHCP4O6_PACKET_SEND_FAIL)
179 .arg(rsp->getLabel())
180 .arg(e.what());
181 }
182}
183
184}; // namespace dhcp
185
186}; // namespace isc
buffer.h
callout_handle.h
callout_handle_store.h
cfgmgr.h
isc::OutOfRange
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Definition: exceptions/exceptions.h:115
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition: exceptions/exceptions.h:153
isc::dhcp::CfgMgr::instance
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
isc::dhcp::CfgMgr::getStagingCfg
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:160
isc::dhcp::ControlledDhcpv4Srv::getInstance
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
Definition: ctrl_dhcp4_srv.h:118
isc::dhcp::Dhcp4o6IpcBase
This class implements the communication between the DHCPv4 and DHCPv6 servers to allow for transmissi...
Definition: dhcp4o6_ipc.h:61
isc::dhcp::Dhcp4o6IpcBase::send
void send(const Pkt6Ptr &pkt)
Send message over IPC.
Definition: dhcp4o6_ipc.cc:226
isc::dhcp::Dhcp4o6IpcBase::receive
Pkt6Ptr receive()
Receive message over IPC.
Definition: dhcp4o6_ipc.cc:127
isc::dhcp::Dhcp4o6IpcBase::ENDPOINT_TYPE_V4
@ ENDPOINT_TYPE_V4
Definition: dhcp4o6_ipc.h:66
isc::dhcp::Dhcp4o6IpcBase::close
void close()
Close communication socket.
Definition: dhcp4o6_ipc.cc:118
isc::dhcp::Dhcp4o6IpcBase::open
virtual void open()=0
Open communication socket (for derived classes).
isc::dhcp::Dhcp4o6IpcBase::socket_fd_
int socket_fd_
Socket descriptor.
Definition: dhcp4o6_ipc.h:125
isc::dhcp::Dhcp4to6Ipc
Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side.
Definition: dhcp4to6_ipc.h:23
isc::dhcp::Dhcp4to6Ipc::handler
static void handler()
On receive handler.
Definition: dhcp4to6_ipc.cc:55
isc::dhcp::Dhcp4to6Ipc::instance
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
Definition: dhcp4to6_ipc.cc:32
isc::dhcp::Dhcp4to6Ipc::open
virtual void open()
Open communication socket.
Definition: dhcp4to6_ipc.cc:37
isc::dhcp::Dhcp4to6Ipc::Dhcp4to6Ipc
Dhcp4to6Ipc()
Constructor.
Definition: dhcp4to6_ipc.cc:30
isc::dhcp::Dhcpv4Srv::processStatsSent
static void processStatsSent(const Pkt4Ptr &response)
Updates statistics for transmitted packets.
Definition: dhcp4_srv.cc:3577
isc::dhcp::Dhcpv4Srv::getHookIndexBuffer4Send
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
Definition: dhcp4_srv.cc:3623
isc::dhcp::Dhcpv4Srv::processPacket
void processPacket(Pkt4Ptr &query, Pkt4Ptr &rsp, bool allow_packet_park=true)
Process a single incoming DHCPv4 packet.
Definition: dhcp4_srv.cc:844
isc::dhcp::IfaceMgr::instance
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
isc::dhcp::IfaceMgr::addExternalSocket
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
Definition: iface_mgr.cc:317
isc::dhcp::Pkt4o6
Represents DHCPv4-over-DHCPv6 packet.
Definition: pkt4o6.h:30
isc::dhcp::ScopedEnableOptionsCopy
RAII object enabling copying options retrieved from the packet.
Definition: pkt.h:40
isc::hooks::CalloutHandle::NEXT_STEP_DROP
@ NEXT_STEP_DROP
drop the packet
Definition: callout_handle.h:95
isc::hooks::CalloutHandle::NEXT_STEP_SKIP
@ NEXT_STEP_SKIP
skip the next processing step
Definition: callout_handle.h:94
isc::hooks::HooksManager::calloutsPresent
static bool calloutsPresent(int index)
Are callouts present?
Definition: hooks_manager.cc:49
isc::hooks::HooksManager::callCallouts
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Definition: hooks_manager.cc:73
ctrl_dhcp4_srv.h
dhcp4_log.h
Contains declarations for loggers used by the DHCPv4 server component.
dhcp4to6_ipc.h
Defines the Dhcp4o6Ipc class.
D6O_DHCPV4_MSG
@ D6O_DHCPV4_MSG
Definition: dhcp6.h:107
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
hooks_log.h
hooks_manager.h
iface_mgr.h
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
isc::dhcp
Definition: ctrl_dhcp4_srv.cc:75
isc::dhcp::DBG_DHCP4_DETAIL
const int DBG_DHCP4_DETAIL
Debug level used to trace detailed errors.
Definition: dhcp4_log.h:53
isc::dhcp::Pkt4Ptr
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:546
isc::dhcp::DBG_DHCP4_DETAIL_DATA
const int DBG_DHCP4_DETAIL_DATA
This level is used to log the contents of packets received and sent.
Definition: dhcp4_log.h:56
isc::dhcp::OptionCollection
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
Definition: option.h:41
isc::dhcp::Pkt4o6Ptr
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
Definition: pkt4o6.h:82
isc::dhcp::getCalloutHandle
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
Definition: callout_handle_store.h:47
isc::dhcp::DBG_DHCP4_BASIC
const int DBG_DHCP4_BASIC
Debug level used to trace basic operations within the code.
Definition: dhcp4_log.h:33
isc::dhcp::packet4_logger
isc::log::Logger packet4_logger(DHCP4_PACKET_LOGGER_NAME)
Logger for processed packets.
Definition: dhcp4_log.h:103
isc::dhcp::Pkt6Ptr
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:31
isc::dhcp::DBG_DHCP4_HOOKS
const int DBG_DHCP4_HOOKS
Debug level used to trace hook related operations.
Definition: dhcp4_log.h:36
isc::dhcp::OptionPtr
boost::shared_ptr< Option > OptionPtr
Definition: option.h:38
isc::hooks
Definition: callout_handle.cc:21
isc::hooks::hooks_logger
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
Definition: hooks_log.h:37
isc::hooks::CalloutHandlePtr
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
Definition: callout_handle.h:416
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
pkt4.h
pkt4o6.h
pkt6.h