/* * Copyright (c) 2017, Matias Fontanini * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef TINS_IP_H #define TINS_IP_H #include #include #include #include #include #include #include namespace Tins { namespace Memory { class OutputMemoryStream; } // Memory /** * \class IP * \brief Class that represents an IP PDU. * * By default, IP PDUs are initialized, setting TTL to IP::DEFAULT_TTL, * id field to 1 and version to 4. Taking this into account, users * should set destination and source port and would be enough to send one. * * When IP is the lowest layer on a packet, and the packet is serialized * this willc heck if the source address is different than 0.0.0.0. If it is, * the address of the interface in which the packet is going to be sent * is retrieved (by using the routing table and the destination address) * and set as the source address. If you don't want this behaviour, simply * set the source address to 0.0.0.0. */ class TINS_API IP : public PDU { public: /** * This PDU's flag. */ static const PDU::PDUType pdu_flag = PDU::IP; /** * The type used to store addresses. */ typedef IPv4Address address_type; /** * Type used to represent the different IP flags. */ enum Flags { FLAG_RESERVED = 4, DONT_FRAGMENT = 2, MORE_FRAGMENTS = 1 }; /** * \brief Enum indicating the option's class. * * Enum OptionClass represents the different classes of * IP Options. */ enum OptionClass { CONTROL = 0, MEASUREMENT = 2 }; /** * \brief Enum indicating the option's id number. * * Enum Option indicates the possible IP Options. */ enum OptionNumber { END = 0, NOOP = 1, SEC = 2, LSRR = 3, TIMESTAMP = 4, EXTSEC = 5, RR = 7, SID = 8, SSRR = 9, MTUPROBE = 11, MTUREPLY = 12, EIP = 17, TR = 18, ADDEXT = 19, RTRALT = 20, SDB = 21, DPS = 23, UMP = 24, QS = 25 }; /** * \brief The type used to represent an option's type. */ TINS_BEGIN_PACK struct option_identifier { #if TINS_IS_LITTLE_ENDIAN uint8_t number:5, op_class:2, copied:1; #elif TINS_IS_BIG_ENDIAN uint8_t copied:1, op_class:2, number:5; #endif /** * \brief Default constructor. * * Initializes every field to 0. */ option_identifier() #if TINS_IS_LITTLE_ENDIAN : number(0), op_class(0), copied(0) {} #else : copied(0), op_class(0), number(0) {} #endif /** * \brief Constructs this option from a single uint8_t value. * * This parses the value and initializes each field with the * appropriate value. * * \param value The value to be parsed and used for * initialization */ option_identifier(uint8_t value) #if TINS_IS_LITTLE_ENDIAN : number(value & 0x1f), op_class((value >> 5) & 0x03), copied((value >> 7) & 0x01) {} #elif TINS_IS_BIG_ENDIAN : copied((value >> 7) & 0x01), op_class((value >> 5) & 0x03), number(value & 0x1f) {} #endif /** * Constructor using user provided values for each field. * \param number The number field value. * \param op_class The option class field value. * \param copied The copied field value. */ option_identifier(OptionNumber number, OptionClass op_class, small_uint<1> copied) #if TINS_IS_LITTLE_ENDIAN : number(static_cast(number)), op_class(static_cast(op_class)), copied(copied) {} #else : copied(copied), op_class(static_cast(op_class)), number(static_cast(number)) {} #endif /** * \brief Equality operator. */ bool operator==(const option_identifier& rhs) const { return number == rhs.number && op_class == rhs.op_class && copied == rhs.copied; } } TINS_END_PACK; /** * The IP options type. */ typedef PDUOption option; /** * The type of the security option. */ struct security_type { uint16_t security, compartments; uint16_t handling_restrictions; small_uint<24> transmission_control; security_type(uint16_t sec = 0, uint16_t comp = 0, uint16_t hand_res = 0, small_uint<24> tcc = 0) : security(sec), compartments(comp), handling_restrictions(hand_res), transmission_control(tcc) { } static security_type from_option(const option& opt); }; /** * The type of the Loose Source and Record Route */ struct generic_route_option_type { typedef std::vector routes_type; uint8_t pointer; routes_type routes; generic_route_option_type(uint8_t ptr = 0, routes_type rts = routes_type()) : pointer(ptr), routes(rts) {} static generic_route_option_type from_option(const option& opt); }; /** * The type of the Loose Source and Record Route */ typedef generic_route_option_type lsrr_type; /** * The type of the Strict Source and Record Route */ typedef generic_route_option_type ssrr_type; /** * The type of the Record Route */ typedef generic_route_option_type record_route_type; /** * The type used to store IP options. */ typedef std::vector