This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/infra/packet_manager/packet_utils.c
2024-11-27 18:23:59 +08:00

1078 lines
29 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <assert.h>
#include <sys/queue.h>
#include "tuple.h"
#include "uthash.h"
#include "log_internal.h"
#include "packet_helper.h"
#include "packet_internal.h"
#include "stellar/exdata.h"
#define PACKET_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet", format, ##__VA_ARGS__)
/******************************************************************************
* metadata utils
******************************************************************************/
void packet_set_route_ctx(struct packet *pkt, const struct route_ctx *ctx)
{
pkt->meta.route_ctx = *ctx;
}
const struct route_ctx *packet_get_route_ctx(const struct packet *pkt)
{
return &pkt->meta.route_ctx;
}
void packet_set_sids(struct packet *pkt, const struct sids *sids)
{
pkt->meta.sids = *sids;
}
const struct sids *packet_get_sids(const struct packet *pkt)
{
return &pkt->meta.sids;
}
void packet_prepend_sids(struct packet *pkt, const struct sids *sids)
{
if (pkt->meta.sids.used + sids->used > MAX_SIDS)
{
PACKET_LOG_ERROR("sids overflow");
return;
}
else
{
for (int i = pkt->meta.sids.used - 1; i >= 0; i--)
{
pkt->meta.sids.sid[i + sids->used] = pkt->meta.sids.sid[i];
}
for (int i = 0; i < sids->used; i++)
{
pkt->meta.sids.sid[i] = sids->sid[i];
}
pkt->meta.sids.used += sids->used;
}
}
void packet_set_session_id(struct packet *pkt, uint64_t id)
{
pkt->meta.session_id = id;
}
uint64_t packet_get_session_id(const struct packet *pkt)
{
return pkt->meta.session_id;
}
void packet_set_domain(struct packet *pkt, uint64_t domain)
{
pkt->meta.domain = domain;
}
uint64_t packet_get_domain(const struct packet *pkt)
{
return pkt->meta.domain;
}
void packet_set_link_id(struct packet *pkt, uint16_t id)
{
pkt->meta.link_id = id;
}
uint16_t packet_get_link_id(const struct packet *pkt)
{
return pkt->meta.link_id;
}
void packet_set_direction(struct packet *pkt, enum packet_direction dir)
{
pkt->meta.direction = dir;
}
enum packet_direction packet_get_direction(const struct packet *pkt)
{
return pkt->meta.direction;
}
void packet_set_timeval(struct packet *pkt, const struct timeval *tv)
{
pkt->meta.tv = *tv;
}
const struct timeval *packet_get_timeval(const struct packet *pkt)
{
return &pkt->meta.tv;
}
/******************************************************************************
* tuple uitls
******************************************************************************/
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
{
memset(tuple, 0, sizeof(struct tuple2));
const struct layer_internal *layer = NULL;
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
{
layer = &pkt->layers[i];
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
return 0;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
return 0;
}
}
return -1;
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
{
memset(tuple, 0, sizeof(struct tuple2));
const struct layer_internal *layer = NULL;
for (int8_t i = 0; i < pkt->layers_used; i++)
{
layer = &pkt->layers[i];
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
return 0;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
return 0;
}
}
return -1;
}
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple)
{
memset(tuple, 0, sizeof(struct tuple4));
const struct layer_internal *layer_l3 = NULL;
const struct layer_internal *layer_l4 = NULL;
const struct layer_internal *layer = NULL;
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
{
layer = &pkt->layers[i];
// first get L4 layer
if (layer->proto == LAYER_PROTO_UDP)
{
const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr;
tuple->src_port = udp_hdr->uh_sport;
tuple->dst_port = udp_hdr->uh_dport;
layer_l4 = layer;
continue;
}
if (layer->proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
tuple->src_port = tcp_hdr->th_sport;
tuple->dst_port = tcp_hdr->th_dport;
layer_l4 = layer;
continue;
}
// second get L3 layer
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
layer_l3 = layer;
break;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
layer_l3 = layer;
break;
}
}
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
{
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple)
{
memset(tuple, 0, sizeof(struct tuple4));
const struct layer_internal *layer_l3 = NULL;
const struct layer_internal *layer_l4 = NULL;
const struct layer_internal *layer = NULL;
for (int8_t i = 0; i < pkt->layers_used; i++)
{
layer = &pkt->layers[i];
// first get L3 layer
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
layer_l3 = layer;
continue;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
layer_l3 = layer;
continue;
}
// second get L4 layer
if (layer->proto == LAYER_PROTO_UDP)
{
const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr;
tuple->src_port = udp_hdr->uh_sport;
tuple->dst_port = udp_hdr->uh_dport;
layer_l4 = layer;
break;
}
if (layer->proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
tuple->src_port = tcp_hdr->th_sport;
tuple->dst_port = tcp_hdr->th_dport;
layer_l4 = layer;
break;
}
}
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
{
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple)
{
memset(tuple, 0, sizeof(struct tuple6));
const struct layer_internal *layer_l3 = NULL;
const struct layer_internal *layer_l4 = NULL;
const struct layer_internal *layer = NULL;
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
{
layer = &pkt->layers[i];
// first get L4 layer
if (layer->proto == LAYER_PROTO_UDP)
{
const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr;
tuple->ip_proto = IPPROTO_UDP;
tuple->src_port = udp_hdr->uh_sport;
tuple->dst_port = udp_hdr->uh_dport;
layer_l4 = layer;
continue;
}
if (layer->proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
tuple->ip_proto = IPPROTO_TCP;
tuple->src_port = tcp_hdr->th_sport;
tuple->dst_port = tcp_hdr->th_dport;
layer_l4 = layer;
continue;
}
// second get L3 layer
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
layer_l3 = layer;
break;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
layer_l3 = layer;
break;
}
}
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
{
tuple->domain = packet_get_domain(pkt);
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple)
{
memset(tuple, 0, sizeof(struct tuple6));
const struct layer_internal *layer_l3 = NULL;
const struct layer_internal *layer_l4 = NULL;
const struct layer_internal *layer = NULL;
for (int8_t i = 0; i < pkt->layers_used; i++)
{
layer = &pkt->layers[i];
// first get L3 layer
if (layer->proto == LAYER_PROTO_IPV4)
{
const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr;
tuple->addr_family = AF_INET;
tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr);
tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr);
layer_l3 = layer;
continue;
}
if (layer->proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
tuple->addr_family = AF_INET6;
tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr);
tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr);
layer_l3 = layer;
continue;
}
// second get L4 layer
if (layer->proto == LAYER_PROTO_UDP)
{
const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr;
tuple->ip_proto = IPPROTO_UDP;
tuple->src_port = udp_hdr->uh_sport;
tuple->dst_port = udp_hdr->uh_dport;
layer_l4 = layer;
break;
}
if (layer->proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
tuple->ip_proto = IPPROTO_TCP;
tuple->src_port = tcp_hdr->th_sport;
tuple->dst_port = tcp_hdr->th_dport;
layer_l4 = layer;
break;
}
}
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
{
tuple->domain = packet_get_domain(pkt);
return 0;
}
else
{
return -1;
}
}
/******************************************************************************
* layer uitls
******************************************************************************/
int packet_get_layer_count(const struct packet *pkt)
{
return pkt->layers_used;
}
const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx)
{
const struct layer_internal *layer = packet_get_layer(pkt, idx);
if (layer == NULL)
{
return NULL;
}
else
{
return (const struct layer *)layer;
}
}
const struct layer_internal *packet_get_layer(const struct packet *pkt, int idx)
{
if (idx < 0 || idx >= pkt->layers_used)
{
return NULL;
}
return &pkt->layers[idx];
}
const struct layer_internal *packet_get_innermost_layer(const struct packet *pkt, enum layer_proto proto)
{
const struct layer_internal *layer = NULL;
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
{
layer = &pkt->layers[i];
if (layer->proto == proto)
{
return layer;
}
}
return NULL;
}
const struct layer_internal *packet_get_outermost_layer(const struct packet *pkt, enum layer_proto proto)
{
const struct layer_internal *layer = NULL;
for (int8_t i = 0; i < pkt->layers_used; i++)
{
layer = &pkt->layers[i];
if (layer->proto == proto)
{
return layer;
}
}
return NULL;
}
/******************************************************************************
* tunnel uitls
******************************************************************************/
struct tunnel_detector
{
enum tunnel_type type;
int contain_layers;
int (*identify_func)(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2);
};
static int is_ipv4_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused)))
{
if (curr && curr->proto == LAYER_PROTO_IPV4 &&
next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6))
{
return 1;
}
return 0;
}
static int is_ipv6_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused)))
{
if (curr && curr->proto == LAYER_PROTO_IPV6 &&
next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6))
{
return 1;
}
return 0;
}
static int is_gre_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2 __attribute__((unused)))
{
if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) &&
next1 && next1->proto == LAYER_PROTO_GRE)
{
return 1;
}
return 0;
}
static int is_gtp_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2)
{
if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) &&
next1 && next1->proto == LAYER_PROTO_UDP &&
next2 && next2->proto == LAYER_PROTO_GTP_U)
{
return 1;
}
return 0;
}
static int is_vxlan_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2)
{
if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) &&
next1 && next1->proto == LAYER_PROTO_UDP &&
next2 && next2->proto == LAYER_PROTO_VXLAN)
{
return 1;
}
return 0;
}
static int is_l2tp_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2)
{
if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) &&
next1 && next1->proto == LAYER_PROTO_UDP &&
next2 && next2->proto == LAYER_PROTO_L2TP)
{
return 1;
}
return 0;
}
static int is_teredo_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2)
{
if (curr && curr->proto == LAYER_PROTO_IPV4 &&
next1 && next1->proto == LAYER_PROTO_UDP &&
next2 && next2->proto == LAYER_PROTO_IPV6)
{
return 1;
}
return 0;
}
static struct tunnel_detector detectors[] = {
{TUNNEL_IPV4, 1, is_ipv4_tunnel},
{TUNNEL_IPV6, 1, is_ipv6_tunnel},
{TUNNEL_GRE, 2, is_gre_tunnel},
{TUNNEL_GTP, 3, is_gtp_tunnel},
{TUNNEL_VXLAN, 3, is_vxlan_tunnel},
{TUNNEL_L2TP, 3, is_l2tp_tunnel},
{TUNNEL_TEREDO, 2, is_teredo_tunnel},
};
// return index of detectors
static int detect_tunnel(const struct layer_internal *curr, const struct layer_internal *next1, const struct layer_internal *next2)
{
for (int i = 0; i < (int)(sizeof(detectors) / sizeof(detectors[0])); i++)
{
if (detectors[i].identify_func(curr, next1, next2))
{
return i;
}
}
return -1;
}
int packet_get_tunnel_count(const struct packet *pkt)
{
int count = 0;
int used = packet_get_layer_count(pkt);
const struct layer_internal *curr = NULL;
const struct layer_internal *next1 = NULL;
const struct layer_internal *next2 = NULL;
for (int i = 0; i < used; i++)
{
curr = packet_get_layer(pkt, i);
next1 = packet_get_layer(pkt, i + 1);
next2 = packet_get_layer(pkt, i + 2);
if (detect_tunnel(curr, next1, next2) >= 0)
{
count++;
}
}
return count;
}
// return 0: success 
// return -1: failed
int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out)
{
int ret = -1;
int count = 0;
int used = packet_get_layer_count(pkt);
const struct layer_internal *curr = NULL;
const struct layer_internal *next1 = NULL;
const struct layer_internal *next2 = NULL;
memset(out, 0, sizeof(struct tunnel));
for (int i = 0; i < used; i++)
{
curr = packet_get_layer(pkt, i);
next1 = packet_get_layer(pkt, i + 1);
next2 = packet_get_layer(pkt, i + 2);
ret = detect_tunnel(curr, next1, next2);
if (ret >= 0 && count++ == idx)
{
struct tunnel_detector *hit = &detectors[ret];
out->type = hit->type;
out->layer_count = hit->contain_layers;
if (out->layer_count >= 1)
out->layers[0] = (const struct layer *)curr;
if (out->layer_count >= 2)
out->layers[1] = (const struct layer *)next1;
if (out->layer_count >= 3)
out->layers[2] = (const struct layer *)next2;
return 0;
}
}
return -1;
}
/******************************************************************************
* load balance uitls
******************************************************************************/
uint64_t packet_ldbc_hash(const struct packet *pkt, enum packet_load_balance_method method, enum packet_direction direction)
{
uint64_t temp = 0;
uint64_t hash_value = 1;
int inner_addr_len = 0;
int outer_addr_len = 0;
const char *inner_src_addr = NULL;
const char *inner_dst_addr = NULL;
const char *outer_src_addr = NULL;
const char *outer_dst_addr = NULL;
struct tuple2 inner_addr;
struct tuple2 outer_addr;
if (pkt == NULL)
{
return hash_value;
}
if (packet_get_innermost_tuple2(pkt, &inner_addr) == -1)
{
return hash_value;
}
if (packet_get_outermost_tuple2(pkt, &outer_addr) == -1)
{
return hash_value;
}
if (inner_addr.addr_family == AF_INET)
{
inner_src_addr = (const char *)&inner_addr.src_addr.v4;
inner_dst_addr = (const char *)&inner_addr.dst_addr.v4;
inner_addr_len = sizeof(struct in_addr);
}
else
{
inner_src_addr = (const char *)&inner_addr.src_addr.v6;
inner_dst_addr = (const char *)&inner_addr.dst_addr.v6;
inner_addr_len = sizeof(struct in6_addr);
}
if (outer_addr.addr_family == AF_INET)
{
outer_src_addr = (const char *)&outer_addr.src_addr.v4;
outer_dst_addr = (const char *)&outer_addr.dst_addr.v4;
outer_addr_len = sizeof(struct in_addr);
}
else
{
outer_src_addr = (const char *)&outer_addr.src_addr.v6;
outer_dst_addr = (const char *)&outer_addr.dst_addr.v6;
outer_addr_len = sizeof(struct in6_addr);
}
switch (method)
{
case PKT_LDBC_METH_OUTERMOST_INT_IP:
if (direction == PACKET_DIRECTION_INCOMING)
{
// direction 1: E2I
HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
}
break;
case PKT_LDBC_METH_OUTERMOST_EXT_IP:
if (direction == PACKET_DIRECTION_INCOMING)
{
// direction 1: E2I
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value);
}
break;
case PKT_LDBC_METH_OUTERMOST_INT_EXT_IP:
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
HASH_VALUE(outer_dst_addr, outer_addr_len, temp);
hash_value = hash_value ^ temp;
break;
case PKT_LDBC_METH_INNERMOST_INT_IP:
if (direction == PACKET_DIRECTION_INCOMING)
{
// direction 1: E2I
HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(inner_src_addr, inner_addr_len, hash_value);
}
break;
case PKT_LDBC_METH_INNERMOST_EXT_IP:
if (direction == PACKET_DIRECTION_INCOMING)
{
// direction 1: E2I
HASH_VALUE(inner_src_addr, inner_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value);
}
break;
default:
return hash_value;
}
return hash_value;
}
/******************************************************************************
* other uitls
******************************************************************************/
struct packet *packet_new(uint16_t pkt_len)
{
struct packet *pkt = (struct packet *)calloc(1, sizeof(struct packet) + pkt_len);
if (pkt == NULL)
{
return NULL;
}
pkt->data_len = pkt_len;
pkt->data_ptr = (const char *)pkt + sizeof(struct packet);
pkt->need_free = 1;
return pkt;
}
struct packet *packet_dup(const struct packet *pkt)
{
if (pkt == NULL)
{
return NULL;
}
struct packet *dup_pkt = packet_new(pkt->data_len);
if (dup_pkt == NULL)
{
return NULL;
}
dup_pkt->layers_used = pkt->layers_used;
dup_pkt->layers_size = pkt->layers_size;
memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len);
dup_pkt->data_len = pkt->data_len;
packet_set_action(dup_pkt, PACKET_ACTION_DROP);
for (int8_t i = 0; i < pkt->layers_used; i++)
{
dup_pkt->layers[i].proto = pkt->layers[i].proto;
dup_pkt->layers[i].hdr_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset;
dup_pkt->layers[i].pld_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len;
dup_pkt->layers[i].hdr_offset = pkt->layers[i].hdr_offset;
dup_pkt->layers[i].hdr_len = pkt->layers[i].hdr_len;
dup_pkt->layers[i].pld_len = pkt->layers[i].pld_len;
}
// update frag_layer
if (pkt->frag_layer)
{
dup_pkt->frag_layer = &dup_pkt->layers[pkt->frag_layer - pkt->layers];
}
memcpy(&dup_pkt->meta, &pkt->meta, sizeof(struct metadata));
struct packet_origin origin = {
.type = ORIGIN_TYPE_USER,
.ctx = NULL,
.cb = NULL,
.args = NULL,
.thr_idx = -1,
};
packet_set_origin(dup_pkt, &origin);
return dup_pkt;
}
void packet_free(struct packet *pkt)
{
if (pkt)
{
if (packet_is_claim(pkt))
{
PACKET_LOG_ERROR("packet has been claimed and cannot be released, please check the module arrangement order");
assert(0);
return;
}
if (pkt->origin.cb)
{
pkt->origin.cb(pkt, pkt->origin.args);
}
if (pkt->need_free)
{
free((void *)pkt);
}
}
}
int packet_is_fragment(const struct packet *pkt)
{
return (pkt->frag_layer) ? 1 : 0;
}
int packet_is_defraged(const struct packet *pkt)
{
return pkt->is_defraged;
}
void packet_set_defraged(struct packet *pkt)
{
pkt->is_defraged = 1;
TAILQ_INIT(&pkt->frag_list);
}
void packet_push_frag(struct packet *pkt, struct packet *frag)
{
if (!packet_is_defraged(pkt))
{
assert(0);
return;
}
TAILQ_INSERT_TAIL(&pkt->frag_list, frag, frag_tqe);
}
struct packet *packet_pop_frag(struct packet *pkt)
{
if (!packet_is_defraged(pkt))
{
assert(0);
return NULL;
}
struct packet *frag = TAILQ_FIRST(&pkt->frag_list);
if (frag)
{
TAILQ_REMOVE(&pkt->frag_list, frag, frag_tqe);
}
return frag;
}
const char *packet_get_raw_data(const struct packet *pkt)
{
return pkt->data_ptr;
}
uint16_t packet_get_raw_len(const struct packet *pkt)
{
return pkt->data_len;
}
const char *packet_get_payload_data(const struct packet *pkt)
{
if (pkt == NULL || pkt->layers_used == 0)
{
return NULL;
}
if (pkt->layers[pkt->layers_used - 1].pld_len)
{
return pkt->layers[pkt->layers_used - 1].pld_ptr;
}
else
{
return NULL;
}
}
uint16_t packet_get_payload_len(const struct packet *pkt)
{
if (pkt == NULL || pkt->layers_used == 0)
{
return 0;
}
return pkt->layers[pkt->layers_used - 1].pld_len;
}
void packet_set_exdata(struct packet *pkt, int idx, void *ex_ptr)
{
struct exdata_runtime *exdata_rt = (struct exdata_runtime *)pkt->user_data;
assert(exdata_rt);
exdata_set(exdata_rt, idx, ex_ptr);
}
void *packet_get_exdata(const struct packet *pkt, int idx)
{
struct exdata_runtime *exdata_rt = (struct exdata_runtime *)pkt->user_data;
assert(exdata_rt);
return exdata_get(exdata_rt, idx);
}
void packet_tag_clean(struct packet *pkt)
{
pkt->tag_key_bits = 0;
pkt->tag_val_bits = 0;
}
void packet_tag_set(struct packet *pkt, uint64_t key_bits, uint64_t val_bits)
{
pkt->tag_key_bits |= key_bits;
pkt->tag_val_bits |= val_bits;
}
void packet_tag_get(const struct packet *pkt, uint64_t *key_bits, uint64_t *val_bits)
{
if (key_bits)
{
*key_bits = pkt->tag_key_bits;
}
if (val_bits)
{
*val_bits = pkt->tag_val_bits;
}
}
void packet_set_user_data(struct packet *pkt, void *data)
{
pkt->user_data = data;
}
void *packet_get_user_data(struct packet *pkt)
{
return pkt->user_data;
}
void packet_set_origin(struct packet *pkt, struct packet_origin *origin)
{
pkt->origin = *origin;
}
struct packet_origin *packet_get_origin(struct packet *pkt)
{
return &pkt->origin;
}
void packet_set_claim(struct packet *pkt, bool claim)
{
pkt->is_claim = claim;
}
bool packet_is_claim(const struct packet *pkt)
{
return pkt->is_claim;
}
void packet_set_type(struct packet *pkt, enum packet_type type)
{
pkt->type = type;
}
enum packet_type packet_get_type(const struct packet *pkt)
{
return pkt->type;
}
void packet_set_stage(struct packet *pkt, enum packet_stage stage)
{
pkt->stage = stage;
}
enum packet_stage packet_get_stage(const struct packet *pkt)
{
return pkt->stage;
}
void packet_set_action(struct packet *pkt, enum packet_action action)
{
pkt->action = action;
}
enum packet_action packet_get_action(const struct packet *pkt)
{
return pkt->action;
}
int packet_get_ip_proto(const struct packet *pkt)
{
return pkt->ip_proto;
}
const char *packet_stage_to_str(enum packet_stage stage)
{
switch (stage)
{
case PACKET_STAGE_PREROUTING:
return "PACKET_STAGE_PREROUTING";
case PACKET_STAGE_INPUT:
return "PACKET_STAGE_INPUT";
case PACKET_STAGE_FORWARD:
return "PACKET_STAGE_FORWARD";
case PACKET_STAGE_OUTPUT:
return "PACKET_STAGE_OUTPUT";
case PACKET_STAGE_POSTROUTING:
return "PACKET_STAGE_POSTROUTING";
default:
return "PACKET_STAGE_UNKNOWN";
}
}