Browse Source

[4109a] Copy the send part (logs and hook) from standard service to 4o6 handler

Francis Dupont 8 years ago
parent
commit
1ab0eff8f6

+ 18 - 0
src/bin/dhcp6/dhcp6_messages.mes

@@ -237,6 +237,24 @@ received in Decline message. It's expected that the option will contain an
 address that is being declined. Specific information will be printed in a
 separate message.
 
+% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv4 server (type %1) for %2 on interface %3
+This debug message is printed when the server is receiving a DHCPv4o6
+from the DHCPv4 server over inter-process communication.
+
+% DHCP6_DHCP4O6_RECEIVE_FAIL failed to receive DHCPv4o6: %1
+This debug message indicates the inter-process communication with the
+DHCPv4 server failed. The reason for the error is included in
+the message.
+
+% DHCP6_DHCP4O6_RECEIVING receiving DHCPv4o6 packet from DHCPv4 server
+This debug message is printed when the server is receiving a DHCPv4o6
+from the DHCPv4 server over inter-process communication
+
+% DHCP6_DHCP4O6_SEND_FAIL failed to send DHCPv4o6 packet: %1
+This error is output if the IPv6 DHCP server fails to send an assembled
+DHCPv4o6 message to a client. The reason for the error is included in the
+message.
+
 % DHCP6_DYNAMIC_RECONFIGURATION initiate server reconfiguration using file: %1, after receiving SIGHUP signal
 This is the info message logged when the DHCPv6 server starts reconfiguration
 as a result of receiving SIGHUP signal.

+ 2 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -165,6 +165,8 @@ createStatusCode(const Pkt6& pkt, const Option6IA& ia, const uint16_t status_cod
 namespace isc {
 namespace dhcp {
 
+int Dhcpv6Srv::hook_index_buffer6_send = Hooks.hook_index_buffer6_send_;
+
 const std::string Dhcpv6Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
 
 Dhcpv6Srv::Dhcpv6Srv(uint16_t port)

+ 8 - 2
src/bin/dhcp6/dhcp6_srv.h

@@ -787,12 +787,18 @@ private:
     /// @param query packet received
     static void processStatsReceived(const Pkt6Ptr& query);
 
+    /// UDP port number on which server listens.
+    uint16_t port_;
+
+public:
+    /// @note used by DHCPv4-over-DHCPv6 so must be public
+
     /// @brief Updates statistics for transmitted packets
     /// @param query packet transmitted
     static void processStatsSent(const Pkt6Ptr& response);
 
-    /// UDP port number on which server listens.
-    uint16_t port_;
+    /// the index of the buffer6_send hook
+    static int hook_index_buffer6_send;
 
 protected:
 

+ 77 - 6
src/bin/dhcp6/dhcp6to4_ipc.cc

@@ -8,10 +8,20 @@
 
 #include <util/buffer.h>
 #include <dhcp/iface_mgr.h>
+#include <dhcp/pkt6.h>
+#include <dhcpsrv/callout_handle_store.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcp6/dhcp6to4_ipc.h>
+#include <dhcp6/dhcp6_log.h>
+#include <dhcp6/dhcp6_srv.h>
+#include <exceptions/exceptions.h>
+#include <hooks/callout_handle.h>
+#include <hooks/hooks_log.h>
+#include <hooks/hooks_manager.h>
+#include <stats/stats_mgr.h>
 
 using namespace std;
+using namespace isc::hooks;
 
 namespace isc {
 namespace dhcp {
@@ -44,13 +54,30 @@ void Dhcp6to4Ipc::open() {
 
 void Dhcp6to4Ipc::handler() {
     Dhcp6to4Ipc& ipc = Dhcp6to4Ipc::instance();
+    Pkt6Ptr pkt;
+
+    try {
+        LOG_DEBUG(packet6_logger, DBG_DHCP6_DETAIL, DHCP6_DHCP4O6_RECEIVING);
+        // Receive message from IPC.
+        pkt = ipc.receive();
+
+        if (pkt) {
+            LOG_DEBUG(packet6_logger, DBG_DHCP6_BASIC, DHCP6_DHCP4O6_PACKET_RECEIVED)
+                .arg(static_cast<int>(pkt->getType()))
+                .arg(pkt->getRemoteAddr().toText())
+                .arg(pkt->getIface());
+        }
+    } catch (const std::exception& e) {
+        LOG_DEBUG(packet6_logger,DBG_DHCP6_DETAIL, DHCP6_DHCP4O6_RECEIVE_FAIL)
+            .arg(e.what());
+    }
 
-    // Receive message from IPC.
-    Pkt6Ptr pkt = ipc.receive();
     if (!pkt) {
         return;
     }
 
+    // Should we check it is a DHCPV6_DHCPV4_RESPONSE?
+
     // The received message has been unpacked by the receive() function. This
     // method could have modified the message so it's better to pack() it
     // again because we'll be forwarding it to a client.
@@ -58,16 +85,60 @@ void Dhcp6to4Ipc::handler() {
     buf.clear();
     pkt->pack();
 
-    uint8_t msg_type = pkt->getType();
+    // Don't use getType(): get the message type from the buffer
+    uint8_t msg_type = buf[0];
     if ((msg_type == DHCPV6_RELAY_FORW) || (msg_type == DHCPV6_RELAY_REPL)) {
         pkt->setRemotePort(DHCP6_SERVER_PORT);
     } else {
         pkt->setRemotePort(DHCP6_CLIENT_PORT);
     }
 
-    // Forward packet to the client.
-    IfaceMgr::instance().send(pkt);
-    // processStatsSent(pkt);
+    // Can't call the pkt6_send callout because we don't have the query
+
+    // Copied from Dhcpv6Srv::run_one() sending part
+
+    try {
+        // Let's execute all callouts registered for buffer6_send
+        if (HooksManager::calloutsPresent(Dhcpv6Srv::hook_index_buffer6_send)) {
+            CalloutHandlePtr callout_handle = getCalloutHandle(pkt);
+
+            // Delete previously set arguments
+            callout_handle->deleteAllArguments();
+
+            // Pass incoming packet as argument
+            callout_handle->setArgument("response6", pkt);
+
+            // Call callouts
+            HooksManager::callCallouts(Dhcpv6Srv::hook_index_buffer6_send,
+                                       *callout_handle);
+
+            // Callouts decided to skip the next processing step. The next
+            // processing step would to parse the packet, so skip at this
+            // stage means drop.
+            if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
+                LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP)
+                    .arg(pkt->getLabel());
+                return;
+            }
+
+            /// @todo: Add support for DROP status
+
+            callout_handle->getArgument("response6", pkt);
+        }
+
+        LOG_DEBUG(packet6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_RESPONSE_DATA)
+            .arg(static_cast<int>(pkt->getType())).arg(pkt->toText());
+
+
+        // Forward packet to the client.
+        IfaceMgr::instance().send(pkt);
+
+        // Update statistics accordingly for sent packet.
+        Dhcpv6Srv::processStatsSent(pkt);
+
+    } catch (const std::exception& e) {
+        LOG_ERROR(packet6_logger, DHCP6_DHCP4O6_SEND_FAIL).arg(e.what());
+    }
 }
 
 };  // namespace dhcp