// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. #ifndef PKT4_H #define PKT4_H #include #include #include #include #include #include "asiolink/io_address.h" #include "util/buffer.h" #include "dhcp/option.h" namespace isc { namespace dhcp { class Pkt4 { public: /// length of the CHADDR field in DHCPv4 message const static size_t MAX_CHADDR_LEN = 16; /// length of the SNAME field in DHCPv4 message const static size_t MAX_SNAME_LEN = 64; /// length of the FILE field in DHCPv4 message const static size_t MAX_FILE_LEN = 128; /// specifies DHCPv4 packet header length (fixed part) const static size_t DHCPV4_PKT_HDR_LEN = 236; /// Constructor, used in replying to a message. /// /// @param msg_type type of message (e.g. DHCPDISOVER=1) /// @param transid transaction-id Pkt4(uint8_t msg_type, uint32_t transid); /// @brief Constructor, used in message reception. /// /// Creates new message. Pkt4 will copy data to bufferIn_ /// buffer on creation. /// /// @param data pointer to received data /// @param len size of buffer to be allocated for this packet. Pkt4(const uint8_t* data, size_t len); /// @brief Prepares on-wire format of DHCPv4 packet. /// /// Prepares on-wire format of message and all its options. /// Options must be stored in options_ field. /// Output buffer will be stored in bufferOut_. /// /// @return true if packing procedure was successful bool pack(); /// @brief Parses on-wire form of DHCPv4 packet. /// /// Parses received packet, stored in on-wire format in bufferIn_. /// /// Will create a collection of option objects that will /// be stored in options_ container. /// /// Method with throw exception if packet parsing fails. void unpack(); /// @brief performs sanity check on a packet. /// /// This is usually performed after unpack(). It checks if packet is sane: /// required options are present, fields have sane content etc. /// For example verifies that DHCP_MESSAGE_TYPE is present and have /// reasonable value. This method is expected to grow significantly. /// It makes sense to separate unpack() and check() for testing purposes. /// /// TODO: It is called from unpack() directly. It should be separated. /// /// Method will throw exception if anomaly is found. void check(); /// @brief Copies content of input buffer to output buffer. /// /// This is mostly a diagnostic function. It is being used for sending /// received packet. Received packet is stored in bufferIn_, but /// transmitted data is stored in bufferOut_. If we want to send packet /// that we just received, a copy between those two buffers is necessary. void repack(); /// @brief Returns text representation of the packet. /// /// This function is useful mainly for debugging. /// /// @return string with text representation std::string toText(); /// @brief Returns the size of the required buffer to build the packet. /// /// Returns the size of the required buffer to build the packet with /// the current set of packet options. /// /// @return number of bytes required to build this packet size_t len(); /// @brief Sets hops field. /// /// @param hops value to be set void setHops(uint8_t hops) { hops_ = hops; }; /// @brief Returns hops field. /// /// @return hops field uint8_t getHops() const { return (hops_); }; // Note: There's no need to manipulate OP field directly, // thus no setOp() method. See op_ comment. /// @brief Returns op field. /// /// @return op field uint8_t getOp() const { return (op_); }; /// @brief Sets secs field. /// /// @param secs value to be set void setSecs(uint16_t secs) { secs_ = secs; }; /// @brief Returns secs field. /// /// @return secs field uint16_t getSecs() const { return (secs_); }; /// @brief Sets flags field. /// /// @param flags value to be set void setFlags(uint16_t flags) { flags_ = flags; }; /// @brief Returns flags field. /// /// @return flags field uint16_t getFlags() const { return (flags_); }; /// @brief Returns ciaddr field. /// /// @return ciaddr field const isc::asiolink::IOAddress& getCiaddr() const { return (ciaddr_); }; /// @brief Sets ciaddr field. /// /// @param ciaddr value to be set void setCiaddr(const isc::asiolink::IOAddress& ciaddr) { ciaddr_ = ciaddr; }; /// @brief Returns siaddr field. /// /// @return siaddr field const isc::asiolink::IOAddress& getSiaddr() const { return (siaddr_); }; /// @brief Sets siaddr field. /// /// @param siaddr value to be set void setSiaddr(const isc::asiolink::IOAddress& siaddr) { siaddr_ = siaddr; }; /// @brief Returns yiaddr field. /// /// @return yiaddr field const isc::asiolink::IOAddress& getYiaddr() const { return (yiaddr_); }; /// @brief Sets yiaddr field. /// /// @param yiaddr value to be set void setYiaddr(const isc::asiolink::IOAddress& yiaddr) { yiaddr_ = yiaddr; }; /// @brief Returns giaddr field. /// /// @return giaddr field const isc::asiolink::IOAddress& getGiaddr() const { return (giaddr_); }; /// @brief Sets giaddr field. /// /// @param giaddr value to be set void setGiaddr(const isc::asiolink::IOAddress& giaddr) { giaddr_ = giaddr; }; /// @brief Returns value of transaction-id field. /// /// @return transaction-id uint32_t getTransid() const { return (transid_); }; /// @brief Returns message type (e.g. 1 = DHCPDISCOVER). /// /// @return message type uint8_t getType() const { return (msg_type_); } /// @brief Sets message type (e.g. 1 = DHCPDISCOVER). /// /// @param type message type to be set void setType(uint8_t type) { msg_type_=type; }; /// @brief Returns sname field /// /// Note: This is 64 bytes long field. It doesn't have to be /// null-terminated. Do not use strlen() or similar on it. /// /// @return sname field const OptionBuffer getSname() const { return (std::vector(sname_, &sname_[MAX_SNAME_LEN])); }; /// @brief Sets sname field. /// /// @param sname value to be set /// @param sname_len length of the sname buffer (up to MAX_SNAME_LEN) void setSname(const uint8_t* sname, size_t sname_len = MAX_SNAME_LEN); /// @brief Returns file field /// /// Note: This is 128 bytes long field. It doesn't have to be /// null-terminated. Do not use strlen() or similar on it. /// /// @return pointer to file field const OptionBuffer getFile() const { return (std::vector(file_, &file_[MAX_FILE_LEN])); }; /// Sets file field /// /// @param file value to be set /// @param file_len length of the file buffer (up to MAX_FILE_LEN) void setFile(const uint8_t* file, size_t file_len = MAX_FILE_LEN); /// @brief Sets hardware address. /// /// Sets parameters of hardware address. hlen specifies /// length of macAddr buffer. Content of macAddr buffer /// will be copied to appropriate field. /// /// Note: macAddr must be a buffer of at least hlen bytes. /// /// @param hType hardware type (will be sent in htype field) /// @param hlen hardware length (will be sent in hlen field) /// @param macAddr pointer to hardware address void setHWAddr(uint8_t hType, uint8_t hlen, const std::vector& macAddr); /// Returns htype field /// /// @return hardware type uint8_t getHtype() const { return (htype_); }; /// Returns hlen field /// /// @return hardware address length uint8_t getHlen() const { return (hlen_); }; /// @brief Returns chaddr field. /// /// Note: This is 16 bytes long field. It doesn't have to be /// null-terminated. Do no use strlen() or similar on it. /// /// @return pointer to hardware address const uint8_t* getChaddr() const { return (chaddr_); }; /// @brief Returns reference to output buffer. /// /// Returned buffer will contain reasonable data only for /// output (TX) packet and after pack() was called. This buffer /// is only valid till Pkt4 object is valid. /// /// RX packet or TX packet before pack() will return buffer with /// zero length /// /// @return reference to output buffer const isc::util::OutputBuffer& getBuffer() const { return (bufferOut_); }; /// @brief Add an option. /// /// Throws BadValue if option with that type is already present. /// /// @param opt option to be added void addOption(boost::shared_ptr