feature: packet IO support IP reassembly

This commit is contained in:
luwenpeng
2024-10-23 10:01:20 +08:00
parent a7b79a0e22
commit fd3cc20554
54 changed files with 3474 additions and 4271 deletions

View File

@@ -1,4 +1,59 @@
#include "gtest_utils.h"
#include <gtest/gtest.h>
#include "packet_parser.h"
#include "packet_helper.h"
#include "packet_internal.h"
#include "ip_reassembly.h"
static inline void packet_overwrite_v6_saddr(struct packet *pkt, struct in6_addr saddr)
{
const struct layer_private *ipv6_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV6);
EXPECT_TRUE(ipv6_layer);
struct ip6_hdr *hdr = (struct ip6_hdr *)ipv6_layer->hdr_ptr;
ip6_hdr_set_src_in6_addr(hdr, saddr);
}
static inline void packet_overwrite_v6_frag_offset(struct packet *pkt, uint16_t offset)
{
const struct layer_private *ipv6_layer = packet_get_innermost_layer(pkt, LAYER_PROTO_IPV6);
EXPECT_TRUE(ipv6_layer);
struct ip6_hdr *hdr = (struct ip6_hdr *)ipv6_layer->hdr_ptr;
struct ip6_frag *frag_hdr = ip6_hdr_get_frag_ext(hdr);
EXPECT_TRUE(frag_hdr);
ipv6_frag_set_offset(frag_hdr, offset);
}
static inline void stat_cmp(struct ip_reassembly_stat *curr, struct ip_reassembly_stat *expect)
{
EXPECT_TRUE(curr != NULL);
EXPECT_TRUE(expect != NULL);
EXPECT_TRUE(curr->ip4_defrags_expected == expect->ip4_defrags_expected);
EXPECT_TRUE(curr->ip4_defrags_succeed == expect->ip4_defrags_succeed);
EXPECT_TRUE(curr->ip4_defrags_failed == expect->ip4_defrags_failed);
EXPECT_TRUE(curr->ip4_frags == expect->ip4_frags);
EXPECT_TRUE(curr->ip4_frags_freed == expect->ip4_frags_freed);
EXPECT_TRUE(curr->ip4_frags_buffered == expect->ip4_frags_buffered);
EXPECT_TRUE(curr->ip4_frags_no_buffer == expect->ip4_frags_no_buffer);
EXPECT_TRUE(curr->ip4_frags_timeout == expect->ip4_frags_timeout);
EXPECT_TRUE(curr->ip4_frags_invalid_length == expect->ip4_frags_invalid_length);
EXPECT_TRUE(curr->ip4_frags_overlap == expect->ip4_frags_overlap);
EXPECT_TRUE(curr->ip4_frags_too_many == expect->ip4_frags_too_many);
EXPECT_TRUE(curr->ip6_defrags_expected == expect->ip6_defrags_expected);
EXPECT_TRUE(curr->ip6_defrags_succeed == expect->ip6_defrags_succeed);
EXPECT_TRUE(curr->ip6_defrags_failed == expect->ip6_defrags_failed);
EXPECT_TRUE(curr->ip6_frags == expect->ip6_frags);
EXPECT_TRUE(curr->ip6_frags_freed == expect->ip6_frags_freed);
EXPECT_TRUE(curr->ip6_frags_buffered == expect->ip6_frags_buffered);
EXPECT_TRUE(curr->ip6_frags_no_buffer == expect->ip6_frags_no_buffer);
EXPECT_TRUE(curr->ip6_frags_timeout == expect->ip6_frags_timeout);
EXPECT_TRUE(curr->ip6_frags_invalid_length == expect->ip6_frags_invalid_length);
EXPECT_TRUE(curr->ip6_frags_overlap == expect->ip6_frags_overlap);
EXPECT_TRUE(curr->ip6_frags_too_many == expect->ip6_frags_too_many);
}
/*
* Frame 3: 1510 bytes on wire (12080 bits), 1510 bytes captured (12080 bits)
@@ -605,84 +660,84 @@ unsigned char expect[] = {
#if 1
TEST(IPV6_REASSEMBLE, NORMAL)
{
struct packet pkt;
struct packet *new_pkt;
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet frag_pkt3 = {};
struct packet frag_pkt4 = {};
struct packet *frag_pkt = NULL;
struct packet *defrag_pkt = NULL;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 2, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
2, 0, 2, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag3
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 3, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt3, (const char *)frag3, sizeof(frag3));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt3, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
3, 0, 3, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag4
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 1, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
4, 4, 4, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt4, (const char *)frag4, sizeof(frag4));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt4, 1);
EXPECT_TRUE(defrag_pkt);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 1, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
4, 4, 4, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
EXPECT_TRUE(defrag_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
EXPECT_TRUE(defrag_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(defrag_pkt->data_ptr, expect, defrag_pkt->data_len) == 0);
// check IPv6
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV6);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_IPV6);
EXPECT_TRUE(layer);
struct ip6_hdr *hdr = (struct ip6_hdr *)layer->hdr_ptr;
EXPECT_TRUE(ip6_hdr_get_version(hdr) == 6);
@@ -702,7 +757,7 @@ TEST(IPV6_REASSEMBLE, NORMAL)
EXPECT_TRUE(ip6_hdr_get_frag_ext(hdr) == NULL);
// check UDP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_UDP);
layer = packet_get_innermost_layer(defrag_pkt, LAYER_PROTO_UDP);
EXPECT_TRUE(layer);
struct udphdr *udp_hdr = (struct udphdr *)layer->hdr_ptr;
EXPECT_TRUE(udp_hdr_get_src_port(udp_hdr) == 6363);
@@ -711,473 +766,309 @@ TEST(IPV6_REASSEMBLE, NORMAL)
EXPECT_TRUE(udp_hdr_get_checksum(udp_hdr) == 0x7916);
// free packet
packet_free(new_pkt);
EXPECT_TRUE(packet_is_defraged(defrag_pkt));
ip_reassembly_free(assy);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt);
packet_free(frag_pkt);
frag_pkt = packet_pop_frag(defrag_pkt);
EXPECT_TRUE(frag_pkt == NULL);
packet_free(defrag_pkt);
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
packet_free(pkt);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 1, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
4, 4, 4, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV6_REASSEMBLE, EXPIRE)
{
struct packet pkt;
struct packet *new_pkt;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 2);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
2, 0, 1, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 1, 2, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
}
#endif
#if 1
TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG)
{
struct packet pkt;
struct packet *new_pkt;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 2);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
2, 0, 2, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 1, 0, 1, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 2, 0, 1, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag3
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
4, 0, 3, 0, 1, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag4
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 1, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
5, 4, 4, 0, 1, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
// check IPv6
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV6);
EXPECT_TRUE(layer);
struct ip6_hdr *hdr = (struct ip6_hdr *)layer->hdr_ptr;
EXPECT_TRUE(ip6_hdr_get_version(hdr) == 6);
EXPECT_TRUE(ip6_hdr_get_traffic_class(hdr) == 0);
EXPECT_TRUE(ip6_hdr_get_flow_label(hdr) == 0x21289);
EXPECT_TRUE(ip6_hdr_get_payload_len(hdr) == 5387);
EXPECT_TRUE(ip6_hdr_get_next_header(hdr) == 17); // UDP
EXPECT_TRUE(ip6_hdr_get_hop_limit(hdr) == 64);
char src_str[INET6_ADDRSTRLEN];
char dst_str[INET6_ADDRSTRLEN];
struct in6_addr src_addr = ip6_hdr_get_src_in6_addr(hdr);
struct in6_addr dst_addr = ip6_hdr_get_dst_in6_addr(hdr);
inet_ntop(AF_INET6, &src_addr, src_str, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &dst_addr, dst_str, INET6_ADDRSTRLEN);
EXPECT_TRUE(strcmp(src_str, "2607:f010:3f9::1001") == 0);
EXPECT_TRUE(strcmp(dst_str, "2607:f010:3f9::11:0") == 0);
EXPECT_TRUE(ip6_hdr_get_frag_ext(hdr) == NULL);
// check UDP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_UDP);
EXPECT_TRUE(layer);
struct udphdr *udp_hdr = (struct udphdr *)layer->hdr_ptr;
EXPECT_TRUE(udp_hdr_get_src_port(udp_hdr) == 6363);
EXPECT_TRUE(udp_hdr_get_dst_port(udp_hdr) == 6363);
EXPECT_TRUE(udp_hdr_get_total_len(udp_hdr) == 5387);
EXPECT_TRUE(udp_hdr_get_checksum(udp_hdr) == 0x7916);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
}
#endif
#if 1
TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG)
{
struct packet pkt;
struct packet *new_pkt;
const struct layer_private *layer;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 1, // ip6: defrags_expected, defrags_succeed, defrags_failed
2, 2, 2, 0, 2, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag4
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag4
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 1, 0, 0, 1); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag3
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 2, 0, 0, 1); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
4, 0, 3, 0, 0, 1); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 1, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
5, 4, 4, 0, 0, 1); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
// check packet
packet_print(new_pkt);
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
// check IPv6
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_IPV6);
EXPECT_TRUE(layer);
struct ip6_hdr *hdr = (struct ip6_hdr *)layer->hdr_ptr;
EXPECT_TRUE(ip6_hdr_get_version(hdr) == 6);
EXPECT_TRUE(ip6_hdr_get_traffic_class(hdr) == 0);
EXPECT_TRUE(ip6_hdr_get_flow_label(hdr) == 0x21289);
EXPECT_TRUE(ip6_hdr_get_payload_len(hdr) == 5387);
EXPECT_TRUE(ip6_hdr_get_next_header(hdr) == 17); // UDP
EXPECT_TRUE(ip6_hdr_get_hop_limit(hdr) == 64);
char src_str[INET6_ADDRSTRLEN];
char dst_str[INET6_ADDRSTRLEN];
struct in6_addr src_addr = ip6_hdr_get_src_in6_addr(hdr);
struct in6_addr dst_addr = ip6_hdr_get_dst_in6_addr(hdr);
inet_ntop(AF_INET6, &src_addr, src_str, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &dst_addr, dst_str, INET6_ADDRSTRLEN);
EXPECT_TRUE(strcmp(src_str, "2607:f010:3f9::1001") == 0);
EXPECT_TRUE(strcmp(dst_str, "2607:f010:3f9::11:0") == 0);
EXPECT_TRUE(ip6_hdr_get_frag_ext(hdr) == NULL);
// check UDP
layer = packet_get_innermost_layer(new_pkt, LAYER_PROTO_UDP);
EXPECT_TRUE(layer);
struct udphdr *udp_hdr = (struct udphdr *)layer->hdr_ptr;
EXPECT_TRUE(udp_hdr_get_src_port(udp_hdr) == 6363);
EXPECT_TRUE(udp_hdr_get_dst_port(udp_hdr) == 6363);
EXPECT_TRUE(udp_hdr_get_total_len(udp_hdr) == 5387);
EXPECT_TRUE(udp_hdr_get_checksum(udp_hdr) == 0x7916);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV6_REASSEMBLE, FULL)
{
struct packet pkt;
struct packet *new_pkt;
struct in6_addr src_addr;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 1,
.bucket_num = 1,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct in6_addr addr;
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet frag_pkt3 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 2, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
char dup1[sizeof(frag1)] = {0};
char dup2[sizeof(frag1)] = {0};
char dup3[sizeof(frag1)] = {0};
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
char dup_frag[sizeof(frag1)] = {0};
memcpy(dup_frag, frag1, sizeof(frag1));
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
memcpy(dup1, frag1, sizeof(frag1));
memcpy(dup2, frag1, sizeof(frag1));
memcpy(dup3, frag1, sizeof(frag1));
// flow1
memset(&src_addr, 1, sizeof(src_addr));
packet_set_ipv6_src_addr(&pkt, src_addr);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)dup1, sizeof(dup1));
memset(&addr, 1, sizeof(addr));
packet_overwrite_v6_saddr(&frag_pkt1, addr);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// flow2
memset(&src_addr, 2, sizeof(src_addr));
packet_set_ipv6_src_addr(&pkt, src_addr);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
2, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 2, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)dup2, sizeof(dup2));
memset(&addr, 2, sizeof(addr));
packet_overwrite_v6_saddr(&frag_pkt2, addr);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
2, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
2, 0, 2, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// flow3
memset(&src_addr, 3, sizeof(src_addr));
packet_set_ipv6_src_addr(&pkt, src_addr);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt3, (const char *)dup3, sizeof(dup3));
memset(&addr, 3, sizeof(addr));
packet_overwrite_v6_saddr(&frag_pkt3, addr);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt3, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
2, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
3, 0, 2, 1, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
2, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 2, 1, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
2, 0, 2, // ip6: defrags_expected, defrags_succeed, defrags_failed
3, 2, 2, 1, 2, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif
#if 1
TEST(IPV6_REASSEMBLE, OVERLAP)
{
struct packet pkt;
struct packet *new_pkt;
struct ip_reassembly *assy;
struct ip_reassembly_config cfg = {
.enable = true,
.bucket_entries = 16,
.bucket_num = 8,
.ip_frag_timeout_ms = 1,
.ip_frag_expire_polling_interval_ms = 0,
.ip_frag_expire_polling_limit = 1024,
struct packet frag_pkt1 = {};
struct packet frag_pkt2 = {};
struct packet frag_pkt3 = {};
struct packet frag_pkt4 = {};
struct packet *defrag_pkt = NULL;
struct ip_reassembly *ip_reass;
struct ip_reassembly_stat *curr_stat;
struct ip_reassembly_stat expect_stat;
ip_reass = ip_reassembly_new(1, 1024, 64);
EXPECT_TRUE(ip_reass != NULL);
curr_stat = ip_reassembly_get_stat(ip_reass);
EXPECT_TRUE(curr_stat != NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
assy = ip_reassembly_new(&cfg, 0);
EXPECT_TRUE(assy != NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
0, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
stat_cmp(curr_stat, &expect_stat);
// frag1
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
1, 0, 1, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt1, (const char *)frag1, sizeof(frag1));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt1, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
1, 0, 1, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag2
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
2, 0, 2, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt2, (const char *)frag2, sizeof(frag2));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt2, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
2, 0, 2, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag3 -- overwrite frag offset
char dup_frag[sizeof(frag3)] = {0};
memcpy(dup_frag, frag3, sizeof(frag3));
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
packet_set_ipv6_frag_offset(&pkt, 2048);
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
3, 0, 3, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
packet_parse(&frag_pkt3, (const char *)dup_frag, sizeof(dup_frag));
packet_overwrite_v6_frag_offset(&frag_pkt3, 2048);
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt3, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed
3, 0, 3, 0, 0, 0, 0, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// frag4
memset(&pkt, 0, sizeof(pkt));
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
new_pkt = ip_reassembly_packet(assy, &pkt, 1);
EXPECT_TRUE(new_pkt == NULL);
packet_parse(&frag_pkt4, (const char *)frag4, sizeof(frag4));
defrag_pkt = ip_reassembly_defrag(ip_reass, &frag_pkt4, 1);
EXPECT_TRUE(defrag_pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 1, // ip6: defrags_expected, defrags_succeed, defrags_failed
4, 4, 4, 0, 0, 0, 1, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
check_stat(ip_reassembly_stat(assy),
0, 0, 0, 0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
1, 0, 0, 0, 1, 0, // ip6: defrags_expected, defrags_succeed, defrags_failed_timeout, defrags_failed_invalid_length, defrags_failed_overlap, defrags_failed_too_many_frag
4, 4, 4, 0, 0, 0); // ip6: frags, frags_freed, frags_buffered, frags_bypass_no_buffer, frags_bypass_dup_fist_frag, frags_bypass_dup_last_frag
struct packet *pkt = NULL;
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt);
packet_free(pkt);
pkt = ip_reassembly_clean(ip_reass, 2);
EXPECT_TRUE(pkt == NULL);
expect_stat = {
0, 0, 0, // ip4: defrags_expected, defrags_succeed, defrags_failed
0, 0, 0, 0, 0, 0, 0, 0, // ip4: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
1, 0, 1, // ip6: defrags_expected, defrags_succeed, defrags_failed
4, 4, 4, 0, 0, 0, 1, 0 // ip6: frags, frags_freed, frags_buffered, frags_no_buffer, timeout, invalid_length, overlap, too_many
};
stat_cmp(curr_stat, &expect_stat);
// free packet
packet_free(new_pkt);
ip_reassembly_free(assy);
ip_reassembly_free(ip_reass);
}
#endif