mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Build layer 5 as RawPDU if IPv6 has fragment header
This commit is contained in:
39
src/ipv6.cpp
39
src/ipv6.cpp
@@ -82,8 +82,12 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz)
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(header_);
|
||||
uint8_t current_header = header_.next_header;
|
||||
bool is_payload_fragmented = false;
|
||||
while (stream) {
|
||||
if (is_extension_header(current_header)) {
|
||||
if (current_header == FRAGMENT) {
|
||||
is_payload_fragmented = true;
|
||||
}
|
||||
const uint8_t ext_type = stream.read<uint8_t>();
|
||||
// every ext header is at least 8 bytes long
|
||||
// minus one, from the next_header field.
|
||||
@@ -98,24 +102,29 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz)
|
||||
stream.skip(payload_size);
|
||||
}
|
||||
else {
|
||||
inner_pdu(
|
||||
Internals::pdu_from_flag(
|
||||
static_cast<Constants::IP::e>(current_header),
|
||||
stream.pointer(),
|
||||
stream.size(),
|
||||
false
|
||||
)
|
||||
);
|
||||
if (!inner_pdu()) {
|
||||
if (is_payload_fragmented) {
|
||||
inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
|
||||
}
|
||||
else {
|
||||
inner_pdu(
|
||||
Internals::allocate<IPv6>(
|
||||
current_header,
|
||||
Internals::pdu_from_flag(
|
||||
static_cast<Constants::IP::e>(current_header),
|
||||
stream.pointer(),
|
||||
stream.size()
|
||||
stream.size(),
|
||||
false
|
||||
)
|
||||
);
|
||||
if (!inner_pdu()) {
|
||||
inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
|
||||
inner_pdu(
|
||||
Internals::allocate<IPv6>(
|
||||
current_header,
|
||||
stream.pointer(),
|
||||
stream.size()
|
||||
)
|
||||
);
|
||||
if (!inner_pdu()) {
|
||||
inner_pdu(new Tins::RawPDU(stream.pointer(), stream.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// We got to an actual PDU, we're done
|
||||
@@ -219,7 +228,9 @@ void IPv6::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* pa
|
||||
Internals::pdu_type_to_id<IPv6>(inner_pdu()->pdu_type())
|
||||
);
|
||||
}
|
||||
set_last_next_header(new_flag);
|
||||
if (new_flag != 0xff) {
|
||||
set_last_next_header(new_flag);
|
||||
}
|
||||
}
|
||||
payload_length(static_cast<uint16_t>(total_sz - sizeof(header_)));
|
||||
stream.write(header_);
|
||||
|
||||
@@ -24,7 +24,7 @@ using namespace Tins;
|
||||
class IPv6Test : public testing::Test {
|
||||
public:
|
||||
static const uint8_t expected_packet1[], expected_packet2[],
|
||||
hop_by_hop_options[];
|
||||
hop_by_hop_options[], broken1[];
|
||||
|
||||
void test_equals(IPv6& ip1, IPv6& ip2);
|
||||
};
|
||||
@@ -55,6 +55,12 @@ const uint8_t IPv6Test::hop_by_hop_options[] = {
|
||||
222, 173, 190, 239, 190, 173, 254, 237
|
||||
};
|
||||
|
||||
const uint8_t IPv6Test::broken1[] = {
|
||||
51, 51, 0, 0, 0, 251, 96, 3, 8, 165, 51, 186, 134, 221, 96, 14, 233, 9, 0, 11, 44, 255,
|
||||
254, 128, 0, 0, 0, 0, 0, 0, 98, 3, 8, 255, 254, 165, 51, 186, 255, 2, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 251, 17, 0, 11, 80, 53, 98, 2, 81, 72, 50, 10
|
||||
};
|
||||
|
||||
void IPv6Test::test_equals(IPv6& ip1, IPv6& ip2) {
|
||||
EXPECT_EQ(ip1.version(), ip2.version());
|
||||
EXPECT_EQ(ip1.traffic_class(), ip2.traffic_class());
|
||||
@@ -161,6 +167,14 @@ TEST_F(IPv6Test, Serialize) {
|
||||
test_equals(ip1, ip2);
|
||||
}
|
||||
|
||||
TEST_F(IPv6Test, Broken1) {
|
||||
EthernetII pkt(broken1, sizeof(broken1));
|
||||
EXPECT_EQ(
|
||||
PDU::serialization_type(broken1, broken1 + sizeof(broken1)),
|
||||
pkt.serialize()
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(IPv6Test, Version) {
|
||||
IPv6 ipv6;
|
||||
ipv6.version(3);
|
||||
|
||||
Reference in New Issue
Block a user