support IPv4 & IPv6 frag reassemble
This commit is contained in:
41
src/packet/checksum.h
Normal file
41
src/packet/checksum.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user