#include <dhcp/pkt4.h>
#include <stats/stats_mgr.h>
+#include <vector>
+
using namespace isc;
using namespace isc::bootp;
using namespace isc::dhcp;
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.
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.
-// 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>
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";
"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
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