Kea 2.5.9
dhcp4to6_ipc.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2024 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>
15#include <dhcpsrv/cfgmgr.h>
17#include <dhcp4/dhcp4to6_ipc.h>
18#include <dhcp4/dhcp4_log.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
31
33 static Dhcp4to6Ipc dhcp4to6_ipc;
34 return (dhcp4to6_ipc);
35}
36
38 uint16_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
39 if (port == 0) {
41 return;
42 }
43 if (port > 65534) {
44 isc_throw(OutOfRange, "DHCP4o6 port " << port);
45 }
46
47 int old_fd = socket_fd_;
49 if ((old_fd == -1) && (socket_fd_ != old_fd)) {
52 }
53}
54
55void Dhcp4to6Ipc::handler(int /* fd */) {
57 Pkt6Ptr pkt;
58
59 try {
61 // Receive message from the IPC socket.
62 pkt = ipc.receive();
63
64 // From Dhcpv4Srv::runOne() after receivePacket()
65 if (pkt) {
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) {
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()) {
85 .arg(pkt->getLabel())
86 .arg("DHCPv4 message option not present");
87 return;
88 } else if (msgs.size() > 1) {
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) {
99 .arg(pkt->getLabel())
100 .arg("null DHCPv4 message option");
101 return;
102 }
103
104 // Extract the DHCPv4 packet with DHCPv6 packet attached
105 Pkt4Ptr query(new Pkt4o6(msg->getData(), pkt));
106
107 // From Dhcpv4Srv::runOne() processing and after
108 Pkt4Ptr rsp;
109
110 rsp = ControlledDhcpv4Srv::getInstance()->processPacket(query, false);
111
112 if (!rsp) {
113 return;
114 }
115
116 try {
117 // Now all fields and options are constructed into output wire buffer.
118 // Option objects modification does not make sense anymore. Hooks
119 // can only manipulate wire buffer at this stage.
120 // Let's execute all callouts registered for buffer4_send
122 CalloutHandlePtr callout_handle = getCalloutHandle(query);
123
124 // Delete previously set arguments
125 callout_handle->deleteAllArguments();
126
127 // Use the RAII wrapper to make sure that the callout handle state is
128 // reset when this object goes out of scope. All hook points must do
129 // it to prevent possible circular dependency between the callout
130 // handle and its arguments.
131 ScopedCalloutHandleState callout_handle_state(callout_handle);
132
133 // Enable copying options from the packet within hook library.
134 ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
135
136 // Pass incoming packet as argument
137 callout_handle->setArgument("response4", rsp);
138
139 // Call callouts
141 *callout_handle);
142
143 // Callouts decided to skip the next processing step. The next
144 // processing step would be to parse the packet, so skip at this
145 // stage means drop.
146 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
147 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
150 .arg(rsp->getLabel());
151 return;
152 }
153
154 callout_handle->getArgument("response4", rsp);
155 }
156
157 Pkt4o6Ptr rsp6 = boost::dynamic_pointer_cast<Pkt4o6>(rsp);
158 // Should not happen
159 if (!rsp6) {
160 isc_throw(Unexpected, "Dhcp4o6 packet cast fail");
161 }
162
164 .arg(rsp6->getLabel())
165 .arg(rsp6->getName())
166 .arg(static_cast<int>(rsp6->getType()))
167 .arg(rsp6->getRemoteAddr())
168 .arg(rsp6->getRemotePort())
169 .arg(rsp6->getIface())
170 .arg(rsp->getLabel())
171 .arg(rsp->getName())
172 .arg(static_cast<int>(rsp->getType()));
173
176 .arg(rsp6->getLabel())
177 .arg(rsp6->getName())
178 .arg(static_cast<int>(rsp6->getType()))
179 .arg(rsp6->toText());
180
181 ipc.send(rsp6->getPkt6());
182
183 // Update statistics accordingly for sent packet.
185
186 } catch (const std::exception& e) {
188 .arg(rsp->getLabel())
189 .arg(e.what());
190 }
191}
192
193} // namespace dhcp
194} // namespace isc
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
This class implements the communication between the DHCPv4 and DHCPv6 servers to allow for transmissi...
Definition: dhcp4o6_ipc.h:61
void send(const Pkt6Ptr &pkt)
Send message over IPC.
Definition: dhcp4o6_ipc.cc:225
Pkt6Ptr receive()
Receive message over IPC.
Definition: dhcp4o6_ipc.cc:127
void close()
Close communication socket.
Definition: dhcp4o6_ipc.cc:118
virtual void open()=0
Open communication socket (for derived classes).
int socket_fd_
Socket descriptor.
Definition: dhcp4o6_ipc.h:125
Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side.
Definition: dhcp4to6_ipc.h:23
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
Definition: dhcp4to6_ipc.cc:32
virtual void open()
Open communication socket.
Definition: dhcp4to6_ipc.cc:37
static void handler(int)
On receive handler.
Definition: dhcp4to6_ipc.cc:55
Dhcp4to6Ipc()
Constructor.
Definition: dhcp4to6_ipc.cc:30
static void processStatsSent(const Pkt4Ptr &response)
Updates statistics for transmitted packets.
Definition: dhcp4_srv.cc:5026
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
Definition: dhcp4_srv.cc:5072
Pkt4Ptr processPacket(Pkt4Ptr query, bool allow_answer_park=true)
Process a single incoming DHCPv4 packet.
Definition: dhcp4_srv.cc:1267
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:54
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
Definition: iface_mgr.cc:329
Represents DHCPv4-over-DHCPv6 packet.
Definition: pkt4o6.h:30
RAII object enabling copying options retrieved from the packet.
Definition: pkt.h:46
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
static bool calloutsPresent(int index)
Are callouts present?
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
Contains declarations for loggers used by the DHCPv4 server component.
Defines the Dhcp4o6Ipc class.
@ D6O_DHCPV4_MSG
Definition: dhcp6.h:107
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND
const int DBG_DHCP4_DETAIL
Debug level used to trace detailed errors.
Definition: dhcp4_log.h:53
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:555
const int DBG_DHCP4_DETAIL_DATA
This level is used to log the contents of packets received and sent.
Definition: dhcp4_log.h:56
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
Definition: option.h:40
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVING
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
Definition: pkt4o6.h:82
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
const isc::log::MessageID DHCP4_DHCP4O6_RESPONSE_DATA
const int DBG_DHCP4_BASIC
Debug level used to trace basic operations within the code.
Definition: dhcp4_log.h:33
isc::log::Logger packet4_logger(DHCP4_PACKET_LOGGER_NAME)
Logger for processed packets.
Definition: dhcp4_log.h:103
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:31
const isc::log::MessageID DHCP4_DHCP4O6_BAD_PACKET
const int DBG_DHCP4_HOOKS
Debug level used to trace hook related operations.
Definition: dhcp4_log.h:36
const isc::log::MessageID DHCP4_HOOK_BUFFER_SEND_SKIP
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_RECEIVED
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND_FAIL
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVE_FAIL
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
Definition: hooks_log.h:37
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
Defines the logger used by the top-level component of kea-lfc.