Kea: dhcp4to6_ipc.cc Source File

| Kea 3.2.0-git

dhcp4to6_ipc.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2026 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(int /* fd */) {
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::runOne() 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(pkt->getLabel())
86 .arg("DHCPv4 message option not present");
87 return;
88 } else if (msgs.size() > 1) {
89 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
90 .arg(pkt->getLabel())
91 .arg("more than one DHCPv4 message option");
92 return;
93 }
94
95 // Get the DHCPv4 message.
96 OptionPtr msg = msgs.begin()->second;
97 if (!msg) {
98 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
99 .arg(pkt->getLabel())
100 .arg("null DHCPv4 message option");
101 return;
102 }
103
104 Pkt4Ptr query;
105 try {
106 // Extract the DHCPv4 packet with DHCPv6 packet attached
107 query.reset(new Pkt4o6(msg->getData(), pkt));
108 } catch (const std::exception& e) {
109 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_DHCP4O6_BAD_PACKET)
110 .arg(pkt->getLabel())
111 .arg(e.what());
112 return;
113 }
114
115 // From Dhcpv4Srv::runOne() processing and after
116 Pkt4Ptr rsp;
117
118 rsp = ControlledDhcpv4Srv::getInstance()->processPacket(query, false);
119
120 if (!rsp) {
121 return;
122 }
123
124 try {
125 // Now all fields and options are constructed into output wire buffer.
126 // Option objects modification does not make sense anymore. Hooks
127 // can only manipulate wire buffer at this stage.
128 // Let's execute all callouts registered for buffer4_send
129 if (HooksManager::calloutsPresent(Dhcpv4Srv::getHookIndexBuffer4Send())) {
130 CalloutHandlePtr callout_handle = getCalloutHandle(query);
131
132 // Delete previously set arguments
133 callout_handle->deleteAllArguments();
134
135 // Use the RAII wrapper to make sure that the callout handle state is
136 // reset when this object goes out of scope. All hook points must do
137 // it to prevent possible circular dependency between the callout
138 // handle and its arguments.
139 ScopedCalloutHandleState callout_handle_state(callout_handle);
140
141 // Enable copying options from the packet within hook library.
142 ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
143
144 // Pass incoming packet as argument
145 callout_handle->setArgument("response4", rsp);
146
147 // Call callouts
148 HooksManager::callCallouts(Dhcpv4Srv::getHookIndexBuffer4Send(),
149 *callout_handle);
150
151 // Callouts decided to skip the next processing step. The next
152 // processing step would be to parse the packet, so skip at this
153 // stage means drop.
154 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
155 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
156 LOG_DEBUG(hooks_logger, DBG_DHCP4_HOOKS,
157 DHCP4_HOOK_BUFFER_SEND_SKIP)
158 .arg(rsp->getLabel());
159 return;
160 }
161
162 callout_handle->getArgument("response4", rsp);
163 }
164
165 Pkt4o6Ptr rsp6 = boost::dynamic_pointer_cast<Pkt4o6>(rsp);
166 // Should not happen
167 if (!rsp6) {
168 isc_throw(Unexpected, "Dhcp4o6 packet cast fail");
169 }
170
171 LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP4_DHCP4O6_PACKET_SEND)
172 .arg(rsp6->getLabel())
173 .arg(rsp6->getName())
174 .arg(static_cast<int>(rsp6->getType()))
175 .arg(rsp6->getRemoteAddr())
176 .arg(rsp6->getRemotePort())
177 .arg(rsp6->getIface())
178 .arg(rsp->getLabel())
179 .arg(rsp->getName())
180 .arg(static_cast<int>(rsp->getType()));
181
182 LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL_DATA,
183 DHCP4_DHCP4O6_RESPONSE_DATA)
184 .arg(rsp6->getLabel())
185 .arg(rsp6->getName())
186 .arg(static_cast<int>(rsp6->getType()))
187 .arg(rsp6->toText());
188
189 ipc.send(rsp6->getPkt6());
190
191 // Update statistics accordingly for sent packet.
192 Dhcpv4Srv::processStatsSent(rsp);
193
194 } catch (const std::exception& e) {
195 LOG_ERROR(packet4_logger, DHCP4_DHCP4O6_PACKET_SEND_FAIL)
196 .arg(rsp->getLabel())
197 .arg(e.what());
198 }
199}
200
201} // namespace dhcp
202} // 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:29
isc::dhcp::CfgMgr::getStagingCfg
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:121
isc::dhcp::ControlledDhcpv4Srv::getInstance
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
Definition ctrl_dhcp4_srv.h:118
isc::dhcp::Dhcp4o6IpcBase::send
void send(const Pkt6Ptr &pkt)
Send message over IPC.
Definition dhcp4o6_ipc.cc:225
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::Dhcp4o6IpcBase
Dhcp4o6IpcBase()
Constructor.
Definition dhcp4o6_ipc.cc:33
isc::dhcp::Dhcp4o6IpcBase::socket_fd_
int socket_fd_
Socket descriptor.
Definition dhcp4o6_ipc.h:125
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::handler
static void handler(int)
On receive handler.
Definition dhcp4to6_ipc.cc:55
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:5366
isc::dhcp::Dhcpv4Srv::getHookIndexBuffer4Send
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
Definition dhcp4_srv.cc:5410
isc::dhcp::Dhcpv4Srv::processPacket
Pkt4Ptr processPacket(Pkt4Ptr query, bool allow_answer_park=true)
Process a single incoming DHCPv4 packet.
Definition dhcp4_srv.cc:1372
isc::dhcp::IfaceMgr::instance
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition iface_mgr.cc:52
isc::dhcp::IfaceMgr::addExternalSocket
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
Definition iface_mgr.cc:367
isc::dhcp::Pkt4o6
Represents DHCPv4-over-DHCPv6 packet.
Definition pkt4o6.h:29
isc::dhcp::ScopedEnableOptionsCopy
RAII object enabling copying options retrieved from the packet.
Definition pkt.h:46
isc::hooks::CalloutHandle::NEXT_STEP_DROP
@ NEXT_STEP_DROP
drop the packet
Definition callout_handle.h:89
isc::hooks::CalloutHandle::NEXT_STEP_SKIP
@ NEXT_STEP_SKIP
skip the next processing step
Definition callout_handle.h:88
isc::hooks::HooksManager::calloutsPresent
static bool calloutsPresent(int index)
Are callouts present?
Definition hooks_manager.cc:54
isc::hooks::HooksManager::callCallouts
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Definition hooks_manager.cc:76
isc::hooks::ScopedCalloutHandleState
Wrapper class around callout handle which automatically resets handle's state.
Definition callout_handle.h:510
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:210
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 dhcp4/client_handler.cc:20
isc::dhcp::DHCP4_DHCP4O6_PACKET_SEND
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND
Definition dhcp4_messages.h:61
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:556
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:40
isc::dhcp::DHCP4_DHCP4O6_RECEIVING
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVING
Definition dhcp4_messages.h:64
isc::dhcp::Pkt4o6Ptr
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
Definition pkt4o6.h:83
isc::dhcp::getCalloutHandle
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
Definition callout_handle_store.h:47
isc::dhcp::DHCP4_DHCP4O6_RESPONSE_DATA
const isc::log::MessageID DHCP4_DHCP4O6_RESPONSE_DATA
Definition dhcp4_messages.h:65
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::DHCP4_DHCP4O6_BAD_PACKET
const isc::log::MessageID DHCP4_DHCP4O6_BAD_PACKET
Definition dhcp4_messages.h:57
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::DHCP4_HOOK_BUFFER_SEND_SKIP
const isc::log::MessageID DHCP4_HOOK_BUFFER_SEND_SKIP
Definition dhcp4_messages.h:79
isc::dhcp::DHCP4_DHCP4O6_PACKET_RECEIVED
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_RECEIVED
Definition dhcp4_messages.h:60
isc::dhcp::DHCP4_DHCP4O6_PACKET_SEND_FAIL
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND_FAIL
Definition dhcp4_messages.h:62
isc::dhcp::OptionPtr
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
isc::dhcp::DHCP4_DHCP4O6_RECEIVE_FAIL
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVE_FAIL
Definition dhcp4_messages.h:63
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:470
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
pkt4.h
pkt4o6.h
pkt6.h