add IPv4 & IPv6 frag reassemble test case
This commit is contained in:
@@ -1,32 +0,0 @@
|
|||||||
#include "ip_fragment.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the number of fragmented packets, stored in the pkts_out array
|
|
||||||
* Packets in the pkts_out array should be freed by calling the packet_free() function
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint16_t ipv4_fragment_packet(struct packet *pkt_in, struct packet **pkts_out, uint16_t n_pkts_out, uint16_t mtu_size)
|
|
||||||
{
|
|
||||||
if (pkt_in == NULL || pkts_out == NULL || n_pkts_out == 0)
|
|
||||||
{
|
|
||||||
IP_FRAGMENT_LOG_ERROR("invalid input parameters");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t ipv6_fragment_packet(struct packet *pkt_in, struct packet **pkts_out, uint16_t n_pkts_out, uint16_t mtu_size)
|
|
||||||
{
|
|
||||||
if (pkt_in == NULL || pkts_out == NULL || n_pkts_out == 0)
|
|
||||||
{
|
|
||||||
IP_FRAGMENT_LOG_ERROR("invalid input parameters");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef _IP_FRAGMENT_H
|
|
||||||
#define _IP_FRAGMENT_H
|
|
||||||
|
|
||||||
#ifdef __cpluscplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "packet.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#define IP_FRAGMENT_LOG_DEBUG(format, ...) LOG_DEBUG("ip_fragment", format, ##__VA_ARGS__)
|
|
||||||
#define IP_FRAGMENT_LOG_ERROR(format, ...) LOG_ERROR("ip_fragment", format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the number of fragmented packets, stored in the pkts_out array
|
|
||||||
* Packets in the pkts_out array should be freed by calling the packet_free() function
|
|
||||||
*/
|
|
||||||
uint16_t ipv4_fragment_packet(struct packet *pkt_in, struct packet **pkts_out, uint16_t n_pkts_out, uint16_t mtu_size);
|
|
||||||
uint16_t ipv6_fragment_packet(struct packet *pkt_in, struct packet **pkts_out, uint16_t n_pkts_out, uint16_t mtu_size);
|
|
||||||
|
|
||||||
#ifdef __cpluscplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -12,39 +12,45 @@
|
|||||||
#include "packet_helpers.h"
|
#include "packet_helpers.h"
|
||||||
#include "ip_reassemble.h"
|
#include "ip_reassemble.h"
|
||||||
|
|
||||||
#define IP_FRAG_HASH_FNUM 2
|
|
||||||
#define PRIME_VALUE 0xeaad8405
|
|
||||||
|
|
||||||
#define IP_FRAG_TBL_POS(mgr, sig) ((mgr)->table + ((sig) & (mgr)->entry_mask))
|
|
||||||
|
|
||||||
#define IPV4_KEYLEN 1
|
#define IPV4_KEYLEN 1
|
||||||
#define IPV6_KEYLEN 4
|
#define IPV6_KEYLEN 4
|
||||||
#define IPv6_KEY_BYTES(key) (key)[0], (key)[1], (key)[2], (key)[3]
|
#define PRIME_VALUE 0xeaad8405
|
||||||
|
#define IP_FRAG_HASH_FNUM 2
|
||||||
|
#define IP_FRAG_TBL_POS(mgr, sig) ((mgr)->table + ((sig) & (mgr)->entry_mask))
|
||||||
|
|
||||||
#define IP_REASSEMBLE_DEBUG_ARG1(desc, key, ...) \
|
#define KEY_TO_STR(key, str_str, dst_str) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if ((key)->src_dst_len == IPV4_KEYLEN) \
|
if ((key)->src_dst_len == IPV4_KEYLEN) \
|
||||||
{ \
|
{ \
|
||||||
IP_REASSEMBLE_DEBUG(desc, "key <%lu, %#x>", (key)->src_dst_addr[0], (key)->ip_id); \
|
uint32_t src_addr = (key)->src_dst_addr[0] >> 32; \
|
||||||
} \
|
uint32_t dst_addr = (key)->src_dst_addr[0] & 0xffffffff; \
|
||||||
else \
|
inet_ntop(AF_INET, &src_addr, src_str, INET6_ADDRSTRLEN); \
|
||||||
{ \
|
inet_ntop(AF_INET, &dst_addr, dst_str, INET6_ADDRSTRLEN); \
|
||||||
IP_REASSEMBLE_DEBUG(desc, "key <%08lu%08lu%08lu%08lu, %#x>", IPv6_KEY_BYTES((key)->src_dst_addr), (key)->ip_id); \
|
} \
|
||||||
} \
|
else \
|
||||||
|
{ \
|
||||||
|
inet_ntop(AF_INET6, &(key)->src_dst_addr[0], src_str, INET6_ADDRSTRLEN); \
|
||||||
|
inet_ntop(AF_INET6, &(key)->src_dst_addr[2], dst_str, INET6_ADDRSTRLEN); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define IP_REASSEMBLE_ERROR_ARG1(desc, key, ...) \
|
#define IP_REASSEMBLE_DEBUG1(desc, key, ...) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if ((key)->src_dst_len == IPV4_KEYLEN) \
|
char src_str[INET6_ADDRSTRLEN] = {0}; \
|
||||||
{ \
|
char dst_str[INET6_ADDRSTRLEN] = {0}; \
|
||||||
IP_REASSEMBLE_ERROR(desc, "key <%lu, %#x>", (key)->src_dst_addr[0], (key)->ip_id); \
|
KEY_TO_STR(key, src_str, dst_str); \
|
||||||
} \
|
IP_REASSEMBLE_DEBUG("%s (%s->%s 0x%0x)", desc, src_str, dst_str, (key)->ip_id); \
|
||||||
else \
|
} while (0)
|
||||||
{ \
|
|
||||||
IP_REASSEMBLE_ERROR(desc, "key <%08lu%08lu%08lu%08lu, %#x>", IPv6_KEY_BYTES((key)->src_dst_addr), (key)->ip_id); \
|
#define IP_REASSEMBLE_ERROR1(desc, key, ...) \
|
||||||
} \
|
do \
|
||||||
|
{ \
|
||||||
|
char src_str[INET6_ADDRSTRLEN] = {0}; \
|
||||||
|
char dst_str[INET6_ADDRSTRLEN] = {0}; \
|
||||||
|
KEY_TO_STR(key, src_str, dst_str); \
|
||||||
|
IP_REASSEMBLE_ERROR("%s (%s->%s 0x%0x)", desc, src_str, dst_str, (key)->ip_id); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -61,18 +67,21 @@ enum
|
|||||||
|
|
||||||
struct ip_frag_hdr
|
struct ip_frag_hdr
|
||||||
{
|
{
|
||||||
|
void *hdr_data; // need be freed
|
||||||
|
uint16_t hdr_len;
|
||||||
|
|
||||||
uint16_t l3_offset;
|
uint16_t l3_offset;
|
||||||
uint16_t l3_len;
|
uint16_t l3_len;
|
||||||
uint16_t hdr_len;
|
|
||||||
uint8_t next_proto;
|
uint8_t next_proto;
|
||||||
void *hdr_data; // need be freed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_frag_pkt
|
struct ip_frag_pkt
|
||||||
{
|
{
|
||||||
uint16_t offset;
|
|
||||||
uint16_t len;
|
|
||||||
void *data; // need be freed
|
void *data; // need be freed
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
|
uint16_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_flow_key
|
struct ip_flow_key
|
||||||
@@ -99,15 +108,6 @@ struct ip_flow
|
|||||||
struct ip_frag_pkt frags[IP_MAX_FRAG_NUM]; // first two entries in the frags[] array are for the last and first fragments.
|
struct ip_frag_pkt frags[IP_MAX_FRAG_NUM]; // first two entries in the frags[] array are for the last and first fragments.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_reassemble_stat
|
|
||||||
{
|
|
||||||
uint64_t find_num;
|
|
||||||
uint64_t add_num;
|
|
||||||
uint64_t del_num;
|
|
||||||
uint64_t fail_total;
|
|
||||||
uint64_t fail_nospace;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ip_reassemble_manager
|
struct ip_reassemble_manager
|
||||||
{
|
{
|
||||||
// config
|
// config
|
||||||
@@ -131,13 +131,40 @@ struct ip_reassemble_manager
|
|||||||
struct ip_flow **tqh_last;
|
struct ip_flow **tqh_last;
|
||||||
} lru;
|
} lru;
|
||||||
struct ip_flow *last;
|
struct ip_flow *last;
|
||||||
struct ip_flow *table; // array of ip_frag_pkt
|
struct ip_flow *table; // array of ip_flow
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Private API
|
* utils
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#define ip_reassemble_stat_inc(mgr, filed, key) \
|
||||||
|
{ \
|
||||||
|
if ((key)->src_dst_len == IPV4_KEYLEN) \
|
||||||
|
{ \
|
||||||
|
(mgr)->stat.ip4_flow_##filed++; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
(mgr)->stat.ip6_flow_##filed++; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *memdup(const void *src, size_t len)
|
||||||
|
{
|
||||||
|
if (src == NULL || len == 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dst = malloc(len);
|
||||||
|
if (dst == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return memcpy(dst, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t combine32ms1b(uint32_t x)
|
static inline uint32_t combine32ms1b(uint32_t x)
|
||||||
{
|
{
|
||||||
x |= x >> 1;
|
x |= x >> 1;
|
||||||
@@ -195,7 +222,7 @@ static inline int ip_reassemble_check_config(const struct ip_reassemble_config *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* struct ip_flow_key
|
* ip flow key
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static inline void ipv4_flow_key_hash(const struct ip_flow_key *key, uint32_t *value1, uint32_t *value2)
|
static inline void ipv4_flow_key_hash(const struct ip_flow_key *key, uint32_t *value1, uint32_t *value2)
|
||||||
@@ -267,27 +294,13 @@ static inline void ip_flow_key_zero(struct ip_flow_key *key)
|
|||||||
|
|
||||||
key->src_dst_len = 0;
|
key->src_dst_len = 0;
|
||||||
key->ip_id = 0;
|
key->ip_id = 0;
|
||||||
|
key->proto = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* struct ip_frag_hdr
|
* ip frag hdr
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static inline void *memdup(const void *src, size_t len)
|
|
||||||
{
|
|
||||||
if (src == NULL || len == 0)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *dst = malloc(len);
|
|
||||||
if (dst == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return memcpy(dst, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ip_frag_hdr_init(struct ip_frag_hdr *hdr, const struct packet *pkt)
|
static inline void ip_frag_hdr_init(struct ip_frag_hdr *hdr, const struct packet *pkt)
|
||||||
{
|
{
|
||||||
struct layer_record *layer = pkt->frag_layer;
|
struct layer_record *layer = pkt->frag_layer;
|
||||||
@@ -325,21 +338,47 @@ static inline void ip_frag_hdr_free(struct ip_frag_hdr *hdr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* struct ip_flow
|
* ip frag pkt
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
static inline void ip_frag_pkt_init(struct ip_frag_pkt *frag, void *data, uint16_t len, uint16_t offset)
|
||||||
|
{
|
||||||
|
frag->data = memdup(data, len);
|
||||||
|
frag->len = len;
|
||||||
|
frag->offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ip_frag_pkt_free(struct ip_frag_pkt *frag)
|
||||||
|
{
|
||||||
|
if (frag)
|
||||||
|
{
|
||||||
|
if (frag->data)
|
||||||
|
{
|
||||||
|
free(frag->data);
|
||||||
|
frag->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag->len = 0;
|
||||||
|
frag->offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* ip flow
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static inline void ip_flow_init(struct ip_flow *flow, const struct ip_flow_key *key)
|
static inline void ip_flow_init(struct ip_flow *flow, const struct ip_flow_key *key)
|
||||||
{
|
{
|
||||||
static const struct ip_frag_pkt zero_frag = {
|
static const struct ip_frag_pkt zero_frag = {
|
||||||
.offset = 0,
|
|
||||||
.len = 0,
|
|
||||||
.data = NULL,
|
.data = NULL,
|
||||||
|
.len = 0,
|
||||||
|
.offset = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
flow->lru.tqe_next = NULL;
|
flow->lru.tqe_next = NULL;
|
||||||
flow->lru.tqe_prev = NULL;
|
flow->lru.tqe_prev = NULL;
|
||||||
flow->key = *key;
|
flow->key = *key;
|
||||||
flow->create_time = timestamp_get_msec();
|
flow->create_time = timestamp_get_sec();
|
||||||
flow->expected_total_size = UINT32_MAX;
|
flow->expected_total_size = UINT32_MAX;
|
||||||
flow->received_frag_size = 0;
|
flow->received_frag_size = 0;
|
||||||
flow->next_fill_idx = IP_MIN_FRAG_NUM;
|
flow->next_fill_idx = IP_MIN_FRAG_NUM;
|
||||||
@@ -352,13 +391,7 @@ static inline void ip_flow_free(struct ip_flow *flow)
|
|||||||
for (uint32_t i = 0; i < IP_MAX_FRAG_NUM; i++)
|
for (uint32_t i = 0; i < IP_MAX_FRAG_NUM; i++)
|
||||||
{
|
{
|
||||||
struct ip_frag_pkt *frag = &flow->frags[i];
|
struct ip_frag_pkt *frag = &flow->frags[i];
|
||||||
frag->offset = 0;
|
ip_frag_pkt_free(frag);
|
||||||
frag->len = 0;
|
|
||||||
if (frag->data != NULL)
|
|
||||||
{
|
|
||||||
free(frag->data);
|
|
||||||
frag->data = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ip_flow_key_zero(&flow->key);
|
ip_flow_key_zero(&flow->key);
|
||||||
ip_frag_hdr_free(&flow->hdr);
|
ip_frag_hdr_free(&flow->hdr);
|
||||||
@@ -371,17 +404,30 @@ static inline int ip_flow_is_ready(struct ip_flow *flow)
|
|||||||
|
|
||||||
// return 0 : success
|
// return 0 : success
|
||||||
// return -1 : failed
|
// return -1 : failed
|
||||||
static inline int ip_flow_update(struct ip_flow *flow, const struct packet *pkt,
|
static inline int ip_flow_update(struct ip_reassemble_manager *mgr,
|
||||||
char *data, uint16_t len, uint16_t offset, bool more_frags)
|
struct ip_flow *flow, const struct packet *pkt,
|
||||||
|
char *frag_data, uint16_t frag_len, uint16_t frag_offset, bool more_frags)
|
||||||
{
|
{
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
struct ip_frag_pkt *frag_pkt;
|
||||||
if (offset == 0)
|
/*
|
||||||
|
* Internet Protocol, Version 6 (IPv6) Specification
|
||||||
|
*
|
||||||
|
* https://datatracker.ietf.org/doc/html/rfc8200#section-4.5
|
||||||
|
*
|
||||||
|
* It should be noted that fragments may be duplicated in the
|
||||||
|
* network. Instead of treating these exact duplicate fragments
|
||||||
|
* as overlapping fragments, an implementation may choose to
|
||||||
|
* detect this case and drop exact duplicate fragments while
|
||||||
|
* keeping the other fragments belonging to the same packet.
|
||||||
|
*/
|
||||||
|
if (frag_offset == 0)
|
||||||
{
|
{
|
||||||
if (flow->frags[IP_FIRST_FRAG_IDX].data != NULL)
|
if (flow->frags[IP_FIRST_FRAG_IDX].data != NULL)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("duplicate first fragment encountered: ", &flow->key);
|
IP_REASSEMBLE_DEBUG1("duplicate first fragment bypass", &flow->key);
|
||||||
return -1;
|
ip_reassemble_stat_inc(mgr, bypass_dup_fist_frag, &flow->key);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
idx = IP_FIRST_FRAG_IDX;
|
idx = IP_FIRST_FRAG_IDX;
|
||||||
ip_frag_hdr_init(&flow->hdr, pkt);
|
ip_frag_hdr_init(&flow->hdr, pkt);
|
||||||
@@ -390,53 +436,56 @@ static inline int ip_flow_update(struct ip_flow *flow, const struct packet *pkt,
|
|||||||
{
|
{
|
||||||
if (flow->frags[IP_LAST_FRAG_IDX].data != NULL)
|
if (flow->frags[IP_LAST_FRAG_IDX].data != NULL)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("duplicate last fragment encountered: ", &flow->key);
|
IP_REASSEMBLE_DEBUG1("duplicate last fragment bypass", &flow->key);
|
||||||
return -1;
|
ip_reassemble_stat_inc(mgr, bypass_dup_last_frag, &flow->key);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
idx = IP_LAST_FRAG_IDX;
|
idx = IP_LAST_FRAG_IDX;
|
||||||
flow->expected_total_size = offset + len;
|
flow->expected_total_size = frag_offset + frag_len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (flow->next_fill_idx >= IP_MAX_FRAG_NUM)
|
if (flow->next_fill_idx >= IP_MAX_FRAG_NUM)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("max number of fragment exceeded: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("max number of fragment exceeded", &flow->key);
|
||||||
|
ip_reassemble_stat_inc(mgr, fail_many_frag, &flow->key);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
idx = flow->next_fill_idx;
|
idx = flow->next_fill_idx;
|
||||||
flow->next_fill_idx++;
|
flow->next_fill_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
flow->received_frag_size += len;
|
flow->received_frag_size += frag_len;
|
||||||
flow->frags[idx].data = memdup(data, len);
|
frag_pkt = &flow->frags[idx];
|
||||||
flow->frags[idx].offset = offset;
|
ip_frag_pkt_init(frag_pkt, frag_data, frag_len, frag_offset);
|
||||||
flow->frags[idx].len = len;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* ip flow table
|
* ip reassemble manager add/del/reuse/find/update flow
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static inline void ip_flow_table_add(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
static inline void ip_reassemble_manager_add_flow(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
||||||
{
|
{
|
||||||
|
ip_reassemble_stat_inc(mgr, add, &flow->key);
|
||||||
TAILQ_INSERT_TAIL(&mgr->lru, flow, lru);
|
TAILQ_INSERT_TAIL(&mgr->lru, flow, lru);
|
||||||
mgr->entry_used++;
|
mgr->entry_used++;
|
||||||
mgr->stat.add_num++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ip_flow_table_del(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
static inline void ip_reassemble_manager_del_flow(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
||||||
{
|
{
|
||||||
|
ip_reassemble_stat_inc(mgr, del, &flow->key);
|
||||||
TAILQ_REMOVE(&mgr->lru, flow, lru);
|
TAILQ_REMOVE(&mgr->lru, flow, lru);
|
||||||
mgr->entry_used--;
|
mgr->entry_used--;
|
||||||
mgr->stat.del_num++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ip_flow_table_reuse(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
static inline void ip_reassemble_manager_reuse_flow(struct ip_reassemble_manager *mgr, struct ip_flow *flow, const struct ip_flow_key *key)
|
||||||
{
|
{
|
||||||
ip_flow_table_del(mgr, flow);
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
ip_flow_table_add(mgr, flow);
|
ip_flow_free(flow);
|
||||||
|
ip_flow_init(flow, key);
|
||||||
|
ip_reassemble_manager_add_flow(mgr, flow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -444,9 +493,9 @@ static inline void ip_flow_table_reuse(struct ip_reassemble_manager *mgr, struct
|
|||||||
* free : the first empty entry in the bucket
|
* free : the first empty entry in the bucket
|
||||||
* expired: the first timed-out entry in the bucket
|
* expired: the first timed-out entry in the bucket
|
||||||
*/
|
*/
|
||||||
static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, const struct ip_flow_key *key, struct ip_flow **free, struct ip_flow **expired)
|
static struct ip_flow *ip_reassemble_manager_find_flow(struct ip_reassemble_manager *mgr, const struct ip_flow_key *key, struct ip_flow **free, struct ip_flow **expired)
|
||||||
{
|
{
|
||||||
mgr->stat.find_num++;
|
ip_reassemble_stat_inc(mgr, find, key);
|
||||||
|
|
||||||
if (mgr->last != NULL && ip_flow_key_cmp(key, &mgr->last->key) == 0)
|
if (mgr->last != NULL && ip_flow_key_cmp(key, &mgr->last->key) == 0)
|
||||||
{
|
{
|
||||||
@@ -455,10 +504,6 @@ static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, con
|
|||||||
|
|
||||||
uint32_t sig1 = 0;
|
uint32_t sig1 = 0;
|
||||||
uint32_t sig2 = 0;
|
uint32_t sig2 = 0;
|
||||||
uint64_t timeout = mgr->timeout;
|
|
||||||
uint32_t assoc = mgr->bucket_entries;
|
|
||||||
uint64_t tms = timestamp_get_msec();
|
|
||||||
|
|
||||||
if (key->src_dst_len == IPV4_KEYLEN)
|
if (key->src_dst_len == IPV4_KEYLEN)
|
||||||
{
|
{
|
||||||
ipv4_flow_key_hash(key, &sig1, &sig2);
|
ipv4_flow_key_hash(key, &sig1, &sig2);
|
||||||
@@ -475,6 +520,9 @@ static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, con
|
|||||||
// search in the bucket
|
// search in the bucket
|
||||||
struct ip_flow *old = NULL;
|
struct ip_flow *old = NULL;
|
||||||
struct ip_flow *empty = NULL;
|
struct ip_flow *empty = NULL;
|
||||||
|
uint64_t timeout = mgr->timeout;
|
||||||
|
uint32_t assoc = mgr->bucket_entries;
|
||||||
|
uint64_t tms = timestamp_get_sec();
|
||||||
for (uint32_t i = 0; i != assoc; i++)
|
for (uint32_t i = 0; i != assoc; i++)
|
||||||
{
|
{
|
||||||
if (ip_flow_key_cmp(key, &p1[i].key) == 0)
|
if (ip_flow_key_cmp(key, &p1[i].key) == 0)
|
||||||
@@ -487,7 +535,7 @@ static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, con
|
|||||||
{
|
{
|
||||||
empty = (empty == NULL) ? (p1 + i) : empty;
|
empty = (empty == NULL) ? (p1 + i) : empty;
|
||||||
}
|
}
|
||||||
else if (timeout + p1[i].create_time < tms)
|
else if (timeout + p1[i].create_time <= tms)
|
||||||
{
|
{
|
||||||
old = (old == NULL) ? (p1 + i) : old;
|
old = (old == NULL) ? (p1 + i) : old;
|
||||||
}
|
}
|
||||||
@@ -502,7 +550,7 @@ static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, con
|
|||||||
{
|
{
|
||||||
empty = (empty == NULL) ? (p2 + i) : empty;
|
empty = (empty == NULL) ? (p2 + i) : empty;
|
||||||
}
|
}
|
||||||
else if (timeout + p2[i].create_time < tms)
|
else if (timeout + p2[i].create_time <= tms)
|
||||||
{
|
{
|
||||||
old = (old == NULL) ? (p2 + i) : old;
|
old = (old == NULL) ? (p2 + i) : old;
|
||||||
}
|
}
|
||||||
@@ -513,22 +561,20 @@ static struct ip_flow *ip_flow_table_find(struct ip_reassemble_manager *mgr, con
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ip_flow *ip_flow_table_update(struct ip_reassemble_manager *mgr, const struct ip_flow_key *key)
|
static struct ip_flow *ip_reassemble_manager_update_flow(struct ip_reassemble_manager *mgr, const struct ip_flow_key *key)
|
||||||
{
|
{
|
||||||
|
struct ip_flow *flow = NULL;
|
||||||
struct ip_flow *free = NULL;
|
struct ip_flow *free = NULL;
|
||||||
struct ip_flow *expired = NULL;
|
struct ip_flow *expired = NULL;
|
||||||
struct ip_flow *flow = NULL;
|
|
||||||
uint64_t tms = timestamp_get_msec();
|
|
||||||
|
|
||||||
flow = ip_flow_table_find(mgr, key, &free, &expired);
|
flow = ip_reassemble_manager_find_flow(mgr, key, &free, &expired);
|
||||||
if (flow == NULL)
|
if (flow == NULL)
|
||||||
{
|
{
|
||||||
if (expired)
|
if (expired)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("ip flow new (use expired iterm): ", key);
|
IP_REASSEMBLE_DEBUG1("add ip flow success: reuse expired entry", key);
|
||||||
ip_flow_free(expired);
|
ip_reassemble_manager_reuse_flow(mgr, expired, key);
|
||||||
ip_flow_init(expired, key);
|
ip_reassemble_stat_inc(mgr, timeout, key);
|
||||||
ip_flow_table_reuse(mgr, expired);
|
|
||||||
|
|
||||||
mgr->last = expired;
|
mgr->last = expired;
|
||||||
return expired;
|
return expired;
|
||||||
@@ -536,28 +582,27 @@ static struct ip_flow *ip_flow_table_update(struct ip_reassemble_manager *mgr, c
|
|||||||
|
|
||||||
if (free)
|
if (free)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("ip flow new (use free iterm): ", key);
|
IP_REASSEMBLE_DEBUG1("add ip flow success: use free entry", key);
|
||||||
ip_flow_init(free, key);
|
ip_flow_init(free, key);
|
||||||
ip_flow_table_add(mgr, free);
|
ip_reassemble_manager_add_flow(mgr, free);
|
||||||
|
|
||||||
mgr->last = free;
|
mgr->last = free;
|
||||||
return free;
|
return free;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no space
|
// no space
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("bucket full discarding new fragmented packets: ", key);
|
IP_REASSEMBLE_ERROR1("add ip flow failed: bucket full", key);
|
||||||
mgr->stat.fail_nospace++;
|
ip_reassemble_stat_inc(mgr, fail_no_space, key);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// expired
|
// expired
|
||||||
if (mgr->timeout + flow->create_time < tms)
|
if (mgr->timeout + flow->create_time <= timestamp_get_sec())
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("ip flow find, but expired: ", key);
|
IP_REASSEMBLE_DEBUG1("add ip flow success: reuse expired entry", key);
|
||||||
ip_flow_free(flow);
|
ip_reassemble_manager_reuse_flow(mgr, flow, key);
|
||||||
ip_flow_init(flow, key);
|
ip_reassemble_stat_inc(mgr, timeout, key);
|
||||||
ip_flow_table_reuse(mgr, flow);
|
|
||||||
|
|
||||||
mgr->last = flow;
|
mgr->last = flow;
|
||||||
return flow;
|
return flow;
|
||||||
@@ -565,41 +610,33 @@ static struct ip_flow *ip_flow_table_update(struct ip_reassemble_manager *mgr, c
|
|||||||
// not expired
|
// not expired
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("ip flow find, not expired: ", key);
|
IP_REASSEMBLE_DEBUG1("find ip flow success: not expire", key);
|
||||||
|
|
||||||
mgr->last = flow;
|
mgr->last = flow;
|
||||||
return flow;
|
return flow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ip_flow_table_expire(struct ip_reassemble_manager *mgr)
|
|
||||||
{
|
|
||||||
struct ip_flow *flow = NULL;
|
|
||||||
uint64_t curr_ts = timestamp_get_msec();
|
|
||||||
uint64_t timeout = mgr->timeout;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(flow, &mgr->lru, lru)
|
|
||||||
if (timeout + flow->create_time < curr_ts)
|
|
||||||
{
|
|
||||||
IP_REASSEMBLE_DEBUG_ARG1("time expires discarding old fragmented packets: ", &flow->key);
|
|
||||||
ip_flow_free(flow);
|
|
||||||
ip_flow_table_del(mgr, flow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* frag reassemble
|
* frag reassemble
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
static struct packet *ip_frag_reassemble(struct ip_reassemble_manager *mgr, struct ip_flow *flow)
|
||||||
{
|
{
|
||||||
struct ip_frag_pkt *first = &flow->frags[IP_FIRST_FRAG_IDX];
|
struct ip_frag_pkt *first = &flow->frags[IP_FIRST_FRAG_IDX];
|
||||||
struct ip_frag_pkt *last = &flow->frags[IP_LAST_FRAG_IDX];
|
struct ip_frag_pkt *last = &flow->frags[IP_LAST_FRAG_IDX];
|
||||||
struct ip_frag_pkt *temp = NULL;
|
struct ip_frag_pkt *temp = NULL;
|
||||||
|
|
||||||
|
uint32_t loop = 0;
|
||||||
|
uint16_t last_offset = last->offset;
|
||||||
|
|
||||||
|
struct ip *ip4_hdr = NULL;
|
||||||
|
struct ip6_hdr *ip6_hdr = NULL;
|
||||||
|
|
||||||
// calculate the length of the reassembled packet
|
// calculate the length of the reassembled packet
|
||||||
uint32_t buff_len = flow->expected_total_size + flow->hdr.hdr_len;
|
uint32_t packet_len = flow->expected_total_size + flow->hdr.hdr_len;
|
||||||
char *buff = (char *)calloc(1, buff_len + sizeof(struct packet));
|
char *buff = (char *)calloc(1, packet_len + sizeof(struct packet));
|
||||||
if (buff == NULL)
|
if (buff == NULL)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR("unable to allocate memory");
|
IP_REASSEMBLE_ERROR("unable to allocate memory");
|
||||||
@@ -607,20 +644,17 @@ static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *ptr = buff + sizeof(struct packet);
|
char *ptr = buff + sizeof(struct packet);
|
||||||
char *end = ptr + buff_len;
|
char *end = ptr + packet_len;
|
||||||
|
|
||||||
// copy last frag
|
// copy last frag
|
||||||
if (last->len > end - ptr)
|
if (last->len > end - ptr)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("last packet length is greater than the expected reassembled length: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("last frag length not match expected reassembled length", &flow->key);
|
||||||
free(buff);
|
goto error_out_invalid_length;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
end -= last->len;
|
end -= last->len;
|
||||||
memcpy(end, last->data, last->len);
|
memcpy(end, last->data, last->len);
|
||||||
|
|
||||||
uint32_t loop = 0;
|
|
||||||
uint16_t last_offset = last->offset;
|
|
||||||
while (first->len != last_offset)
|
while (first->len != last_offset)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -631,22 +665,15 @@ static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
|||||||
* will use the more recently arrived copy in the data buffer and
|
* will use the more recently arrived copy in the data buffer and
|
||||||
* datagram delivered.
|
* datagram delivered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (uint32_t i = flow->next_fill_idx - 1; i >= IP_MIN_FRAG_NUM; i--)
|
for (uint32_t i = flow->next_fill_idx - 1; i >= IP_MIN_FRAG_NUM; i--)
|
||||||
{
|
{
|
||||||
if (i == IP_FIRST_FRAG_IDX || i == IP_LAST_FRAG_IDX)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = &flow->frags[i];
|
temp = &flow->frags[i];
|
||||||
if (temp->offset + temp->len == last_offset)
|
if (temp->offset + temp->len == last_offset)
|
||||||
{
|
{
|
||||||
if (temp->len > end - ptr)
|
if (temp->len > end - ptr)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("middle fragment packet length doesn't match last fragment packet offset: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("middle frag length not match expected reassembled length", &flow->key);
|
||||||
free(buff);
|
goto error_out_invalid_length;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end -= temp->len;
|
end -= temp->len;
|
||||||
@@ -656,11 +683,10 @@ static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loop > flow->next_fill_idx)
|
if (loop > flow->next_fill_idx - IP_MIN_FRAG_NUM)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("holes appear during frag reassemble: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("overlap appear during frag reassemble", &flow->key);
|
||||||
free(buff);
|
goto error_out_overlap;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loop++;
|
loop++;
|
||||||
@@ -669,9 +695,8 @@ static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
|||||||
// copy fist fragment data
|
// copy fist fragment data
|
||||||
if (first->len > end - ptr)
|
if (first->len > end - ptr)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("last packet length is greater than the expected reassembled length: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("first frag length not match expected reassembled length", &flow->key);
|
||||||
free(buff);
|
goto error_out_invalid_length;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
end -= first->len;
|
end -= first->len;
|
||||||
memcpy(end, first->data, first->len);
|
memcpy(end, first->data, first->len);
|
||||||
@@ -679,37 +704,46 @@ static struct packet *ip_frag_reassemble(struct ip_flow *flow)
|
|||||||
// copy frag hdr
|
// copy frag hdr
|
||||||
if (flow->hdr.hdr_len > end - ptr)
|
if (flow->hdr.hdr_len > end - ptr)
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR_ARG1("hdr length is greater than the expected reassembled length: ", &flow->key);
|
IP_REASSEMBLE_ERROR1("packet header length not match expected reassembled length", &flow->key);
|
||||||
free(buff);
|
goto error_out_invalid_length;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
end -= flow->hdr.hdr_len;
|
end -= flow->hdr.hdr_len;
|
||||||
memcpy(end, flow->hdr.hdr_data, flow->hdr.hdr_len);
|
memcpy(end, flow->hdr.hdr_data, flow->hdr.hdr_len);
|
||||||
|
|
||||||
|
// assert
|
||||||
assert(ptr == end);
|
assert(ptr == end);
|
||||||
|
|
||||||
if (flow->key.src_dst_len == IPV4_KEYLEN)
|
if (flow->key.src_dst_len == IPV4_KEYLEN)
|
||||||
{
|
{
|
||||||
// update ip total length & ip checksum
|
// update ip total length & ip checksum
|
||||||
struct ip *hdr = (struct ip *)(ptr + flow->hdr.l3_offset);
|
ip4_hdr = (struct ip *)(ptr + flow->hdr.l3_offset);
|
||||||
ipv4_hdr_set_total_len(hdr, buff_len - flow->hdr.l3_offset); // update total length
|
ipv4_hdr_set_total_len(ip4_hdr, packet_len - flow->hdr.l3_offset); // update total length
|
||||||
ipv4_hdr_set_mf_flag(hdr, false); // update more fragment flag
|
ipv4_hdr_set_mf_flag(ip4_hdr, false); // update more fragment flag
|
||||||
ipv4_hdr_set_frag_offset(hdr, 0); // update fragment offset
|
ipv4_hdr_set_frag_offset(ip4_hdr, 0); // update fragment offset
|
||||||
hdr->ip_sum = 0; // update checksum
|
ip4_hdr->ip_sum = 0; // update checksum
|
||||||
hdr->ip_sum = checksum((char *)hdr, flow->hdr.l3_len);
|
ip4_hdr->ip_sum = checksum((char *)ip4_hdr, flow->hdr.l3_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// update ipv6 payload length & next header
|
// update ipv6 payload length & next header
|
||||||
struct ip6_hdr *hdr = (struct ip6_hdr *)(ptr + flow->hdr.l3_offset);
|
ip6_hdr = (struct ip6_hdr *)(ptr + flow->hdr.l3_offset);
|
||||||
ipv6_hdr_set_payload_len(hdr, flow->expected_total_size); // update payload length
|
ipv6_hdr_set_payload_len(ip6_hdr, flow->expected_total_size); // update payload length
|
||||||
ipv6_hdr_set_next_header(hdr, flow->hdr.next_proto); // update next header
|
ipv6_hdr_set_next_header(ip6_hdr, flow->hdr.next_proto); // update next header
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new packet
|
// create a new packet
|
||||||
struct packet *new_pkt = (struct packet *)buff;
|
packet_parse((struct packet *)buff, buff + sizeof(struct packet), packet_len);
|
||||||
packet_parse(new_pkt, buff + sizeof(struct packet), buff_len);
|
return (struct packet *)buff;
|
||||||
|
|
||||||
return new_pkt;
|
error_out_invalid_length:
|
||||||
|
ip_reassemble_stat_inc(mgr, fail_invalid_length, &flow->key);
|
||||||
|
free(buff);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
error_out_overlap:
|
||||||
|
ip_reassemble_stat_inc(mgr, fail_overlap, &flow->key);
|
||||||
|
free(buff);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -781,9 +815,60 @@ void ip_reassemble_manager_destory(struct ip_reassemble_manager *mgr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ip_reassemble_manager_stat(struct ip_reassemble_manager *mgr)
|
void ip_reassemble_manager_expire(struct ip_reassemble_manager *mgr)
|
||||||
{
|
{
|
||||||
// TODO
|
struct ip_flow *flow = NULL;
|
||||||
|
uint64_t curr_ts = timestamp_get_sec();
|
||||||
|
uint64_t timeout = mgr->timeout;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(flow, &mgr->lru, lru)
|
||||||
|
if (timeout + flow->create_time <= curr_ts)
|
||||||
|
{
|
||||||
|
IP_REASSEMBLE_DEBUG1("expire ip flow: discarding old fragmented packets", &flow->key);
|
||||||
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
|
ip_reassemble_stat_inc(mgr, timeout, &flow->key);
|
||||||
|
ip_flow_free(flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_reassemble_manager_print_stat(struct ip_reassemble_manager *mgr)
|
||||||
|
{
|
||||||
|
if (mgr)
|
||||||
|
{
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_find : %lu", mgr->stat.ip4_flow_find);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_add : %lu", mgr->stat.ip4_flow_add);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_del : %lu", mgr->stat.ip4_flow_del);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_timeout : %lu", mgr->stat.ip4_flow_timeout);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_fail_no_space : %lu", mgr->stat.ip4_flow_fail_no_space);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_fail_overlap : %lu", mgr->stat.ip4_flow_fail_overlap);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_fail_many_frag : %lu", mgr->stat.ip4_flow_fail_many_frag);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_fail_invalid_length : %lu", mgr->stat.ip4_flow_fail_invalid_length);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_bypass_dup_fist_frag : %lu", mgr->stat.ip4_flow_bypass_dup_fist_frag);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip4_flow_bypass_dup_last_frag : %lu", mgr->stat.ip4_flow_bypass_dup_last_frag);
|
||||||
|
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_find : %lu", mgr->stat.ip6_flow_find);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_add : %lu", mgr->stat.ip6_flow_add);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_del : %lu", mgr->stat.ip6_flow_del);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_timeout : %lu", mgr->stat.ip6_flow_timeout);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_fail_no_space : %lu", mgr->stat.ip6_flow_fail_no_space);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_fail_overlap : %lu", mgr->stat.ip6_flow_fail_overlap);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_fail_many_frag : %lu", mgr->stat.ip6_flow_fail_many_frag);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_fail_invalid_length : %lu", mgr->stat.ip6_flow_fail_invalid_length);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_bypass_dup_fist_frag : %lu", mgr->stat.ip6_flow_bypass_dup_fist_frag);
|
||||||
|
IP_REASSEMBLE_DEBUG("ip6_flow_bypass_dup_last_frag : %lu", mgr->stat.ip6_flow_bypass_dup_last_frag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ip_reassemble_stat *ip_reassemble_manager_get_stat(struct ip_reassemble_manager *mgr)
|
||||||
|
{
|
||||||
|
if (mgr)
|
||||||
|
{
|
||||||
|
return &(mgr->stat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -812,7 +897,7 @@ struct packet *ip_reassemble_packet(struct ip_reassemble_manager *mgr, const str
|
|||||||
pkt1 = ipv4_reassemble_packet(mgr, pkt);
|
pkt1 = ipv4_reassemble_packet(mgr, pkt);
|
||||||
if (pkt1 && pkt1->frag_layer)
|
if (pkt1 && pkt1->frag_layer)
|
||||||
{
|
{
|
||||||
pkt2 = ip_reassemble_packet(mgr, pkt);
|
pkt2 = ip_reassemble_packet(mgr, pkt1);
|
||||||
packet_free(pkt1);
|
packet_free(pkt1);
|
||||||
return pkt2;
|
return pkt2;
|
||||||
}
|
}
|
||||||
@@ -824,7 +909,7 @@ struct packet *ip_reassemble_packet(struct ip_reassemble_manager *mgr, const str
|
|||||||
pkt1 = ipv6_reassemble_packet(mgr, pkt);
|
pkt1 = ipv6_reassemble_packet(mgr, pkt);
|
||||||
if (pkt1 && pkt1->frag_layer)
|
if (pkt1 && pkt1->frag_layer)
|
||||||
{
|
{
|
||||||
pkt2 = ip_reassemble_packet(mgr, pkt);
|
pkt2 = ip_reassemble_packet(mgr, pkt1);
|
||||||
packet_free(pkt1);
|
packet_free(pkt1);
|
||||||
return pkt2;
|
return pkt2;
|
||||||
}
|
}
|
||||||
@@ -839,13 +924,12 @@ struct packet *ip_reassemble_packet(struct ip_reassemble_manager *mgr, const str
|
|||||||
|
|
||||||
struct packet *ipv4_reassemble_packet(struct ip_reassemble_manager *mgr, const struct packet *pkt)
|
struct packet *ipv4_reassemble_packet(struct ip_reassemble_manager *mgr, const struct packet *pkt)
|
||||||
{
|
{
|
||||||
struct layer_record *layer = pkt->frag_layer;
|
const struct layer_record *layer = pkt->frag_layer;
|
||||||
struct ip *hdr = (struct ip *)layer->hdr_ptr;
|
const struct ip *hdr = (const struct ip *)layer->hdr_ptr;
|
||||||
char *data = (char *)layer->pld_ptr;
|
uint16_t frag_len = ipv4_hdr_get_total_len(hdr) - ipv4_hdr_get_hdr_len(hdr);
|
||||||
uint16_t len = ipv4_hdr_get_total_len(hdr) - ipv4_hdr_get_hdr_len(hdr);
|
if (frag_len > layer->pld_len)
|
||||||
if (len > layer->pld_len)
|
|
||||||
{
|
{
|
||||||
IP_REASSEMBLE_ERROR("unexpected header length on fragmented packet, ip_id: %lu", ipv4_hdr_get_ipid(hdr));
|
IP_REASSEMBLE_ERROR("unexpected header length, ip id: %lu", ipv4_hdr_get_ipid(hdr));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -856,18 +940,20 @@ struct packet *ipv4_reassemble_packet(struct ip_reassemble_manager *mgr, const s
|
|||||||
key.src_dst_len = IPV4_KEYLEN;
|
key.src_dst_len = IPV4_KEYLEN;
|
||||||
key.ip_id = ipv4_hdr_get_ipid(hdr);
|
key.ip_id = ipv4_hdr_get_ipid(hdr);
|
||||||
key.proto = ipv4_hdr_get_proto(hdr);
|
key.proto = ipv4_hdr_get_proto(hdr);
|
||||||
struct ip_flow *flow = ip_flow_table_update(mgr, &key);
|
|
||||||
|
struct ip_flow *flow = ip_reassemble_manager_update_flow(mgr, &key);
|
||||||
if (flow == NULL)
|
if (flow == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *frag_data = (char *)layer->pld_ptr;
|
||||||
bool more_frags = ipv4_hdr_get_mf_flag(hdr);
|
bool more_frags = ipv4_hdr_get_mf_flag(hdr);
|
||||||
uint16_t offset = ipv4_hdr_get_frag_offset(hdr);
|
uint16_t frag_offset = ipv4_hdr_get_frag_offset(hdr);
|
||||||
if (ip_flow_update(flow, pkt, data, len, offset, more_frags) != 0)
|
if (ip_flow_update(mgr, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0)
|
||||||
{
|
{
|
||||||
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
ip_flow_free(flow);
|
ip_flow_free(flow);
|
||||||
ip_flow_table_del(mgr, flow);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,9 +962,9 @@ struct packet *ipv4_reassemble_packet(struct ip_reassemble_manager *mgr, const s
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct packet *new_pkt = ip_frag_reassemble(flow);
|
struct packet *new_pkt = ip_frag_reassemble(mgr, flow);
|
||||||
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
ip_flow_free(flow);
|
ip_flow_free(flow);
|
||||||
ip_flow_table_del(mgr, flow);
|
|
||||||
|
|
||||||
return new_pkt;
|
return new_pkt;
|
||||||
}
|
}
|
||||||
@@ -924,41 +1010,41 @@ struct packet *ipv4_reassemble_packet(struct ip_reassemble_manager *mgr, const s
|
|||||||
|
|
||||||
struct packet *ipv6_reassemble_packet(struct ip_reassemble_manager *mgr, const struct packet *pkt)
|
struct packet *ipv6_reassemble_packet(struct ip_reassemble_manager *mgr, const struct packet *pkt)
|
||||||
{
|
{
|
||||||
struct layer_record *layer = pkt->frag_layer;
|
const struct layer_record *layer = pkt->frag_layer;
|
||||||
const struct ip6_hdr *hdr = (const struct ip6_hdr *)layer->hdr_ptr;
|
const struct ip6_hdr *hdr = (const struct ip6_hdr *)layer->hdr_ptr;
|
||||||
struct ip6_frag *frag_ext = ipv6_hdr_get_frag_ext(hdr);
|
const struct ip6_frag *frag_hdr = ipv6_hdr_get_frag_ext(hdr);
|
||||||
if (frag_ext == NULL)
|
if (frag_hdr == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *frag_data = (char *)frag_hdr + sizeof(struct ip6_frag);
|
||||||
|
uint16_t frag_len = ipv6_hdr_get_payload_len(hdr) - sizeof(struct ip6_frag);
|
||||||
|
if (frag_data + frag_len > pkt->data_ptr + pkt->data_len)
|
||||||
|
{
|
||||||
|
IP_REASSEMBLE_ERROR("unexpected header length, frag id: %lu", ipv6_frag_get_ident(frag_hdr));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct ip_flow_key key = {0};
|
struct ip_flow_key key = {0};
|
||||||
memcpy(&key.src_dst_addr[0], hdr->ip6_src.s6_addr, 16);
|
memcpy(&key.src_dst_addr[0], hdr->ip6_src.s6_addr, 16);
|
||||||
memcpy(&key.src_dst_addr[2], hdr->ip6_dst.s6_addr, 16);
|
memcpy(&key.src_dst_addr[2], hdr->ip6_dst.s6_addr, 16);
|
||||||
key.src_dst_len = IPV6_KEYLEN;
|
key.src_dst_len = IPV6_KEYLEN;
|
||||||
key.ip_id = frag_ext->ip6f_ident;
|
key.ip_id = ipv6_frag_get_ident(frag_hdr);
|
||||||
key.proto = 0; // only first fragment has the upper layer protocol
|
key.proto = 0; // only first fragment has the upper layer protocol
|
||||||
|
|
||||||
struct ip_flow *flow = ip_flow_table_update(mgr, &key);
|
struct ip_flow *flow = ip_reassemble_manager_update_flow(mgr, &key);
|
||||||
if (flow == NULL)
|
if (flow == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data = (char *)layer->hdr_ptr + sizeof(struct ip6_hdr) + sizeof(struct ip6_frag);
|
bool more_frags = ipv6_frag_get_more(frag_hdr);
|
||||||
uint16_t len = ipv6_hdr_get_payload_len(hdr) - sizeof(struct ip6_frag);
|
uint16_t frag_offset = ipv6_frag_get_offset(frag_hdr);
|
||||||
|
if (ip_flow_update(mgr, flow, pkt, frag_data, frag_len, frag_offset, more_frags) != 0)
|
||||||
if (data + len > pkt->data_ptr + pkt->data_len)
|
|
||||||
{
|
|
||||||
IP_REASSEMBLE_ERROR("unexpected header length on fragmented packet, frag_id: %lu", frag_ext->ip6f_ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool more_frags = (frag_ext->ip6f_offlg & IP6F_MORE_FRAG);
|
|
||||||
uint16_t offset = ntohs(frag_ext->ip6f_offlg & IP6F_OFF_MASK);
|
|
||||||
if (ip_flow_update(flow, pkt, data, len, offset, more_frags) != 0)
|
|
||||||
{
|
{
|
||||||
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
ip_flow_free(flow);
|
ip_flow_free(flow);
|
||||||
ip_flow_table_del(mgr, flow);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,9 +1053,9 @@ struct packet *ipv6_reassemble_packet(struct ip_reassemble_manager *mgr, const s
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct packet *new_pkt = ip_frag_reassemble(flow);
|
struct packet *new_pkt = ip_frag_reassemble(mgr, flow);
|
||||||
|
ip_reassemble_manager_del_flow(mgr, flow);
|
||||||
ip_flow_free(flow);
|
ip_flow_free(flow);
|
||||||
ip_flow_table_del(mgr, flow);
|
|
||||||
|
|
||||||
return new_pkt;
|
return new_pkt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,45 @@ struct ip_reassemble_config
|
|||||||
{
|
{
|
||||||
bool enable;
|
bool enable;
|
||||||
|
|
||||||
uint32_t timeout;
|
uint32_t timeout; // seconds
|
||||||
uint32_t bucket_entries;
|
uint32_t bucket_entries;
|
||||||
uint32_t bucket_num;
|
uint32_t bucket_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ip_reassemble_stat
|
||||||
|
{
|
||||||
|
// IPv4 flow stat
|
||||||
|
uint64_t ip4_flow_find;
|
||||||
|
uint64_t ip4_flow_add;
|
||||||
|
uint64_t ip4_flow_del;
|
||||||
|
uint64_t ip4_flow_timeout;
|
||||||
|
|
||||||
|
uint64_t ip4_flow_fail_no_space;
|
||||||
|
uint64_t ip4_flow_fail_overlap;
|
||||||
|
uint64_t ip4_flow_fail_many_frag;
|
||||||
|
uint64_t ip4_flow_fail_invalid_length;
|
||||||
|
uint64_t ip4_flow_bypass_dup_fist_frag;
|
||||||
|
uint64_t ip4_flow_bypass_dup_last_frag;
|
||||||
|
|
||||||
|
// IPv6 flow stat
|
||||||
|
uint64_t ip6_flow_find;
|
||||||
|
uint64_t ip6_flow_add;
|
||||||
|
uint64_t ip6_flow_del;
|
||||||
|
uint64_t ip6_flow_timeout;
|
||||||
|
|
||||||
|
uint64_t ip6_flow_fail_no_space;
|
||||||
|
uint64_t ip6_flow_fail_overlap;
|
||||||
|
uint64_t ip6_flow_fail_many_frag;
|
||||||
|
uint64_t ip6_flow_fail_invalid_length;
|
||||||
|
uint64_t ip6_flow_bypass_dup_fist_frag;
|
||||||
|
uint64_t ip6_flow_bypass_dup_last_frag;
|
||||||
|
};
|
||||||
|
|
||||||
struct ip_reassemble_manager *ip_reassemble_manager_create(const struct ip_reassemble_config *config);
|
struct ip_reassemble_manager *ip_reassemble_manager_create(const struct ip_reassemble_config *config);
|
||||||
void ip_reassemble_manager_destory(struct ip_reassemble_manager *mgr);
|
void ip_reassemble_manager_destory(struct ip_reassemble_manager *mgr);
|
||||||
void ip_reassemble_manager_stat(struct ip_reassemble_manager *mgr);
|
void ip_reassemble_manager_expire(struct ip_reassemble_manager *mgr);
|
||||||
|
void ip_reassemble_manager_print_stat(struct ip_reassemble_manager *mgr);
|
||||||
|
struct ip_reassemble_stat *ip_reassemble_manager_get_stat(struct ip_reassemble_manager *mgr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the reassembled packet, or NULL if the packet is not reassembled
|
* Returns the reassembled packet, or NULL if the packet is not reassembled
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ target_link_libraries(gtest_ipv4_reassemble ip_reassemble gtest)
|
|||||||
add_executable(gtest_ipv6_reassemble gtest_ipv6_reassemble.cpp)
|
add_executable(gtest_ipv6_reassemble gtest_ipv6_reassemble.cpp)
|
||||||
target_link_libraries(gtest_ipv6_reassemble ip_reassemble gtest)
|
target_link_libraries(gtest_ipv6_reassemble ip_reassemble gtest)
|
||||||
|
|
||||||
|
add_executable(gtest_ip_reassemble gtest_ip_reassemble.cpp)
|
||||||
|
target_link_libraries(gtest_ip_reassemble ip_reassemble gtest)
|
||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
gtest_discover_tests(gtest_ipv4_reassemble)
|
gtest_discover_tests(gtest_ipv4_reassemble)
|
||||||
gtest_discover_tests(gtest_ipv6_reassemble)
|
gtest_discover_tests(gtest_ipv6_reassemble)
|
||||||
|
gtest_discover_tests(gtest_ip_reassemble)
|
||||||
15
src/ip_reassemble/test/gtest_ip_reassemble.cpp
Normal file
15
src/ip_reassemble/test/gtest_ip_reassemble.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "gtest_utils.h"
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IP_REASSEMBLE, NESTED)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// IP in IP, both with fragmentation
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
@@ -1,17 +1,4 @@
|
|||||||
#include <gtest/gtest.h>
|
#include "gtest_utils.h"
|
||||||
|
|
||||||
#include "timestamp.h"
|
|
||||||
#include "tcp_utils.h"
|
|
||||||
#include "ipv4_utils.h"
|
|
||||||
#include "packet_helpers.h"
|
|
||||||
#include "ip_reassemble.h"
|
|
||||||
|
|
||||||
struct ip_reassemble_config config = {
|
|
||||||
.enable = true,
|
|
||||||
.timeout = 1000,
|
|
||||||
.bucket_entries = 16,
|
|
||||||
.bucket_num = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frame 4: 60 bytes on wire (480 bits), 60 bytes captured (480 bits)
|
* Frame 4: 60 bytes on wire (480 bits), 60 bytes captured (480 bits)
|
||||||
@@ -204,30 +191,55 @@ unsigned char expect[] = {
|
|||||||
0xf4, 0xa5, 0x27, 0x0f, 0x91, 0x07, 0x24, 0x8b, 0x03, 0xd5, 0x18, 0xe7, 0x50, 0x18, 0xff, 0x00, 0x30, 0x16, 0x00, 0x00, 0x61, 0x62, 0x63, 0x0a // data from frag2
|
0xf4, 0xa5, 0x27, 0x0f, 0x91, 0x07, 0x24, 0x8b, 0x03, 0xd5, 0x18, 0xe7, 0x50, 0x18, 0xff, 0x00, 0x30, 0x16, 0x00, 0x00, 0x61, 0x62, 0x63, 0x0a // data from frag2
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(IPV4_REASSEMBLE, PADDING)
|
#if 1
|
||||||
|
TEST(IPV4_REASSEMBLE, PADDING_ORDER)
|
||||||
{
|
{
|
||||||
struct packet pkt;
|
struct packet pkt;
|
||||||
struct packet *new_pkt;
|
struct packet *new_pkt;
|
||||||
const struct layer_record *layer;
|
const struct layer_record *layer;
|
||||||
struct ip_reassemble_manager *mgr;
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
timestamp_update();
|
timestamp_update();
|
||||||
|
|
||||||
mgr = ip_reassemble_manager_create(&config);
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
EXPECT_TRUE(mgr != NULL);
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag1
|
// frag1
|
||||||
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt == NULL);
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag2
|
// frag2
|
||||||
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt);
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 1, 1, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// check packet
|
// check packet
|
||||||
packet_print(new_pkt);
|
// packet_print(new_pkt);
|
||||||
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
||||||
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
||||||
@@ -272,26 +284,446 @@ TEST(IPV4_REASSEMBLE, PADDING)
|
|||||||
|
|
||||||
ip_reassemble_manager_destory(mgr);
|
ip_reassemble_manager_destory(mgr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV4_REASSEMBLE, PADDING_UNORDER)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
const struct layer_record *layer;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 1, 1, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// check packet
|
||||||
|
// packet_print(new_pkt);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
||||||
|
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
||||||
|
|
||||||
|
// check IPv4
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_IPV4);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct ip *hdr = (struct ip *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_version(hdr) == 4);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_hdr_len(hdr) == 20 /* IPv4 */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_tos(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_total_len(hdr) == 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ipid(hdr) == 0xffff);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_flags(hdr) == 0x0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_frag_offset(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ttl(hdr) == 127);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_proto(hdr) == 6);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_checksum(hdr) == 0x6d73); // NOTE this is correct checksum
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_src_addr(hdr) == 0xc0a82467);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_dst_addr(hdr) == 0xc0a82889);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_len(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == NULL);
|
||||||
|
|
||||||
|
// check TCP
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_TCP);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_dst_port(tcp_hdr) == 9999);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_seq(tcp_hdr) == 2433164423);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_ack(tcp_hdr) == 64297191);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp_hdr) == 20);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_flags(tcp_hdr) == 0x018);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_window(tcp_hdr) == 65280);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_checksum(tcp_hdr) == 0x5e92);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_urg_ptr(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_len(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
TEST(IPV4_REASSEMBLE, EXPIRE)
|
TEST(IPV4_REASSEMBLE, EXPIRE)
|
||||||
{
|
{
|
||||||
// TODO
|
struct packet pkt;
|
||||||
}
|
struct packet *new_pkt;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// sleep 1s
|
||||||
|
sleep(1);
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 2, 1, 1, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV4_REASSEMBLE, DUP_FIRST_FRAG)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
const struct layer_record *layer;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
3, 1, 1, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// check packet
|
||||||
|
// packet_print(new_pkt);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
||||||
|
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
||||||
|
|
||||||
|
// check IPv4
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_IPV4);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct ip *hdr = (struct ip *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_version(hdr) == 4);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_hdr_len(hdr) == 20 /* IPv4 */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_tos(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_total_len(hdr) == 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ipid(hdr) == 0xffff);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_flags(hdr) == 0x0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_frag_offset(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ttl(hdr) == 127);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_proto(hdr) == 6);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_checksum(hdr) == 0x6d73); // NOTE this is correct checksum
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_src_addr(hdr) == 0xc0a82467);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_dst_addr(hdr) == 0xc0a82889);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_len(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == NULL);
|
||||||
|
|
||||||
|
// check TCP
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_TCP);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_dst_port(tcp_hdr) == 9999);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_seq(tcp_hdr) == 2433164423);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_ack(tcp_hdr) == 64297191);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp_hdr) == 20);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_flags(tcp_hdr) == 0x018);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_window(tcp_hdr) == 65280);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_checksum(tcp_hdr) == 0x5e92);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_urg_ptr(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_len(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV4_REASSEMBLE, DUP_LAST_FRAG)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
const struct layer_record *layer;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
3, 1, 1, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// check packet
|
||||||
|
// packet_print(new_pkt);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
||||||
|
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
||||||
|
|
||||||
|
// check IPv4
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_IPV4);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct ip *hdr = (struct ip *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_version(hdr) == 4);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_hdr_len(hdr) == 20 /* IPv4 */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_tos(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_total_len(hdr) == 20 /* IPv4 */ + 20 /* TCP */ + 28 /* DATA */);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ipid(hdr) == 0xffff);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_flags(hdr) == 0x0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_frag_offset(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_ttl(hdr) == 127);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_proto(hdr) == 6);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_checksum(hdr) == 0x6d73); // NOTE this is correct checksum
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_src_addr(hdr) == 0xc0a82467);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_dst_addr(hdr) == 0xc0a82889);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_len(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == NULL);
|
||||||
|
|
||||||
|
// check TCP
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_TCP);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct tcphdr *tcp_hdr = (struct tcphdr *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_src_port(tcp_hdr) == 62629);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_dst_port(tcp_hdr) == 9999);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_seq(tcp_hdr) == 2433164423);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_ack(tcp_hdr) == 64297191);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp_hdr) == 20);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_flags(tcp_hdr) == 0x018);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_window(tcp_hdr) == 65280);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_checksum(tcp_hdr) == 0x5e92);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_urg_ptr(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_len(tcp_hdr) == 0);
|
||||||
|
EXPECT_TRUE(tcp_hdr_get_opt_data(tcp_hdr) == NULL);
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
TEST(IPV4_REASSEMBLE, FULL)
|
TEST(IPV4_REASSEMBLE, FULL)
|
||||||
{
|
{
|
||||||
// TODO
|
struct packet pkt;
|
||||||
}
|
struct packet *new_pkt;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 1,
|
||||||
|
.bucket_num = 1,
|
||||||
|
};
|
||||||
|
|
||||||
TEST(IPV4_REASSEMBLE, HOLE)
|
timestamp_update();
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IPV4_REASSEMBLE, NESTED)
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
{
|
EXPECT_TRUE(mgr != NULL);
|
||||||
// TODO
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
char dup_frag[sizeof(frag1)] = {0};
|
||||||
|
memcpy(dup_frag, frag1, sizeof(frag1));
|
||||||
|
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
|
||||||
|
|
||||||
|
// flow1
|
||||||
|
packet_set_ipv4_src_addr(&pkt, 1);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
1, 1, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// flow2
|
||||||
|
packet_set_ipv4_src_addr(&pkt, 2);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
2, 2, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// flow3
|
||||||
|
packet_set_ipv4_src_addr(&pkt, 3);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
3, 2, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
1, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV4_REASSEMBLE, OVERLAP)
|
||||||
|
{
|
||||||
|
// TEST ON IPv6
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
#include <gtest/gtest.h>
|
#include "gtest_utils.h"
|
||||||
|
|
||||||
#include "timestamp.h"
|
|
||||||
#include "udp_utils.h"
|
|
||||||
#include "ipv6_utils.h"
|
|
||||||
#include "packet_helpers.h"
|
|
||||||
#include "ip_reassemble.h"
|
|
||||||
|
|
||||||
struct ip_reassemble_config config = {
|
|
||||||
.enable = true,
|
|
||||||
.timeout = 1000,
|
|
||||||
.bucket_entries = 16,
|
|
||||||
.bucket_num = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frame 3: 1510 bytes on wire (12080 bits), 1510 bytes captured (12080 bits)
|
* Frame 3: 1510 bytes on wire (12080 bits), 1510 bytes captured (12080 bits)
|
||||||
@@ -615,40 +602,77 @@ unsigned char expect[] = {
|
|||||||
0x7b, 0x0d, 0x49, 0xe1, 0x76, 0x34, 0x07, 0xf7, 0x9e, 0xe5, 0xb7, 0x66, 0x39, 0xb1, 0xb0, 0xa0, 0x1a, 0x44, 0x90, 0xce, 0x07, 0x03, 0xf2, 0x1b, 0x0e, 0xc6,
|
0x7b, 0x0d, 0x49, 0xe1, 0x76, 0x34, 0x07, 0xf7, 0x9e, 0xe5, 0xb7, 0x66, 0x39, 0xb1, 0xb0, 0xa0, 0x1a, 0x44, 0x90, 0xce, 0x07, 0x03, 0xf2, 0x1b, 0x0e, 0xc6,
|
||||||
0x17, 0xed, 0xd8, 0x4f, 0x4f};
|
0x17, 0xed, 0xd8, 0x4f, 0x4f};
|
||||||
|
|
||||||
|
#if 1
|
||||||
TEST(IPV6_REASSEMBLE, NORMAL)
|
TEST(IPV6_REASSEMBLE, NORMAL)
|
||||||
{
|
{
|
||||||
struct packet pkt;
|
struct packet pkt;
|
||||||
struct packet *new_pkt;
|
struct packet *new_pkt;
|
||||||
const struct layer_record *layer;
|
const struct layer_record *layer;
|
||||||
struct ip_reassemble_manager *mgr;
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
timestamp_update();
|
timestamp_update();
|
||||||
|
|
||||||
mgr = ip_reassemble_manager_create(&config);
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
EXPECT_TRUE(mgr != NULL);
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag1
|
// frag1
|
||||||
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt == NULL);
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag2
|
// frag2
|
||||||
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt == NULL);
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag3
|
// frag3
|
||||||
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
|
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt == NULL);
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
3, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// frag4
|
// frag4
|
||||||
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
||||||
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
EXPECT_TRUE(new_pkt);
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
4, 1, 1, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
// check packet
|
// check packet
|
||||||
packet_print(new_pkt);
|
// packet_print(new_pkt);
|
||||||
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
|
EXPECT_TRUE(new_pkt->data_len == 14 /* ETH */ + 40 /* IPv6 */ + 8 /* UDP */ + 5379 /* DATA */);
|
||||||
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
EXPECT_TRUE(new_pkt->data_len == sizeof(expect));
|
||||||
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
EXPECT_TRUE(memcmp(new_pkt->data_ptr, expect, new_pkt->data_len) == 0);
|
||||||
@@ -687,26 +711,458 @@ TEST(IPV6_REASSEMBLE, NORMAL)
|
|||||||
|
|
||||||
ip_reassemble_manager_destory(mgr);
|
ip_reassemble_manager_destory(mgr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
TEST(IPV6_REASSEMBLE, EXPIRE)
|
TEST(IPV6_REASSEMBLE, EXPIRE)
|
||||||
{
|
{
|
||||||
// TODO
|
struct packet pkt;
|
||||||
}
|
struct packet *new_pkt;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// sleep 1
|
||||||
|
sleep(1);
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 2, 1, 1, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV6_REASSEMBLE, DUP_FIRST_FRAG)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
const struct layer_record *layer;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
3, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag3
|
||||||
|
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
4, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag4
|
||||||
|
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
5, 1, 1, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 1, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, 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_TYPE_IPV6);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct ip6_hdr *hdr = (struct ip6_hdr *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_version(hdr) == 6);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_traffic_class(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_flow_label(hdr) == 0x21289);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_payload_len(hdr) == 5387);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_next_header(hdr) == 17); // UDP
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_hop_limit(hdr) == 64);
|
||||||
|
char src_str[INET6_ADDRSTRLEN];
|
||||||
|
char dst_str[INET6_ADDRSTRLEN];
|
||||||
|
struct in6_addr src_addr = ipv6_hdr_get_src_in6_addr(hdr);
|
||||||
|
struct in6_addr dst_addr = ipv6_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(ipv6_hdr_get_frag_ext(hdr) == NULL);
|
||||||
|
|
||||||
|
// check UDP
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_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_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV6_REASSEMBLE, DUP_LAST_FRAG)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
const struct layer_record *layer;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag4
|
||||||
|
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag4
|
||||||
|
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag3
|
||||||
|
packet_parse(&pkt, (const char *)frag3, sizeof(frag3));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
3, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
4, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
5, 1, 1, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 1); // ip6: nospace, overlap, many frag, invalid length, dup first frag, 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_TYPE_IPV6);
|
||||||
|
EXPECT_TRUE(layer);
|
||||||
|
struct ip6_hdr *hdr = (struct ip6_hdr *)layer->hdr_ptr;
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_version(hdr) == 6);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_traffic_class(hdr) == 0);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_flow_label(hdr) == 0x21289);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_payload_len(hdr) == 5387);
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_next_header(hdr) == 17); // UDP
|
||||||
|
EXPECT_TRUE(ipv6_hdr_get_hop_limit(hdr) == 64);
|
||||||
|
char src_str[INET6_ADDRSTRLEN];
|
||||||
|
char dst_str[INET6_ADDRSTRLEN];
|
||||||
|
struct in6_addr src_addr = ipv6_hdr_get_src_in6_addr(hdr);
|
||||||
|
struct in6_addr dst_addr = ipv6_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(ipv6_hdr_get_frag_ext(hdr) == NULL);
|
||||||
|
|
||||||
|
// check UDP
|
||||||
|
layer = packet_get_innermost_layer(new_pkt, LAYER_TYPE_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_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
TEST(IPV6_REASSEMBLE, FULL)
|
TEST(IPV6_REASSEMBLE, FULL)
|
||||||
{
|
{
|
||||||
// TODO
|
struct packet pkt;
|
||||||
}
|
struct packet *new_pkt;
|
||||||
|
struct in6_addr src_addr;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 1,
|
||||||
|
.bucket_num = 1,
|
||||||
|
};
|
||||||
|
|
||||||
TEST(IPV6_REASSEMBLE, HOLE)
|
timestamp_update();
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IPV6_REASSEMBLE, NESTED)
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
{
|
EXPECT_TRUE(mgr != NULL);
|
||||||
// TODO
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
char dup_frag[sizeof(frag1)] = {0};
|
||||||
|
memcpy(dup_frag, frag1, sizeof(frag1));
|
||||||
|
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
|
||||||
|
|
||||||
|
// flow1
|
||||||
|
memset(&src_addr, 1, sizeof(src_addr));
|
||||||
|
packet_set_ipv6_src_addr(&pkt, src_addr);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// flow2
|
||||||
|
memset(&src_addr, 2, sizeof(src_addr));
|
||||||
|
packet_set_ipv6_src_addr(&pkt, src_addr);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 2, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// flow3
|
||||||
|
memset(&src_addr, 3, sizeof(src_addr));
|
||||||
|
packet_set_ipv6_src_addr(&pkt, src_addr);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
3, 2, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
1, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
TEST(IPV6_REASSEMBLE, OVERLAP)
|
||||||
|
{
|
||||||
|
struct packet pkt;
|
||||||
|
struct packet *new_pkt;
|
||||||
|
struct ip_reassemble_manager *mgr;
|
||||||
|
struct ip_reassemble_config config = {
|
||||||
|
.enable = true,
|
||||||
|
.timeout = 1,
|
||||||
|
.bucket_entries = 16,
|
||||||
|
.bucket_num = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
timestamp_update();
|
||||||
|
|
||||||
|
mgr = ip_reassemble_manager_create(&config);
|
||||||
|
EXPECT_TRUE(mgr != NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
0, 0, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag1
|
||||||
|
packet_parse(&pkt, (const char *)frag1, sizeof(frag1));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
1, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag2
|
||||||
|
packet_parse(&pkt, (const char *)frag2, sizeof(frag2));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
2, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag3 -- overwrite frag offset
|
||||||
|
char dup_frag[sizeof(frag3)] = {0};
|
||||||
|
memcpy(dup_frag, frag3, sizeof(frag3));
|
||||||
|
packet_parse(&pkt, (const char *)dup_frag, sizeof(dup_frag));
|
||||||
|
packet_set_ipv6_frag_offset(&pkt, 2048);
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
3, 1, 0, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// frag4
|
||||||
|
packet_parse(&pkt, (const char *)frag4, sizeof(frag4));
|
||||||
|
new_pkt = ip_reassemble_packet(mgr, &pkt);
|
||||||
|
EXPECT_TRUE(new_pkt == NULL);
|
||||||
|
// ip_reassemble_manager_print_stat(mgr);
|
||||||
|
check_stat(ip_reassemble_manager_get_stat(mgr),
|
||||||
|
0, 0, 0, 0, // ip4: find, add, del, timeout
|
||||||
|
0, 0, 0, 0, 0, 0, // ip4: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
4, 1, 1, 0, // ip6: find, add, del, timeout
|
||||||
|
0, 1, 0, 0, 0, 0); // ip6: nospace, overlap, many frag, invalid length, dup first frag, dup last frag
|
||||||
|
|
||||||
|
// free packet
|
||||||
|
packet_free(new_pkt);
|
||||||
|
|
||||||
|
ip_reassemble_manager_destory(mgr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|||||||
86
src/ip_reassemble/test/gtest_utils.h
Normal file
86
src/ip_reassemble/test/gtest_utils.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#ifndef _GTEST_UTILS_H
|
||||||
|
#define _GTEST_UTILS_H
|
||||||
|
|
||||||
|
#ifdef __cpluscplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "timestamp.h"
|
||||||
|
#include "udp_utils.h"
|
||||||
|
#include "tcp_utils.h"
|
||||||
|
#include "ipv4_utils.h"
|
||||||
|
#include "ipv6_utils.h"
|
||||||
|
#include "packet_helpers.h"
|
||||||
|
#include "ip_reassemble.h"
|
||||||
|
|
||||||
|
static inline void packet_set_ipv4_src_addr(struct packet *pkt, uint32_t saddr)
|
||||||
|
{
|
||||||
|
const struct layer_record *ipv4_layer = packet_get_innermost_layer(pkt, LAYER_TYPE_IPV4);
|
||||||
|
EXPECT_TRUE(ipv4_layer);
|
||||||
|
struct ip *hdr = (struct ip *)ipv4_layer->hdr_ptr;
|
||||||
|
ipv4_hdr_set_src_addr(hdr, saddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void packet_set_ipv6_src_addr(struct packet *pkt, struct in6_addr saddr)
|
||||||
|
{
|
||||||
|
const struct layer_record *ipv6_layer = packet_get_innermost_layer(pkt, LAYER_TYPE_IPV6);
|
||||||
|
EXPECT_TRUE(ipv6_layer);
|
||||||
|
struct ip6_hdr *hdr = (struct ip6_hdr *)ipv6_layer->hdr_ptr;
|
||||||
|
ipv6_hdr_set_src_in6_addr(hdr, saddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void packet_set_ipv6_frag_offset(struct packet *pkt, uint16_t offset)
|
||||||
|
{
|
||||||
|
const struct layer_record *ipv6_layer = (struct layer_record *)packet_get_innermost_layer(pkt, LAYER_TYPE_IPV6);
|
||||||
|
EXPECT_TRUE(ipv6_layer);
|
||||||
|
struct ip6_hdr *hdr = (struct ip6_hdr *)ipv6_layer->hdr_ptr;
|
||||||
|
struct ip6_frag *frag_hdr = ipv6_hdr_get_frag_ext(hdr);
|
||||||
|
EXPECT_TRUE(frag_hdr);
|
||||||
|
ipv6_frag_set_offset(frag_hdr, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void check_stat(struct ip_reassemble_stat *stat,
|
||||||
|
uint64_t ip4_flow_find, uint64_t ip4_flow_add, uint64_t ip4_flow_del, uint64_t ip4_flow_timeout,
|
||||||
|
uint64_t ip4_flow_fail_no_space, uint64_t ip4_flow_fail_overlap, uint64_t ip4_flow_fail_many_frag,
|
||||||
|
uint64_t ip4_flow_fail_invalid_length, uint64_t ip4_flow_bypass_dup_fist_frag, uint64_t ip4_flow_bypass_dup_last_frag,
|
||||||
|
uint64_t ip6_flow_find, uint64_t ip6_flow_add, uint64_t ip6_flow_del, uint64_t ip6_flow_timeout,
|
||||||
|
uint64_t ip6_flow_fail_no_space, uint64_t ip6_flow_fail_overlap, uint64_t ip6_flow_fail_many_frag,
|
||||||
|
uint64_t ip6_flow_fail_invalid_length, uint64_t ip6_flow_bypass_dup_fist_frag, uint64_t ip6_flow_bypass_dup_last_frag)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(stat != NULL);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_find == ip4_flow_find);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_add == ip4_flow_add);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_del == ip4_flow_del);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_timeout == ip4_flow_timeout);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_fail_no_space == ip4_flow_fail_no_space);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_fail_overlap == ip4_flow_fail_overlap);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_fail_many_frag == ip4_flow_fail_many_frag);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_fail_invalid_length == ip4_flow_fail_invalid_length);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_bypass_dup_fist_frag == ip4_flow_bypass_dup_fist_frag);
|
||||||
|
EXPECT_TRUE(stat->ip4_flow_bypass_dup_last_frag == ip4_flow_bypass_dup_last_frag);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_find == ip6_flow_find);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_add == ip6_flow_add);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_del == ip6_flow_del);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_timeout == ip6_flow_timeout);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_fail_no_space == ip6_flow_fail_no_space);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_fail_overlap == ip6_flow_fail_overlap);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_fail_many_frag == ip6_flow_fail_many_frag);
|
||||||
|
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_fail_invalid_length == ip6_flow_fail_invalid_length);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_bypass_dup_fist_frag == ip6_flow_bypass_dup_fist_frag);
|
||||||
|
EXPECT_TRUE(stat->ip6_flow_bypass_dup_last_frag == ip6_flow_bypass_dup_last_frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cpluscplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -100,8 +100,6 @@ static inline struct ip6_frag *ipv6_hdr_get_frag_ext(const struct ip6_hdr *hdr)
|
|||||||
return (struct ip6_frag *)((char *)hdr + sizeof(struct ip6_hdr));
|
return (struct ip6_frag *)((char *)hdr + sizeof(struct ip6_hdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO IPv6 extension headers
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* set
|
* set
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@@ -146,7 +144,56 @@ static inline void ipv6_hdr_set_dst_in6_addr(struct ip6_hdr *hdr, struct in6_add
|
|||||||
hdr->ip6_dst = dst_addr;
|
hdr->ip6_dst = dst_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO IPv6 extension headers
|
/******************************************************************************
|
||||||
|
* IPv6 frag extension headers
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
static inline uint8_t ipv6_frag_get_next_header(const struct ip6_frag *frag)
|
||||||
|
{
|
||||||
|
return frag->ip6f_nxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t ipv6_frag_get_offset(const struct ip6_frag *frag)
|
||||||
|
{
|
||||||
|
return ntohs(frag->ip6f_offlg & IP6F_OFF_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t ipv6_frag_get_ident(const struct ip6_frag *frag)
|
||||||
|
{
|
||||||
|
return ntohl(frag->ip6f_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool ipv6_frag_get_more(const struct ip6_frag *frag)
|
||||||
|
{
|
||||||
|
return (frag->ip6f_offlg & IP6F_MORE_FRAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipv6_frag_set_next_header(struct ip6_frag *frag, uint8_t next_header)
|
||||||
|
{
|
||||||
|
frag->ip6f_nxt = next_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipv6_frag_set_offset(struct ip6_frag *frag, uint16_t offset)
|
||||||
|
{
|
||||||
|
frag->ip6f_offlg = (frag->ip6f_offlg & ~IP6F_OFF_MASK) | htons(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipv6_frag_set_ident(struct ip6_frag *frag, uint32_t ident)
|
||||||
|
{
|
||||||
|
frag->ip6f_ident = htonl(ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipv6_frag_set_more(struct ip6_frag *frag, bool more)
|
||||||
|
{
|
||||||
|
if (more)
|
||||||
|
{
|
||||||
|
frag->ip6f_offlg |= IP6F_MORE_FRAG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frag->ip6f_offlg &= ~IP6F_MORE_FRAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cpluscplus
|
#ifdef __cpluscplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,41 @@ TEST(IPV6_UTILS, SET)
|
|||||||
EXPECT_TRUE(memcmp(buff, data, 40) == 0);
|
EXPECT_TRUE(memcmp(buff, data, 40) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fragment Header for IPv6
|
||||||
|
* Next header: UDP (17)
|
||||||
|
* Reserved octet: 0x00
|
||||||
|
* 0000 0101 1010 1... = Offset: 181 (1448 bytes)
|
||||||
|
* .... .... .... .00. = Reserved bits: 0
|
||||||
|
* .... .... .... ...1 = More Fragments: Yes
|
||||||
|
* Identification: 0xf88eb466
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char frag[] = {
|
||||||
|
0x11, 0x00, 0x05, 0xa9, 0xf8, 0x8e, 0xb4, 0x66};
|
||||||
|
|
||||||
|
TEST(IPV6_FRAG_HDR, GET)
|
||||||
|
{
|
||||||
|
const struct ip6_frag *hdr = (struct ip6_frag *)frag;
|
||||||
|
EXPECT_TRUE(ipv6_frag_get_next_header(hdr) == 17);
|
||||||
|
EXPECT_TRUE(ipv6_frag_get_offset(hdr) == 1448);
|
||||||
|
EXPECT_TRUE(ipv6_frag_get_more(hdr) == 1);
|
||||||
|
EXPECT_TRUE(ipv6_frag_get_ident(hdr) == 0xf88eb466);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IPV6_FRAG_HDR, SET)
|
||||||
|
{
|
||||||
|
char buff[8] = {0};
|
||||||
|
|
||||||
|
struct ip6_frag *hdr = (struct ip6_frag *)buff;
|
||||||
|
ipv6_frag_set_next_header(hdr, 17);
|
||||||
|
ipv6_frag_set_offset(hdr, 1448);
|
||||||
|
ipv6_frag_set_more(hdr, 1);
|
||||||
|
ipv6_frag_set_ident(hdr, 0xf88eb466);
|
||||||
|
|
||||||
|
EXPECT_TRUE(memcmp(buff, frag, 8) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ TEST(TCP_UTILS, GET)
|
|||||||
|
|
||||||
TEST(TCP_UTILS, SET1)
|
TEST(TCP_UTILS, SET1)
|
||||||
{
|
{
|
||||||
char buff[40];
|
char buff[40] = {0};
|
||||||
|
|
||||||
struct tcphdr *hdr = (struct tcphdr *)buff;
|
struct tcphdr *hdr = (struct tcphdr *)buff;
|
||||||
tcp_hdr_set_src_port(hdr, 55555);
|
tcp_hdr_set_src_port(hdr, 55555);
|
||||||
|
|||||||
Reference in New Issue
Block a user