Kea 2.7.6
dhcp6to4_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/pkt6.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <dhcp6/dhcp6to4_ipc.h>
15#include <dhcp6/dhcp6_log.h>
17#include <dhcp6/dhcp6_srv.h>
20#include <hooks/hooks_log.h>
21#include <hooks/hooks_manager.h>
22#include <stats/stats_mgr.h>
23
24using namespace std;
25using namespace isc::hooks;
26
27namespace isc {
28namespace dhcp {
29
30uint16_t Dhcp6to4Ipc::client_port = 0;
31
33
35 static Dhcp6to4Ipc dhcp6to4_ipc;
36 return (dhcp6to4_ipc);
37}
38
40 uint16_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port();
41 if (port == 0) {
43 return;
44 }
45 if (port > 65534) {
46 isc_throw(OutOfRange, "DHCP4o6 port " << port);
47 }
48
49 int old_fd = socket_fd_;
51 if ((old_fd == -1) && (socket_fd_ != old_fd)) {
54 }
55}
56
57void Dhcp6to4Ipc::handler(int /* fd */) {
59 Pkt6Ptr pkt;
60
61 try {
63 // Receive message from IPC.
64 pkt = ipc.receive();
65
66 if (pkt) {
68 .arg(static_cast<int>(pkt->getType()))
69 .arg(pkt->getRemoteAddr().toText())
70 .arg(pkt->getRemotePort())
71 .arg(pkt->getIface());
72 }
73 } catch (const std::exception& e) {
75 .arg(e.what());
76 }
77
78 if (!pkt) {
79 return;
80 }
81
82 // Should we check it is a DHCPV6_DHCPV4_RESPONSE?
83
84 // Handle relay port
85 uint16_t relay_port = Dhcpv6Srv::checkRelaySourcePort(pkt);
86
87 // The received message has been unpacked by the receive() function. This
88 // method could have modified the message so it's better to pack() it
89 // again because we'll be forwarding it to a client.
90 isc::util::OutputBuffer& buf = pkt->getBuffer();
91 buf.clear();
92 pkt->pack();
93
94 // Don't use getType(): get the message type from the buffer as we
95 // want to know if it is a relayed message (vs. internal message type).
96 // getType() always returns the type of internal message.
97 uint8_t msg_type = buf[0];
98 if (client_port) {
99 pkt->setRemotePort(client_port);
100 } else if ((msg_type == DHCPV6_RELAY_FORW) ||
101 (msg_type == DHCPV6_RELAY_REPL)) {
102 pkt->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT);
103 } else {
104 pkt->setRemotePort(DHCP6_CLIENT_PORT);
105 }
106
107 // Can't call the pkt6_send callout because we don't have the query
108 // From Dhcpv6Srv::processPacketBufferSend
109
110 try {
111 // Let's execute all callouts registered for buffer6_send
113 CalloutHandlePtr callout_handle = getCalloutHandle(pkt);
114
115 // Delete previously set arguments
116 callout_handle->deleteAllArguments();
117
118 // Use the RAII wrapper to make sure that the callout handle state is
119 // reset when this object goes out of scope. All hook points must do
120 // it to prevent possible circular dependency between the callout
121 // handle and its arguments.
122 ScopedCalloutHandleState callout_handle_state(callout_handle);
123
124 // Enable copying options from the packet within hook library.
125 ScopedEnableOptionsCopy<Pkt6> response6_options_copy(pkt);
126
127 // Pass incoming packet as argument
128 callout_handle->setArgument("response6", pkt);
129
130 // Call callouts
132 *callout_handle);
133
134 // Callouts decided to skip the next processing step. The next
135 // processing step would be 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)) {
141 .arg(pkt->getLabel());
142 return;
143 }
144
145 callout_handle->getArgument("response6", pkt);
146 }
147
149 .arg(pkt->getLabel())
150 .arg(pkt->getName())
151 .arg(static_cast<int>(pkt->getType()))
152 .arg(pkt->toText());
153
154 // Forward packet to the client.
156
157 // Update statistics accordingly for sent packet.
159
160 } catch (const std::exception& e) {
162 .arg(pkt->getLabel())
163 .arg(e.what());
164 }
165}
166
167} // namespace dhcp
168
169} // namespace isc
170
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:28
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:120
This class implements the communication between the DHCPv4 and DHCPv6 servers to allow for transmissi...
Definition dhcp4o6_ipc.h:61
Pkt6Ptr receive()
Receive message over IPC.
void close()
Close communication socket.
virtual void open()=0
Open communication socket (for derived classes).
int socket_fd_
Socket descriptor.
Handles DHCPv4-over-DHCPv6 IPC on the DHCPv6 server side.
static void handler(int)
On receive handler.
Dhcp6to4Ipc()
Constructor.
virtual void open()
Open communication socket.
static Dhcp6to4Ipc & instance()
Returns pointer to the sole instance of Dhcp6to4Ipc.
static uint16_t client_port
static void processStatsSent(const Pkt6Ptr &response)
Updates statistics for transmitted packets.
static uint16_t checkRelaySourcePort(const Pkt6Ptr &query)
Used for DHCPv4-over-DHCPv6 too.
static int getHookIndexBuffer6Send()
Returns the index of the buffer6_send hook.
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
bool send(const Pkt6Ptr &pkt)
Sends an IPv6 packet.
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.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition buffer.h:343
void clear()
Clear buffer content.
Definition buffer.h:466
@ DHCPV6_RELAY_REPL
Definition dhcp6.h:210
@ DHCPV6_RELAY_FORW
Definition dhcp6.h:209
Defines the Dhcp6to4Ipc class.
#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 DHCP6_DHCP4O6_RECEIVING
const isc::log::MessageID DHCP6_DHCP4O6_PACKET_RECEIVED
const isc::log::MessageID DHCP6_DHCP4O6_RESPONSE_DATA
const int DBG_DHCP6_HOOKS
Debug level used to trace hook related operations.
Definition dhcp6_log.h:34
isc::log::Logger packet6_logger(DHCP6_PACKET_LOGGER_NAME)
Logger for processed packets.
Definition dhcp6_log.h:100
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
const int DBG_DHCP6_DETAIL_DATA
This level is used to log the contents of packets received and sent.
Definition dhcp6_log.h:54
const isc::log::MessageID DHCP6_DHCP4O6_SEND_FAIL
const isc::log::MessageID DHCP6_DHCP4O6_RECEIVE_FAIL
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
const int DBG_DHCP6_BASIC
Debug level used to trace basic operations within the code.
Definition dhcp6_log.h:31
const isc::log::MessageID DHCP6_HOOK_BUFFER_SEND_SKIP
const int DBG_DHCP6_DETAIL
Debug level used to trace detailed errors.
Definition dhcp6_log.h:51
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.