diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 11:36:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 11:36:04 +0000 |
commit | 040eee1aa49b49df4698d83a05af57c220127fd1 (patch) | |
tree | f635435954e6ccde5eee9893889e24f30ca68346 /src/lib/dhcp/opaque_data_tuple.h | |
parent | Initial commit. (diff) | |
download | isc-kea-upstream.tar.xz isc-kea-upstream.zip |
Adding upstream version 2.2.0.upstream/2.2.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dhcp/opaque_data_tuple.h')
-rw-r--r-- | src/lib/dhcp/opaque_data_tuple.h | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/src/lib/dhcp/opaque_data_tuple.h b/src/lib/dhcp/opaque_data_tuple.h new file mode 100644 index 0000000..5993fc9 --- /dev/null +++ b/src/lib/dhcp/opaque_data_tuple.h @@ -0,0 +1,290 @@ +// Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef OPAQUE_DATA_TUPLE_H +#define OPAQUE_DATA_TUPLE_H + +#include <dhcp/option.h> +#include <util/buffer.h> +#include <util/io_utilities.h> + +#include <iostream> +#include <iterator> +#include <string> +#include <vector> + +namespace isc { +namespace dhcp { + +/// @brief Exception to be thrown when the operation on @c OpaqueDataTuple +/// object results in an error. +class OpaqueDataTupleError : public Exception { +public: + OpaqueDataTupleError(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) { }; +}; + + +/// @brief Represents a single instance of the opaque data preceded by length. +/// +/// Some of the DHCP options, such as Vendor Class option (16) in DHCPv6 or +/// V-I Vendor Class option (124) in DHCPv4 may carry multiple pairs of +/// opaque-data preceded by its length. Such pairs are called tuples. This class +/// represents a single instance of the tuple in the DHCPv4 or DHCPv6 option. +/// +/// Although, the primary purpose of this class is to represent data tuples in +/// Vendor Class options, there may be other options defined in the future that +/// may have similar structure and this class can be used to represent the data +/// tuples in these new options too. +/// +/// This class exposes a set of convenience methods to assign and retrieve the +/// opaque data from the tuple. It also implements a method to render the tuple +/// data into a wire format, as well as a method to create an instance of the +/// tuple from the wire format. +class OpaqueDataTuple { +public: + + /// @brief Size of the length field in the tuple. + /// + /// In the wire format, the tuple consists of the two fields: one holding + /// a length of the opaque data size, second holding opaque data. The first + /// field's size may be equal to 1 or 2 bytes. Usually, the tuples carried + /// in the DHCPv6 options have 2 byte long length fields, the tuples carried + /// in DHCPv4 options have 1 byte long length fields. + enum LengthFieldType { + LENGTH_1_BYTE, + LENGTH_2_BYTES + }; + + /// @brief Defines a type of the data buffer used to hold the opaque data. + using Buffer = std::vector<uint8_t>; + using InputIterator = Buffer::const_iterator; + + /// @brief Default constructor. + /// + /// @param length_field_type Indicates a length of the field which holds + /// the size of the tuple. + OpaqueDataTuple(LengthFieldType length_field_type); + + /// @brief Constructor + /// + /// Creates a tuple from on-wire data. It calls @c OpaqueDataTuple::unpack + /// internally. + /// + /// @param length_field_type Indicates the length of the field holding the + /// opaque data size. + /// @param begin Iterator pointing to the beginning of the buffer holding + /// wire data. + /// @param end Iterator pointing to the end of the buffer holding wire data. + /// @throw It may throw an exception if the @c unpack throws. + OpaqueDataTuple(LengthFieldType length_field_type, + InputIterator begin, + InputIterator end) + : length_field_type_(length_field_type) { + unpack(begin, end); + } + + /// @brief Appends data to the tuple. + /// + /// This function appends the data of the specified length to the tuple. + /// If the specified buffer length is greater than the size of the buffer, + /// the behavior of this function is undefined. + /// + /// @param data Iterator pointing to the beginning of the buffer being + /// appended. The source buffer may be an STL object or an array of + /// characters. In the latter case, the pointer to the beginning of this + /// array should be passed. + /// @param len Length of the source buffer. + /// @tparam InputIterator Type of the iterator pointing to the beginning of + /// the source buffer. + void append(const char* data, const size_t len) { + data_.insert(data_.end(), data, data + len); + } + void append(InputIterator data, const size_t len) { + data_.insert(data_.end(), data, data + len); + } + + /// @brief Appends string to the tuple. + /// + /// In most cases, the tuple will carry a string. This function appends the + /// string to the tuple. + /// + /// @param text String to be appended in the tuple. + void append(const std::string& text); + + /// @brief Assigns data to the tuple. + /// + /// This function replaces existing data in the tuple with the new data. + /// If the specified buffer length is greater than the size of the buffer, + /// the behavior of this function is undefined. + /// @param data Iterator pointing to the beginning of the buffer being + /// assigned. The source buffer may be an STL object or an array of + /// characters. In the latter case, the pointer to the beginning of this + /// array should be passed. + /// @param len Length of the source buffer. + void assign(const char* data, const size_t len) { + data_.assign(data, data + len); + } + void assign(InputIterator data, const size_t len) { + data_.assign(data, data + len); + } + + /// @brief Assigns string data to the tuple. + /// + /// In most cases, the tuple will carry a string. This function sets the + /// string to the tuple. + /// + /// @param text String to be assigned to the tuple. + void assign(const std::string& text); + + /// @brief Removes the contents of the tuple. + void clear(); + + /// @brief Checks if the data carried in the tuple match the string. + /// + /// @param other String to compare tuple data against. + bool equals(const std::string& other) const; + + /// @brief Returns tuple length data field type. + LengthFieldType getLengthFieldType() const { + return (length_field_type_); + } + + /// @brief Returns the length of the data in the tuple. + size_t getLength() const { + return (data_.size()); + } + + /// @brief Returns a total size of the tuple, including length field. + size_t getTotalLength() const { + return (getDataFieldSize() + getLength()); + } + + /// @brief Returns a reference to the buffer holding tuple data. + /// + /// @warning The returned reference is valid only within the lifetime + /// of the object which returned it. The use of the returned reference + /// after the object has been destroyed yelds undefined behavior. + const Buffer& getData() const { + return (data_); + } + + /// @brief Return the tuple data in the textual format. + std::string getText() const; + + /// @brief Renders the tuple to a buffer in the wire format. + /// + /// This function creates the following wire representation of the tuple: + /// - 1 or 2 bytes holding a length of the data. + /// - variable number of bytes holding data. + /// and writes it to the specified buffer. The new are appended to the + /// buffer, so as data existing in the buffer is preserved. + /// + /// The tuple is considered malformed if one of the following occurs: + /// - the size of the data is 0 (tuple is empty), + /// - the size of the data is greater than 255 and the size of the length + /// field is 1 byte (see @c LengthFieldType). + /// - the size of the data is greater than 65535 and the size of the length + /// field is 2 bytes (see @c LengthFieldType). + /// + /// Function will throw an exception if trying to render malformed tuple. + /// + /// @param [out] buf Buffer to which the data is rendered. + /// + /// @throw OpaqueDataTupleError if failed to render the data to the + /// buffer because the tuple is malformed. + void pack(isc::util::OutputBuffer& buf) const; + + /// @brief Parses wire data and creates a tuple from it. + /// + /// This function parses on-wire data stored in the provided buffer and + /// stores it in the tuple object. The wire data must include at least the + /// data field of the length matching the specified @c LengthFieldType. + /// The remaining buffer length (excluding the length field) must be equal + /// or greater than the length carried in the length field. If any of these + /// two conditions is not met, an exception is thrown. + /// + /// This function allows opaque data with the length of 0. + /// + /// @param begin Iterator pointing to the beginning of the buffer holding + /// wire data. + /// @param end Iterator pointing to the end of the buffer holding wire data. + /// @tparam InputIterator Type of the iterators passed to this function. + void unpack(InputIterator begin, InputIterator end); + + /// @name Assignment and comparison operators. + //{@ + + /// @brief Assignment operator. + /// + /// This operator assigns the string data to the tuple. + /// + /// @param other string to be assigned to the tuple. + /// @return Tuple object after assignment. + OpaqueDataTuple& operator=(const std::string& other); + + /// @brief Equality operator. + /// + /// This operator compares the string given as an argument to the data + /// carried in the tuple in the textual format. + /// + /// @param other String to compare the tuple against. + /// @return true if data carried in the tuple is equal to the string. + bool operator==(const std::string& other) const; + + /// @brief Inequality operator. + /// + /// This operator compares the string given as an argument to the data + /// carried in the tuple for inequality. + /// + /// @param other String to compare the tuple against. + /// @return true if the data carried in the tuple is unequal the given + /// string. + bool operator!=(const std::string& other); + //@} + + /// @brief Returns the size of the tuple length field. + /// + /// The returned value depends on the @c LengthFieldType set for the tuple. + int getDataFieldSize() const; + +private: + + /// @brief Buffer which holds the opaque tuple data. + Buffer data_; + + /// @brief Holds a type of tuple size field (1 byte long or 2 bytes long). + LengthFieldType length_field_type_; +}; + +/// @brief Pointer to the @c OpaqueDataTuple object. +typedef boost::shared_ptr<OpaqueDataTuple> OpaqueDataTuplePtr; + +/// @brief Inserts the @c OpaqueDataTuple as a string into stream. +/// +/// This operator gets the tuple data in the textual format and inserts it +/// into the output stream. +/// +/// @param os Stream object on which insertion is performed. +/// @param tuple Object encapsulating a tuple which data in the textual format +/// is inserted into the stream. +/// @return Reference to the same stream but after insertion operation. +std::ostream& operator<<(std::ostream& os, const OpaqueDataTuple& tuple); + +/// @brief Inserts data carried in the stream into the tuple. +/// +/// this operator inserts data carried in the input stream and inserts it to +/// the @c OpaqueDataTuple object. The existing data is replaced with new data. +/// +/// @param is Input stream from which the data will be inserted. +/// @param tuple @c OpaqueDataTuple object to which the data will be inserted. +/// @return Input stream after insertion to the tuple is performed. +std::istream& operator>>(std::istream& is, OpaqueDataTuple& tuple); + +} // namespace isc::dhcp +} // namespace isc + +#endif |