support IPv4 & IPv6 frag reassemble

This commit is contained in:
luwenpeng
2024-02-22 18:52:04 +08:00
parent 5e5ac458f2
commit 5cd0571b4d
21 changed files with 2116 additions and 95 deletions

41
src/packet/checksum.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef _CHECKSUM_H
#define _CHECKSUM_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdint.h>
// https://datatracker.ietf.org/doc/html/rfc1071
static inline uint16_t checksum(char *data, int len)
{
long sum = 0;
uint16_t *addr = (uint16_t *)data;
while (len > 1)
{
sum += *addr++;
len -= 2;
}
if (len > 0)
{
sum += *(unsigned char *)addr;
}
// Fold 32-bit sum to 16 bits
while (sum >> 16)
{
sum = (sum & 0xffff) + (sum >> 16);
}
return (uint16_t)(~sum);
}
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -126,6 +126,11 @@ static inline uint8_t ipv4_hdr_get_opt_len(const struct ip *hdr)
static inline const char *ipv4_hdr_get_opt_data(const struct ip *hdr)
{
if (ipv4_hdr_get_opt_len(hdr) == 0)
{
return NULL;
}
return (const char *)hdr + sizeof(struct ip);
}

View File

@@ -35,6 +35,16 @@ extern "C"
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Fragment Header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Next Header | Reserved | Fragment Offset |Res|M|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Identification |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/******************************************************************************
@@ -81,6 +91,15 @@ static inline struct in6_addr ipv6_hdr_get_dst_in6_addr(const struct ip6_hdr *hd
return hdr->ip6_dst;
}
static inline struct ip6_frag *ipv6_hdr_get_frag_ext(const struct ip6_hdr *hdr)
{
if (hdr->ip6_nxt != IPPROTO_FRAGMENT)
{
return NULL;
}
return (struct ip6_frag *)((char *)hdr + sizeof(struct ip6_hdr));
}
// TODO IPv6 extension headers
/******************************************************************************

View File

@@ -861,12 +861,12 @@ static inline const char *parse_ipv4(struct packet *handler, const char *data, u
return data;
}
struct ip *hdr = (struct ip *)data;
uint8_t next_proto = ipv4_get_proto(hdr);
uint8_t next_proto = ipv4_hdr_get_proto(hdr);
uint16_t hdr_len = ipv4_hdr_get_hdr_len(hdr);
SET_LAYER(handler, layer, LAYER_TYPE_IPV4, hdr_len, data, len);
// ip fragmented
if ((ntohs(hdr->ip_off) & IP_MF) || (ntohs(hdr->ip_off) & IP_OFFMASK))
if (ipv4_hdr_get_mf_flag(hdr) || ipv4_hdr_get_frag_offset(hdr))
{
PACKET_LOG_DEBUG("ip is fragmented");
handler->frag_layer = layer;
@@ -893,7 +893,13 @@ static inline const char *parse_ipv6(struct packet *handler, const char *data, u
uint8_t next_proto = ipv6_hdr_get_next_header((const struct ip6_hdr *)data);
SET_LAYER(handler, layer, LAYER_TYPE_IPV6, sizeof(struct ip6_hdr), data, len);
// TODO ipv6 fragment
// ipv6 fragment
if (next_proto == IPPROTO_FRAGMENT)
{
PACKET_LOG_DEBUG("ipv6 is fragmented");
handler->frag_layer = layer;
return layer->pld_ptr;
}
// TESTED
return parse_l4(handler, next_proto, layer->pld_ptr, layer->pld_len);
@@ -1132,6 +1138,11 @@ void packet_print(const struct packet *handler)
i, layer, layer_type_tostring(layer->type), layer->hdr_offset,
layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len);
}
for (uint16_t i = 0; i < handler->data_len; i++)
{
printf("0x%02x, ", (uint8_t)handler->data_ptr[i]);
}
printf("\n");
}
// return 0 : found

View File

@@ -12,7 +12,8 @@ extern "C"
#include <netinet/ip6.h>
#include "packet.h"
#include "ipv4_helpers.h"
#include "ipv4_utils.h"
#include "ipv6_utils.h"
struct metadata
{
@@ -71,7 +72,7 @@ static inline bool paket_is_fragment(const struct packet *pkt)
if (pkt->layers[i].type == LAYER_TYPE_IPV4)
{
struct ip *ip_hdr = (struct ip *)pkt->layers[i].hdr_ptr;
if (ipv4_hdr_has_flag_mf(ip_hdr) || ipv4_hdr_get_frag_offset(ip_hdr))
if (ipv4_hdr_get_mf_flag(ip_hdr) || ipv4_hdr_get_frag_offset(ip_hdr))
{
return true;
}
@@ -79,8 +80,8 @@ static inline bool paket_is_fragment(const struct packet *pkt)
if (pkt->layers[i].type == LAYER_TYPE_IPV6)
{
struct ip6_hdr *ip6_hdr = (struct ip6_hdr *)pkt->layers[i].hdr_ptr;
if (ip6_hdr->ip6_nxt == IPPROTO_FRAGMENT)
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)pkt->layers[i].hdr_ptr;
if (ipv6_hdr_get_next_header(ip6_hdr) == IPPROTO_FRAGMENT)
{
return true;
}
@@ -97,7 +98,7 @@ static inline struct packet *packet_dup(const struct packet *pkt)
return NULL;
}
struct packet *pkt_dup = (struct packet *)calloc(1, sizeof(struct packet));
struct packet *pkt_dup = (struct packet *)calloc(1, sizeof(struct packet) + pkt->data_len);
if (pkt_dup == NULL)
{
return NULL;
@@ -105,21 +106,23 @@ static inline struct packet *packet_dup(const struct packet *pkt)
memcpy(pkt_dup, pkt, sizeof(struct packet));
pkt_dup->user_data = NULL;
if (pkt->data_len)
pkt_dup->data_ptr = (const char *)pkt_dup + sizeof(struct packet);
if (pkt_dup->data_ptr == NULL)
{
pkt_dup->data_ptr = (const char *)calloc(1, pkt->data_len);
if (pkt_dup->data_ptr == NULL)
{
free(pkt_dup);
return NULL;
}
memcpy((char *)pkt_dup->data_ptr, pkt->data_ptr, pkt->data_len);
free(pkt_dup);
return NULL;
}
memcpy((char *)pkt_dup->data_ptr, pkt->data_ptr, pkt->data_len);
for (int8_t i = 0; i < pkt->layers_used; i++)
{
pkt_dup->layers[i].hdr_ptr = pkt_dup->data_ptr + pkt->layers[i].hdr_offset;
pkt_dup->layers[i].pld_ptr = pkt_dup->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len;
}
for (int8_t i = 0; i < pkt->layers_used; i++)
{
pkt_dup->layers[i].hdr_ptr = pkt_dup->data_ptr + pkt->layers[i].hdr_offset;
pkt_dup->layers[i].pld_ptr = pkt_dup->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len;
}
if (pkt->frag_layer)
{
pkt_dup->frag_layer = &pkt_dup->layers[pkt->frag_layer - pkt->layers];
}
packet_set0_metadata(pkt_dup, metadata_dup(packet_get0_metadata(pkt)));
@@ -133,66 +136,21 @@ static inline void packet_free(struct packet *pkt)
metadata_free((struct metadata *)packet_get0_metadata(pkt));
packet_set0_metadata(pkt, NULL);
if (pkt->data_ptr)
{
free((char *)pkt->data_ptr);
pkt->data_ptr = NULL;
}
free(pkt);
pkt = NULL;
}
}
static inline uint64_t packet_get_domain(const struct packet *pkt)
{
return pkt->domain;
}
static inline uint16_t packet_get_raw_len(const struct packet *pkt)
static inline uint16_t packet_get_len(const struct packet *pkt)
{
return pkt->data_len;
}
static inline const char *packet_get0_raw_data(const struct packet *pkt)
static inline const char *packet_get_data(const struct packet *pkt)
{
return pkt->data_ptr;
}
static inline uint8_t packet_get_layer_count(const struct packet *pkt)
{
return pkt->layers_used;
}
static inline const struct layer_record *packet_get_layer(const struct packet *pkt, uint8_t index)
{
return &pkt->layers[index];
}
static inline enum layer_type layer_get_type(const struct layer_record *layer)
{
return layer->type;
}
static inline const char *layer_get_hdr_ptr(const struct layer_record *layer)
{
return layer->hdr_ptr;
}
static inline const char *layer_get_pld_ptr(const struct layer_record *layer)
{
return layer->pld_ptr;
}
static inline uint16_t layer_get_hdr_len(const struct layer_record *layer)
{
return layer->hdr_len;
}
static inline uint16_t layer_get_pld_len(const struct layer_record *layer)
{
return layer->pld_len;
}
#ifdef __cpluscplus
}
#endif

View File

@@ -121,6 +121,11 @@ static inline uint16_t tcp_hdr_get_opt_len(const struct tcphdr *hdr)
static inline const char *tcp_hdr_get_opt_data(const struct tcphdr *hdr)
{
if (tcp_hdr_get_opt_len(hdr) == 0)
{
return NULL;
}
return ((const char *)hdr) + sizeof(struct tcphdr);
}

View File

@@ -52,7 +52,7 @@ TEST(IPV4_UTILS, GET1)
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) == data + 20);
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == NULL);
}
TEST(IPV4_UTILS, SET1)
@@ -143,7 +143,7 @@ TEST(IPV4_UTILS, GET2)
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) == data + 20);
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == NULL);
}
TEST(IPV4_UTILS, SET2)
@@ -236,7 +236,7 @@ TEST(IPV4_UTILS, GET3)
EXPECT_TRUE(ipv4_hdr_get_src_addr(hdr) == 0x7f000001);
EXPECT_TRUE(ipv4_hdr_get_dst_addr(hdr) == 0x7f000001);
EXPECT_TRUE(ipv4_hdr_get_opt_len(hdr) == 40);
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == data + 20);
EXPECT_TRUE(ipv4_hdr_get_opt_data(hdr) == (const char *)(data3 + 20));
}
TEST(IPV4_UTILS, SET3)
@@ -256,7 +256,7 @@ TEST(IPV4_UTILS, SET3)
ipv4_hdr_set_src_addr(hdr, 0x7f000001);
ipv4_hdr_set_dst_addr(hdr, 0x7f000001);
ipv4_hdr_set_opt_len(hdr, 40);
ipv4_hdr_set_opt_data(hdr, data3 + 20);
ipv4_hdr_set_opt_data(hdr, (const char *)(data3 + 20));
ipv4_hdr_set_flags(hdr, 2);
EXPECT_TRUE(memcmp(buff, data3, 60) == 0);

View File

@@ -93,7 +93,7 @@ TEST(TCP_UTILS, GET)
EXPECT_TRUE(tcp_hdr_get_checksum(hdr) == 0xfe30);
EXPECT_TRUE(tcp_hdr_get_urg_ptr(hdr) == 0);
EXPECT_TRUE(tcp_hdr_get_opt_len(hdr) == 20);
EXPECT_TRUE(tcp_hdr_get_opt_data(hdr) == data + 20);
EXPECT_TRUE(tcp_hdr_get_opt_data(hdr) == (const char *)(data + 20));
}
TEST(TCP_UTILS, SET1)
@@ -111,7 +111,7 @@ TEST(TCP_UTILS, SET1)
tcp_hdr_set_checksum(hdr, 0xfe30);
tcp_hdr_set_urg_ptr(hdr, 0);
tcp_hdr_set_opt_len(hdr, 20);
tcp_hdr_set_opt_data(hdr, data + 20);
tcp_hdr_set_opt_data(hdr, (const char *)(data + 20));
EXPECT_TRUE(memcmp(buff, data, 40) == 0);
}
@@ -136,7 +136,7 @@ TEST(TCP_UTILS, SET2)
tcp_hdr_set_checksum(hdr, 0xfe30);
tcp_hdr_set_urg_ptr(hdr, 0);
tcp_hdr_set_opt_len(hdr, 20);
tcp_hdr_set_opt_data(hdr, data + 20);
tcp_hdr_set_opt_data(hdr, (const char *)(data + 20));
EXPECT_TRUE(memcmp(buff, data, 40) == 0);
}