]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1064] Added pkt4_send code (tests to do)
authorFrancis Dupont <fdupont@isc.org>
Wed, 22 Jan 2020 18:50:53 +0000 (19:50 +0100)
committerTomek Mrugalski <tomasz@isc.org>
Sun, 26 Jan 2020 18:42:44 +0000 (19:42 +0100)
src/hooks/dhcp/bootp/bootp_callouts.cc
src/hooks/dhcp/bootp/bootp_messages.cc
src/hooks/dhcp/bootp/bootp_messages.h
src/hooks/dhcp/bootp/bootp_messages.mes

index 47026fecc99e3335fe67a9898ed8e267748b61da..3d706be87cb520122a54cc6b592b5993bd3351d7 100644 (file)
@@ -10,6 +10,8 @@
 #include <dhcp/pkt4.h>
 #include <stats/stats_mgr.h>
 
+#include <vector>
+
 using namespace isc;
 using namespace isc::bootp;
 using namespace isc::dhcp;
@@ -17,6 +19,35 @@ using namespace isc::hooks;
 using namespace isc::log;
 using namespace isc::stats;
 
+namespace {
+
+// DHCP Specific options listed in RFC 1533 section 9 and with a code name
+// beginning by DH0_DHCP_.
+const std::vector<uint16_t> DHCP_SPECIFIC_OPTIONS = {
+    DHO_DHCP_REQUESTED_ADDRESS,
+    DHO_DHCP_LEASE_TIME,
+    DHO_DHCP_OPTION_OVERLOAD,
+    DHO_DHCP_MESSAGE_TYPE,
+    DHO_DHCP_SERVER_IDENTIFIER,
+    DHO_DHCP_PARAMETER_REQUEST_LIST,
+    DHO_DHCP_MESSAGE,
+    DHO_DHCP_MAX_MESSAGE_SIZE,
+    DHO_DHCP_RENEWAL_TIME,
+    DHO_DHCP_REBINDING_TIME,
+    DHO_DHCP_CLIENT_IDENTIFIER
+};
+
+// Size of the BOOTP space for vendor extensions.
+const size_t BOOT_VENDOR_SPACE_SIZE = 64;
+
+// Minimum size of a BOOTP message.
+const size_t BOOT_MIN_SIZE = Pkt4::DHCPV4_PKT_HDR_LEN + BOOT_VENDOR_SPACE_SIZE;
+
+// Check as compile time it is really 300!
+static_assert(BOOT_MIN_SIZE == 300, "BOOT_MIN_SIZE is not 300");
+
+} // end of anonymous namespace.
+
 // Functions accessed by the hooks framework use C linkage to avoid the name
 // mangling that accompanies use of the C++ compiler as well as to avoid
 // issues related to namespaces.
@@ -82,6 +113,60 @@ int buffer4_receive(CalloutHandle& handle) {
     return (0);
 }
 
+/// @brief This callout is called at the "pkt4_send" hook.
+///
+/// Remove DHCP specific options and pad the buffer to 300 octets.
+///
+/// @param handle CalloutHandle.
+///
+/// @return 0 upon success, non-zero otherwise.
+int pkt4_send(CalloutHandle& handle) {
+    // Get the query message.
+    Pkt4Ptr query;
+    handle.getArgument("query4", query);
+
+    // Check if it is a BOOTP query.
+    if (!query->inClass("BOOTP")) {
+       return (0);
+    }
+
+    // Get the response message.
+    Pkt4Ptr response;
+    handle.getArgument("response4", response);
+
+    // @todo check if exists and/or already packed.
+
+    for (uint16_t code : DHCP_SPECIFIC_OPTIONS) {
+       while (response->delOption(code))
+           ;
+    }
+
+    // Pack the response.
+    try {
+       LOG_DEBUG(bootp_logger, DBGLVL_TRACE_BASIC, BOOTP_PACKET_PACK)
+           .arg(response->getLabel());
+       response->pack();
+
+       // The pack method adds a DHO_END option at the end.
+       isc::util::OutputBuffer& buffer = response->getBuffer();
+       size_t size = buffer.getLength();
+       if (size < BOOT_MIN_SIZE) {
+           size_t delta = BOOT_MIN_SIZE - size;
+           std::vector<uint8_t> zeros(delta, 0);
+           buffer.writeData(&zeros[0], delta);
+       }
+    } catch (const std::exception& ex) {
+       LOG_ERROR(bootp_logger, BOOTP_PACKET_PACK_FAIL)
+           .arg(response->getLabel())
+           .arg(ex.what());
+    }
+
+    // Avoid to pack it a second time!
+    handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
+
+    return (0);
+}
+
 /// @brief This function is called when the library is loaded.
 ///
 /// @return always 0.
index c097ffd0ba274f12657cc14512dec52086190611..9bcf2ec2bc29bc3d1bc67e2ab98eb67957f0e7b5 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/bootp/bootp_messages.mes on Mon Jan 20 2020 17:15
+// File created from ../../../../src/hooks/dhcp/bootp/bootp_messages.mes on Wed Jan 22 2020 19:48
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -7,6 +7,8 @@
 extern const isc::log::MessageID BOOTP_BOOTP_QUERY = "BOOTP_BOOTP_QUERY";
 extern const isc::log::MessageID BOOTP_LOAD = "BOOTP_LOAD";
 extern const isc::log::MessageID BOOTP_PACKET_OPTIONS_SKIPPED = "BOOTP_PACKET_OPTIONS_SKIPPED";
+extern const isc::log::MessageID BOOTP_PACKET_PACK = "BOOTP_PACKET_PACK";
+extern const isc::log::MessageID BOOTP_PACKET_PACK_FAIL = "BOOTP_PACKET_PACK_FAIL";
 extern const isc::log::MessageID BOOTP_PACKET_UNPACK_FAILED = "BOOTP_PACKET_UNPACK_FAILED";
 extern const isc::log::MessageID BOOTP_UNLOAD = "BOOTP_UNLOAD";
 
@@ -16,6 +18,8 @@ const char* values[] = {
     "BOOTP_BOOTP_QUERY", "recognized a BOOTP query: %1",
     "BOOTP_LOAD", "Bootp hooks library has been loaded",
     "BOOTP_PACKET_OPTIONS_SKIPPED", "an error upacking an option, caused subsequent options to be skipped: %1",
+    "BOOTP_PACKET_PACK", "%1: preparing on-wire format of the packet to be sent",
+    "BOOTP_PACKET_PACK_FAIL", "%1: preparing on-wire-format of the packet to be sent failed %2",
     "BOOTP_PACKET_UNPACK_FAILED", "failed to parse query from %1 to %2, received over interface %3, reason: %4",
     "BOOTP_UNLOAD", "Bootp hooks library has been unloaded",
     NULL
index 29bb524a9481b0c04f5802160187174f83a80734..c3cd9038676c5050275e99c0bb11360889210c45 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../../src/hooks/dhcp/bootp/bootp_messages.mes on Mon Jan 20 2020 17:15
+// File created from ../../../../src/hooks/dhcp/bootp/bootp_messages.mes on Wed Jan 22 2020 19:48
 
 #ifndef BOOTP_MESSAGES_H
 #define BOOTP_MESSAGES_H
@@ -8,6 +8,8 @@
 extern const isc::log::MessageID BOOTP_BOOTP_QUERY;
 extern const isc::log::MessageID BOOTP_LOAD;
 extern const isc::log::MessageID BOOTP_PACKET_OPTIONS_SKIPPED;
+extern const isc::log::MessageID BOOTP_PACKET_PACK;
+extern const isc::log::MessageID BOOTP_PACKET_PACK_FAIL;
 extern const isc::log::MessageID BOOTP_PACKET_UNPACK_FAILED;
 extern const isc::log::MessageID BOOTP_UNLOAD;
 
index 1f6d147bb85f4dae7bae2f10f69e5e1b699bebcc..40880981fd1132862b4ba1d9d911805253f27ef3 100644 (file)
@@ -14,6 +14,16 @@ impossible to unpack the remaining options in the DHCPv4 query. The server
 will still attempt to service the packet. The sole argument provides a
 reason for unpacking error.
 
+% BOOTP_PACKET_PACK %1: preparing on-wire format of the packet to be sent
+This debug message is issued when the server starts preparing the on-wire
+format of the packet to be sent back to the client. The argument specifies
+the client and the transaction identification information.
+
+% BOOTP_PACKET_PACK_FAIL %1: preparing on-wire-format of the packet to be sent failed %2
+This error message is issued when preparing an on-wire format of the
+packet has failed. The first argument identifies the client and the
+BOOTP transaction.  The second argument includes the error string.
+
 % BOOTP_PACKET_UNPACK_FAILED failed to parse query from %1 to %2, received over interface %3, reason: %4
 This debug message is issued when received DHCPv4 query is malformed and
 can't be parsed by the buffer4_receive callout. The query will be