diff --git a/include/tins/ip.h b/include/tins/ip.h index 72b25ff..773acf6 100644 --- a/include/tins/ip.h +++ b/include/tins/ip.h @@ -68,6 +68,15 @@ namespace Tins { */ 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. * @@ -292,10 +301,36 @@ namespace Tins { /** * \brief Getter for the fragment offset field. + * + * This method is deprecated. Use IP::fragment_offset and IP::flags. * + * \deprecated * \return The fragment offset for this IP PDU. + * \sa IP::fragment_offset + * \sa IP::flags */ - uint16_t frag_off() const { return Endian::be_to_host(_ip.frag_off); } + TINS_DEPRECATED(uint16_t frag_off() const) { return Endian::be_to_host(_ip.frag_off); } + + /** + * \brief Getter for the fragment offset field. + * + * This will return the fragment offset field, as present in the packet, + * which indicates the offset of this fragment in blocks of 8 bytes. + * + * \return The fragment offset, measured in units of 8 byte blocks + */ + small_uint<13> fragment_offset() const { + return Endian::be_to_host(_ip.frag_off) & 0x1fff; + } + + /** + * \brief Getter for the flags field. + * + * \return The IP flags field + */ + Flags flags() const { + return static_cast((_ip.frag_off & 0xe0) >> 5); + } /** * \brief Getter for the time to live field. @@ -362,9 +397,32 @@ namespace Tins { /** * \brief Setter for the fragment offset field. * + * This method is deprecated. Use IP::fragment_offset and IP::flags. + * + * \deprecated * \param new_frag_off The new fragment offset. + * \sa IP::fragment_offset + * \sa IP::flags */ - void frag_off(uint16_t new_frag_off); + TINS_DEPRECATED(void frag_off(uint16_t new_frag_off)); + + /** + * \brief Setter for the fragment offset field. + * + * The value provided is measured in units of 8 byte blocks. This means that + * if you want this packet to have a fragment offset of X, + * you need to provide X / 8 as the argument to this method. + * + * \param new_frag_off The new fragment offset, measured in units of 8 byte blocks. + */ + void fragment_offset(small_uint<13> new_frag_off); + + /** + * \brief Setter for the flags field. + * + * \param new_flags The new IP flags field value. + */ + void flags(Flags new_flags); /** * \brief Setter for the time to live field. diff --git a/src/ip.cpp b/src/ip.cpp index 2aa8cdd..e9af2ff 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -157,9 +157,7 @@ void IP::init_ip_fields() { } bool IP::is_fragmented() const { - // It's 0 if offset == 0 && more_frag == 0 - // It's 0x4000 if dont_fragment = 1 - return frag_off() != 0 && frag_off() != 0x4000; + return flags() == IP::MORE_FRAGMENTS || fragment_offset() != 0; } /* Setters */ @@ -180,6 +178,14 @@ void IP::frag_off(uint16_t new_frag_off) { _ip.frag_off = Endian::host_to_be(new_frag_off); } +void IP::fragment_offset(small_uint<13> new_frag_off) { + _ip.frag_off = (_ip.frag_off & 0xe0) | Endian::host_to_be(new_frag_off); +} + +void IP::flags(Flags new_flags) { + _ip.frag_off = (_ip.frag_off & 0xff1f) | (new_flags << 5); +} + void IP::ttl(uint8_t new_ttl) { _ip.ttl = new_ttl; } diff --git a/src/ip_reassembler.cpp b/src/ip_reassembler.cpp index c3120f8..afb80e5 100644 --- a/src/ip_reassembler.cpp +++ b/src/ip_reassembler.cpp @@ -52,7 +52,7 @@ void IPv4Stream::add_fragment(IP *ip) { return; fragments.insert(it, IPv4Fragment(ip->inner_pdu(), offset)); received_size += ip->inner_pdu()->size(); - if(!extract_more_frag(ip)) { + if(ip->flags() != IP::MORE_FRAGMENTS) { total_size = offset + ip->inner_pdu()->size(); received_end = true; } @@ -83,12 +83,9 @@ PDU *IPv4Stream::allocate_pdu() const { } uint16_t IPv4Stream::extract_offset(const IP *ip) { - return (ip->frag_off() & 0x1fff) * 8; + return ip->fragment_offset() * 8; } -bool IPv4Stream::extract_more_frag(const IP *ip) { - return (ip->frag_off() & 0x2000) != 0; -} } // namespace Internals IPv4Reassembler::IPv4Reassembler(overlapping_technique technique) diff --git a/tests/src/ip.cpp b/tests/src/ip.cpp index c31d3f5..e42ede9 100644 --- a/tests/src/ip.cpp +++ b/tests/src/ip.cpp @@ -526,12 +526,6 @@ TEST_F(IPTest, ID) { EXPECT_EQ(ip.id(), 0x7f1a); } -TEST_F(IPTest, FragOffset) { - IP ip; - ip.frag_off(0x7f1a); - EXPECT_EQ(ip.frag_off(), 0x7f1a); -} - TEST_F(IPTest, TTL) { IP ip; ip.ttl(0x7f); @@ -640,7 +634,8 @@ void IPTest::test_equals(const IP &ip1, const IP &ip2) { EXPECT_EQ(ip1.dst_addr(), ip2.dst_addr()); EXPECT_EQ(ip1.src_addr(), ip2.src_addr()); EXPECT_EQ(ip1.id(), ip2.id()); - EXPECT_EQ(ip1.frag_off(), ip2.frag_off()); + EXPECT_EQ(ip1.fragment_offset(), ip2.fragment_offset()); + EXPECT_EQ(ip1.flags(), ip2.flags()); EXPECT_EQ(ip1.tos(), ip2.tos()); EXPECT_EQ(ip1.ttl(), ip2.ttl()); EXPECT_EQ(ip1.version(), ip2.version()); @@ -654,7 +649,7 @@ TEST_F(IPTest, ConstructorFromBuffer) { EXPECT_EQ(ip.src_addr(), "84.52.254.5"); EXPECT_EQ(ip.id(), 0x7a); EXPECT_EQ(ip.tos(), 0x7f); - EXPECT_EQ(ip.frag_off(), 0x43); + EXPECT_EQ(ip.fragment_offset(), 0x43); EXPECT_EQ(ip.protocol(), 1); EXPECT_EQ(ip.ttl(), 0x15); EXPECT_EQ(ip.version(), 2); @@ -759,3 +754,32 @@ TEST_F(IPTest, OverwriteSourceAddressConstructingFromBuffer) { test_overwrite_source_address(ip); } #endif + +TEST_F(IPTest, FragmentOffset) { + const uint8_t packet[] = { + 69, 0, 5, 220, 53, 162, 32, 185, 64, 17, 168, 159, 192, 168, 0, 100, 176, 5, 5, 5, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65 + }; + IP ip(packet, sizeof(packet)); + EXPECT_EQ(0xb9, ip.fragment_offset()); + EXPECT_EQ(IP::MORE_FRAGMENTS, ip.flags()); + EXPECT_TRUE(ip.is_fragmented()); + + ip.fragment_offset(0x1fff); + EXPECT_EQ(0x1fff, ip.fragment_offset()); + EXPECT_EQ(IP::MORE_FRAGMENTS, ip.flags()); + + ip.flags(IP::DONT_FRAGMENT); + EXPECT_EQ(0x1fff, ip.fragment_offset()); + EXPECT_EQ(IP::DONT_FRAGMENT, ip.flags()); + + ip.flags(IP::FLAG_RESERVED); + ip.fragment_offset(0x1aed); + EXPECT_EQ(IP::FLAG_RESERVED, ip.flags()); + EXPECT_EQ(0x1aed, ip.fragment_offset()); + + ip.flags(static_cast(0)); + ip.fragment_offset(0); + EXPECT_FALSE(ip.is_fragmented()); + ip.flags(IP::DONT_FRAGMENT); + EXPECT_FALSE(ip.is_fragmented()); +}