Kea  1.9.9-git
dhcp4to6_ipc.cc
Go to the documentation of this file.
1 // Copyright (C) 2015-2020 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>
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 
23 using namespace std;
24 using namespace isc::dhcp;
25 using namespace isc::hooks;
26 
27 namespace isc {
28 namespace dhcp {
29 
30 Dhcp4to6Ipc::Dhcp4to6Ipc() : Dhcp4o6IpcBase() {}
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 
55 void 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::run_one() 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("DHCPv4 message option not present");
86  return;
87  } else if (msgs.size() > 1) {
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) {
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  // Use the RAII wrapper to make sure that the callout handle state is
125  // reset when this object goes out of scope. All hook points must do
126  // it to prevent possible circular dependency between the callout
127  // handle and its arguments.
128  ScopedCalloutHandleState callout_handle_state(callout_handle);
129 
130  // Enable copying options from the packet within hook library.
131  ScopedEnableOptionsCopy<Pkt4> response4_options_copy(rsp);
132 
133  // Pass incoming packet as argument
134  callout_handle->setArgument("response4", rsp);
135 
136  // Call callouts
137  HooksManager::callCallouts(Dhcpv4Srv::getHookIndexBuffer4Send(),
138  *callout_handle);
139 
140  // Callouts decided to skip the next processing step. The next
141  // processing step would to parse the packet, so skip at this
142  // stage means drop.
143  if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
144  (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
147  .arg(rsp->getLabel());
148  return;
149  }
150 
151  callout_handle->getArgument("response4", rsp);
152  }
153 
154  Pkt4o6Ptr rsp6 = boost::dynamic_pointer_cast<Pkt4o6>(rsp);
155  // Should not happen
156  if (!rsp6) {
157  isc_throw(Unexpected, "Dhcp4o6 packet cast fail");
158  }
159 
161  .arg(rsp6->getLabel())
162  .arg(rsp6->getName())
163  .arg(static_cast<int>(rsp6->getType()))
164  .arg(rsp6->getRemoteAddr())
165  .arg(rsp6->getRemotePort())
166  .arg(rsp6->getIface())
167  .arg(rsp->getLabel())
168  .arg(rsp->getName())
169  .arg(static_cast<int>(rsp->getType()));
170 
173  .arg(rsp6->getLabel())
174  .arg(rsp6->getName())
175  .arg(static_cast<int>(rsp6->getType()))
176  .arg(rsp6->toText());
177 
178  ipc.send(rsp6->getPkt6());
179 
180  // Update statistics accordingly for sent packet.
182 
183  } catch (const std::exception& e) {
185  .arg(rsp->getLabel())
186  .arg(e.what());
187  }
188 }
189 
190 } // namespace dhcp
191 } // namespace isc
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
Definition: dhcp4_srv.cc:4059
static void handler(int)
On receive handler.
Definition: dhcp4to6_ipc.cc:55
virtual void open()
Open communication socket.
Definition: dhcp4to6_ipc.cc:37
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_RECEIVED
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
Definition: iface_mgr.cc:324
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
virtual void open()=0
Open communication socket (for derived classes).
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
STL namespace.
This class implements the communication between the DHCPv4 and DHCPv6 servers to allow for transmissi...
Definition: dhcp4o6_ipc.h:61
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
Definition: dhcp4to6_ipc.cc:32
RAII object enabling copying options retrieved from the packet.
Definition: pkt.h:40
isc::log::Logger packet4_logger(DHCP4_PACKET_LOGGER_NAME)
Logger for processed packets.
Definition: dhcp4_log.h:103
const int DBG_DHCP4_BASIC
Debug level used to trace basic operations within the code.
Definition: dhcp4_log.h:33
const isc::log::MessageID DHCP4_DHCP4O6_BAD_PACKET
const isc::log::MessageID DHCP4_DHCP4O6_PACKET_SEND_FAIL
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:28
int socket_fd_
Socket descriptor.
Definition: dhcp4o6_ipc.h:125
void processPacket(Pkt4Ptr &query, Pkt4Ptr &rsp, bool allow_packet_park=true)
Process a single incoming DHCPv4 packet.
Definition: dhcp4_srv.cc:1070
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVING
const int DBG_DHCP4_DETAIL_DATA
This level is used to log the contents of packets received and sent.
Definition: dhcp4_log.h:56
A generic exception that is thrown when an unexpected error condition occurs.
Wrapper class around callout handle which automatically resets handle's state.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:544
const isc::log::MessageID DHCP4_DHCP4O6_RESPONSE_DATA
const int DBG_DHCP4_DETAIL
Debug level used to trace detailed errors.
Definition: dhcp4_log.h:53
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
Definition: option.h:40
const int DBG_DHCP4_HOOKS
Debug level used to trace hook related operations.
Definition: dhcp4_log.h:36
static void processStatsSent(const Pkt4Ptr &response)
Updates statistics for transmitted packets.
Definition: dhcp4_srv.cc:4013
const isc::log::MessageID DHCP4_DHCP4O6_RECEIVE_FAIL
const isc::log::MessageID DHCP4_HOOK_BUFFER_SEND_SKIP
Defines the logger used by the top-level component of kea-dhcp-ddns.
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
Definition: hooks_log.h:37
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
Definition: pkt4o6.h:82
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
Pkt6Ptr receive()
Receive message over IPC.
Definition: dhcp4o6_ipc.cc:127
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
void close()
Close communication socket.
Definition: dhcp4o6_ipc.cc:118
Defines the Dhcp4o6Ipc class.
void send(const Pkt6Ptr &pkt)
Send message over IPC.
Definition: dhcp4o6_ipc.cc:226
Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side.
Definition: dhcp4to6_ipc.h:23
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
Represents DHCPv4-over-DHCPv6 packet.
Definition: pkt4o6.h:30
Contains declarations for loggers used by the DHCPv4 server component.
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167