123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- // Copyright (C) 2011-2013 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 <asiolink/io_address.h>
- #include <util/buffer.h>
- #include <dhcp/option.h>
- #include <dhcp/hwaddr.h>
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <boost/shared_ptr.hpp>
- #include <iostream>
- #include <vector>
- #include <time.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;
- /// Mask for the value of flags field in the DHCPv4 message
- /// to check whether client requested broadcast response.
- const static uint16_t FLAG_BROADCAST_MASK = 0x8000;
- /// 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 buffer_out_.
- ///
- /// @throw InvalidOperation if packing fails
- void
- 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 buffer_out_. 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 Sets transaction-id value
- ///
- /// @param transid transaction-id to be set.
- void setTransid(uint32_t transid) { transid_ = transid; }
- /// @brief Returns value of transaction-id field.
- ///
- /// @return transaction-id
- uint32_t getTransid() const { return (transid_); };
- /// @brief Returns DHCP message type (e.g. 1 = DHCPDISCOVER).
- ///
- /// @return message type
- uint8_t getType() const;
- /// @brief Sets DHCP message type (e.g. 1 = DHCPDISCOVER).
- ///
- /// @param type message type to be set
- void setType(uint8_t 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<uint8_t>(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<uint8_t>(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 mac_addr buffer. Content of mac_addr buffer
- /// will be copied to appropriate field.
- ///
- /// Note: mac_addr 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 mac_addr pointer to hardware address
- void setHWAddr(uint8_t htype, uint8_t hlen,
- const std::vector<uint8_t>& mac_addr);
- /// @brief Sets hardware address
- ///
- /// Sets hardware address, based on existing HWAddr structure
- /// @param addr already filled in HWAddr structure
- /// @throw BadValue if addr is null
- void setHWAddr(const HWAddrPtr& addr);
- /// Returns htype field
- ///
- /// @return hardware type
- uint8_t
- getHtype() const;
- /// Returns hlen field
- ///
- /// @return hardware address length
- uint8_t
- getHlen() const;
- /// @brief returns hardware address information
- /// @return hardware address structure
- HWAddrPtr getHWAddr() const { return (hwaddr_); }
- /// @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. This buffer is returned as non-const, so hooks
- /// framework (and user's callouts) can modify them if needed
- ///
- /// @return reference to output buffer
- isc::util::OutputBuffer&
- getBuffer() { return (buffer_out_); };
- /// @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<Option> opt);
- /// @brief Returns an option of specified type.
- ///
- /// @return returns option of requested type (or NULL)
- /// if no such option is present
- boost::shared_ptr<Option>
- getOption(uint8_t opt_type) const;
- /// @brief Deletes specified option
- /// @param type option type to be deleted
- /// @return true if anything was deleted, false otherwise
- bool delOption(uint8_t type);
- /// @brief Returns interface name.
- ///
- /// Returns interface name over which packet was received or is
- /// going to be transmitted.
- ///
- /// @return interface name
- std::string getIface() const { return iface_; };
- /// @brief Returns packet timestamp.
- ///
- /// Returns packet timestamp value updated when
- /// packet is received or send.
- ///
- /// @return packet timestamp.
- const boost::posix_time::ptime& getTimestamp() const { return timestamp_; }
- /// @brief Sets interface name.
- ///
- /// Sets interface name over which packet was received or is
- /// going to be transmitted.
- ///
- /// @return interface name
- void setIface(const std::string& iface ) { iface_ = iface; };
- /// @brief Sets interface index.
- ///
- /// @param ifindex specifies interface index.
- void setIndex(uint32_t ifindex) { ifindex_ = ifindex; };
- /// @brief Returns interface index.
- ///
- /// @return interface index
- uint32_t getIndex() const { return (ifindex_); };
- /// @brief Sets remote HW address.
- ///
- /// Sets the destination HW address for the outgoing packet
- /// or source HW address for the incoming packet. When this
- /// is an outgoing packet this address will be used to construct
- /// the link layer header.
- ///
- /// @note mac_addr 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 mac_addr pointer to hardware address
- void setRemoteHWAddr(const uint8_t htype, const uint8_t hlen,
- const std::vector<uint8_t>& mac_addr);
- /// @brief Sets remote HW address.
- ///
- /// Sets hardware address from an existing HWAddr structure.
- /// The remote address is a destination address for outgoing
- /// packet and source address for incoming packet. When this
- /// is an outgoing packet, this address will be used to
- /// construct the link layer header.
- ///
- /// @param addr structure representing HW address.
- ///
- /// @throw BadValue if addr is null
- void setRemoteHWAddr(const HWAddrPtr& addr);
- /// @brief Returns the remote HW address.
- ///
- /// @return remote HW address.
- HWAddrPtr getRemoteHWAddr() const {
- return (remote_hwaddr_);
- }
- /// @brief Sets local HW address.
- ///
- /// Sets the source HW address for the outgoing packet or
- /// destination HW address for the incoming packet.
- ///
- /// @note mac_addr 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 mac_addr pointer to hardware address
- void setLocalHWAddr(const uint8_t htype, const uint8_t hlen,
- const std::vector<uint8_t>& mac_addr);
- /// @brief Sets local HW address.
- ///
- /// Sets hardware address from an existing HWAddr structure.
- /// The local address is a source address for outgoing
- /// packet and destination address for incoming packet.
- ///
- /// @param addr structure representing HW address.
- ///
- /// @throw BadValue if addr is null
- void setLocalHWAddr(const HWAddrPtr& addr);
- /// @brief Returns local HW address.
- ///
- /// @return local HW addr.
- HWAddrPtr getLocalHWAddr() const {
- return (local_hwaddr_);
- }
- /// @brief Sets remote address.
- ///
- /// @param remote specifies remote address
- void setRemoteAddr(const isc::asiolink::IOAddress& remote) {
- remote_addr_ = remote;
- }
- /// @brief Returns remote address
- ///
- /// @return remote address
- const isc::asiolink::IOAddress& getRemoteAddr() const {
- return (remote_addr_);
- }
- /// @brief Sets local address.
- ///
- /// @param local specifies local address
- void setLocalAddr(const isc::asiolink::IOAddress& local) {
- local_addr_ = local;
- }
- /// @brief Returns local address.
- ///
- /// @return local address
- const isc::asiolink::IOAddress& getLocalAddr() const {
- return (local_addr_);
- }
- /// @brief Sets local port.
- ///
- /// @param local specifies local port
- void setLocalPort(uint16_t local) { local_port_ = local; }
- /// @brief Returns local port.
- ///
- /// @return local port
- uint16_t getLocalPort() const { return (local_port_); }
- /// @brief Sets remote port.
- ///
- /// @param remote specifies remote port
- void setRemotePort(uint16_t remote) { remote_port_ = remote; }
- /// @brief Returns remote port.
- ///
- /// @return remote port
- uint16_t getRemotePort() const { return (remote_port_); }
- /// @brief Update packet timestamp.
- ///
- /// Updates packet timestamp. This method is invoked
- /// by interface manager just before sending or
- /// just after receiving it.
- /// @throw isc::Unexpected if timestamp update failed
- void updateTimestamp();
- /// Output buffer (used during message transmission)
- ///
- /// @warning This public member is accessed by derived
- /// classes directly. One of such derived classes is
- /// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
- /// behavior must be taken into consideration before making
- /// changes to this member such as access scope restriction or
- /// data format change etc. This field is also public, because
- /// it may be modified by callouts (which are written in C++ now,
- /// but we expect to also have them in Python, so any accesibility
- /// methods would overly complicate things here and degrade
- /// performance).
- isc::util::OutputBuffer buffer_out_;
- /// @brief That's the data of input buffer used in RX packet.
- ///
- /// @note Note that InputBuffer does not store the data itself, but just
- /// expects that data will be valid for the whole life of InputBuffer.
- /// Therefore we need to keep the data around.
- ///
- /// @warning This public member is accessed by derived
- /// classes directly. One of such derived classes is
- /// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
- /// behavior must be taken into consideration before making
- /// changes to this member such as access scope restriction or
- /// data format change etc. This field is also public, because
- /// it may be modified by callouts (which are written in C++ now,
- /// but we expect to also have them in Python, so any accesibility
- /// methods would overly complicate things here and degrade
- /// performance).
- std::vector<uint8_t> data_;
- private:
- /// @brief Generic method that validates and sets HW address.
- ///
- /// This is a generic method used by all modifiers of this class
- /// which set class members representing HW address.
- ///
- /// @param htype hardware type.
- /// @param hlen hardware length.
- /// @param mac_addr pointer to actual hardware address.
- /// @param [out] hw_addr pointer to a class member to be modified.
- ///
- /// @trow isc::OutOfRange if invalid HW address specified.
- void setHWAddrMember(const uint8_t htype, const uint8_t hlen,
- const std::vector<uint8_t>& mac_addr,
- HWAddrPtr& hw_addr);
- protected:
- /// converts DHCP message type to BOOTP op type
- ///
- /// @param dhcpType DHCP message type (e.g. DHCPDISCOVER)
- ///
- /// @return BOOTP type (BOOTREQUEST or BOOTREPLY)
- uint8_t
- DHCPTypeToBootpType(uint8_t dhcpType);
- /// local HW address (dst if receiving packet, src if sending packet)
- HWAddrPtr local_hwaddr_;
- // remote HW address (src if receiving packet, dst if sending packet)
- HWAddrPtr remote_hwaddr_;
- /// local address (dst if receiving packet, src if sending packet)
- isc::asiolink::IOAddress local_addr_;
- /// remote address (src if receiving packet, dst if sending packet)
- isc::asiolink::IOAddress remote_addr_;
- /// name of the network interface the packet was received/to be sent over
- std::string iface_;
- /// @brief interface index
- ///
- /// Each network interface has assigned unique ifindex. It is functional
- /// equivalent of name, but sometimes more useful, e.g. when using crazy
- /// systems that allow spaces in interface names e.g. MS Windows)
- uint32_t ifindex_;
- /// local UDP port
- uint16_t local_port_;
- /// remote UDP port
- uint16_t remote_port_;
- /// @brief message operation code
- ///
- /// Note: This is legacy BOOTP field. There's no need to manipulate it
- /// directly. Its value is set based on DHCP message type. Note that
- /// DHCPv4 protocol reuses BOOTP message format, so this field is
- /// kept due to BOOTP format. This is NOT DHCPv4 type (DHCPv4 message
- /// type is kept in message type option).
- uint8_t op_;
- /// @brief link-layer address and hardware information
- /// represents 3 fields: htype (hardware type, 1 byte), hlen (length of the
- /// hardware address, up to 16) and chaddr (hardware address field,
- /// 16 bytes)
- HWAddrPtr hwaddr_;
- /// Number of relay agents traversed
- uint8_t hops_;
- /// DHCPv4 transaction-id (32 bits, not 24 bits as in DHCPv6)
- uint32_t transid_;
- /// elapsed (number of seconds since beginning of transmission)
- uint16_t secs_;
- /// flags
- uint16_t flags_;
- /// ciaddr field (32 bits): Client's IP address
- isc::asiolink::IOAddress ciaddr_;
- /// yiaddr field (32 bits): Client's IP address ("your"), set by server
- isc::asiolink::IOAddress yiaddr_;
- /// siaddr field (32 bits): next server IP address in boot process(e.g.TFTP)
- isc::asiolink::IOAddress siaddr_;
- /// giaddr field (32 bits): Gateway IP address
- isc::asiolink::IOAddress giaddr_;
- /// sname field (64 bytes)
- uint8_t sname_[MAX_SNAME_LEN];
- /// file field (128 bytes)
- uint8_t file_[MAX_FILE_LEN];
- // end of real DHCPv4 fields
- /// collection of options present in this message
- ///
- /// @warning This protected member is accessed by derived
- /// classes directly. One of such derived classes is
- /// @ref perfdhcp::PerfPkt4. The impact on derived classes'
- /// behavior must be taken into consideration before making
- /// changes to this member such as access scope restriction or
- /// data format change etc.
- isc::dhcp::Option::OptionCollection options_;
- /// packet timestamp
- boost::posix_time::ptime timestamp_;
- }; // Pkt4 class
- typedef boost::shared_ptr<Pkt4> Pkt4Ptr;
- } // isc::dhcp namespace
- } // isc namespace
- #endif
|