srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_ipv6.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_ipv6.cpp')
-rw-r--r--tests/test_ipv6.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/tests/test_ipv6.cpp b/tests/test_ipv6.cpp
index 1cce85b..2d75e9a 100644
--- a/tests/test_ipv6.cpp
+++ b/tests/test_ipv6.cpp
@@ -129,6 +129,43 @@ TEST_CASE("walk_ipv6_extension_headers walks the fixed-size Fragment header") {
CHECK(result.payload[0] == 0xCA);
}
+TEST_CASE("walk_ipv6_extension_headers reports the fragment id even for the first fragment") {
+ // Same shape as the test above (fragment offset 0 - the first
+ // fragment), but this time checking that the walk continues on to
+ // TCP *and* still surfaces the Identification field, which a
+ // caller needs to correlate this with the fragments that follow.
+ std::vector<unsigned char> payload = {static_cast<unsigned char>(kProtoTcp), 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, // id = 0x3039
+ 0xCA, 0xFE};
+ auto result = walk_ipv6_extension_headers(kNextHeaderFragment, payload);
+ CHECK_FALSE(result.is_non_first_fragment);
+ REQUIRE(result.fragment_id.has_value());
+ CHECK(*result.fragment_id == 0x3039);
+ CHECK(result.final_next_header == kProtoTcp);
+ REQUIRE(result.payload.size() == 2); // walk continued past the fragment header to real payload
+}
+
+TEST_CASE("walk_ipv6_extension_headers stops at a non-first fragment rather than walking into "
+ "continuation data") {
+ // Fragment offset field (13 bits, packed into the top of bytes[2:3])
+ // set to a nonzero value - 8 in units of 8 bytes, i.e. byte offset
+ // 64 into the original datagram. offset_res_m = 8 << 3 = 0x0040.
+ std::vector<unsigned char> payload = {
+ static_cast<unsigned char>(kProtoTcp), 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2A,
+ 0xDE, 0xAD, 0xBE, 0xEF, // pure continuation data - NOT a TCP header
+ };
+ auto result = walk_ipv6_extension_headers(kNextHeaderFragment, payload);
+ CHECK(result.is_non_first_fragment);
+ REQUIRE(result.fragment_id.has_value());
+ CHECK(*result.fragment_id == 0x2A);
+ // final_next_header still names TCP (that's what the reassembled
+ // datagram eventually is), but the payload past it is untouched
+ // continuation data - callers must not decode it as TCP.
+ CHECK(result.final_next_header == kProtoTcp);
+ REQUIRE(result.payload.size() == 4);
+ CHECK(result.payload[0] == 0xDE);
+}
+
TEST_CASE("walk_ipv6_extension_headers applies AH's 4-byte-unit length formula") {
// AH: next_header(1)=TCP, payload_len(1)=1 -> total len (1+2)*4=12 bytes.
std::vector<unsigned char> payload(12, 0);