// Copyright (C) 2012-2024 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 LOCALIZED_OPTION_H #define LOCALIZED_OPTION_H #include #include #include namespace isc { namespace perfdhcp { /// \brief DHCP option at specific offset /// /// This class represents DHCP option with data placed at specified /// offset in DHCP message. /// Objects of this type are intended to be used when DHCP packets /// are created from templates (e.g. read from template file). /// Such packets have number of options with contents that have to be /// replaced before sending: e.g. DUID can be randomized. /// If option of this type is added to \ref PerfPkt6 options collection, /// \ref perfdhcp::PerfPkt6 will call \ref getOffset on this object /// to retrieve user-defined option position and replace contents of /// the output buffer at this offset before packet is sent to the server. /// (\see perfdhcp::PerfPkt6::rawPack). /// In order to read on-wire data from incoming packet client class /// has to specify options of \ref perfdhcp::LocalizedOption type /// with expected offsets of these options in a packet. The /// \ref perfdhcp::PerfPkt6 will use offsets to read fragments /// of packet and store them in options' buffers. /// (\see perfdhcp::PerfPkt6::rawUnpack). /// class LocalizedOption : public dhcp::Option { public: /// \brief Constructor, used to create localized option from buffer. /// /// This constructor creates localized option using whole provided /// option buffer. /// /// \param u universe (V4 or V6). /// \param type option type (0-255 for V4 and 0-65535 for V6). /// Option values 0 and 255 (v4) and 0 (v6) are not valid option /// codes but they are accepted here for the server testing purposes. /// \param data content of the option. /// \param offset location of option in a packet (zero is default). LocalizedOption(dhcp::Option::Universe u, uint16_t type, const dhcp::OptionBuffer& data, const size_t offset = 0) : dhcp::Option(u, type, data), offset_(offset), option_valid_(true) { } /// \brief Constructor, used to create option from buffer iterators. /// /// This constructor creates localized option using part of the /// option buffer pointed by iterators. /// /// \param u specifies universe (V4 or V6) /// \param type option type (0-255 for V4 and 0-65535 for V6) /// \param first iterator to the first element that should be copied /// \param last iterator to the next element after the last one /// to be copied. /// \param offset offset of option in a packet (zero is default) LocalizedOption(dhcp::Option::Universe u, uint16_t type, dhcp::OptionBufferConstIter first, dhcp::OptionBufferConstIter last, const size_t offset = 0) : dhcp::Option(u, type, first, last), offset_(offset), option_valid_(true) { } /// \brief Copy constructor, creates LocalizedOption from Option6IA. /// /// This copy constructor creates regular option from Option6IA. /// The data from Option6IA data members are copied to /// option buffer in appropriate sequence. /// /// \param opt_ia option to be copied. /// \param offset location of the option in a packet. LocalizedOption(const boost::shared_ptr& opt_ia, const size_t offset) : dhcp::Option(Option::V6, 0, dhcp::OptionBuffer()), offset_(offset), option_valid_(false) { // If given option is NULL we will mark this new option // as invalid. User may query if option is valid when // object is created. if (opt_ia) { // Set universe and type. universe_ = opt_ia->getUniverse(); type_ = opt_ia->getType(); util::OutputBuffer buf(opt_ia->len() - opt_ia->getHeaderLen()); try { // Try to pack option data into the temporary buffer. opt_ia->pack(buf); if (buf.getLength() > 0) { const uint8_t* buf_data = buf.getData(); // Option has been packed along with option type flag // and transaction id so we have to skip first 4 bytes // when copying temporary buffer option buffer. data_.assign(buf_data + 4, buf_data + buf.getLength()); } option_valid_ = true; } catch (const Exception&) { // If there was an exception somewhere when packing // the data into the buffer we assume that option is // not valid and should not be used. option_valid_ = false; } } else { option_valid_ = false; } } /// \brief Returns offset of an option in a DHCP packet. /// /// \return option offset in a packet size_t getOffset() const { return offset_; }; /// \brief Checks if option is valid. /// /// \return true, if option is valid. virtual bool valid() const { return (Option::valid() && option_valid_); } private: size_t offset_; ///< Offset of DHCP option in a packet bool option_valid_; ///< Is option valid. }; } // namespace isc::perfdhcp } // namespace isc #endif // LOCALIZED_OPTION_H