When the packet length is greater than the IP expected length, the padding data at the end of the frame will be trimmed.

This commit is contained in:
luwenpeng
2024-05-24 19:10:33 +08:00
parent 94fc1af6bd
commit 54385ed08b
6 changed files with 264 additions and 45 deletions

View File

@@ -437,14 +437,15 @@ static inline struct packet_layer *get_free_layer(struct packet *pkt)
return &pkt->layers[pkt->layers_used];
}
#define SET_LAYER(_pkt, _layer, _type, _hdr_len, _data, _len) \
#define SET_LAYER(_pkt, _layer, _type, _hdr_len, _data, _len, _trim) \
{ \
(_layer)->type = (_type); \
(_layer)->hdr_offset = (_pkt)->data_len - (_len); \
(_layer)->hdr_offset = (_pkt)->data_len - (_pkt)->trim_len - (_len); \
(_layer)->hdr_ptr = (_data); \
(_layer)->hdr_len = (_hdr_len); \
(_layer)->pld_ptr = (_data) + (_hdr_len); \
(_layer)->pld_len = (_len) - (_hdr_len); \
(_layer)->pld_len = (_len) - (_hdr_len) - (_trim); \
(_pkt)->trim_len += (_trim); \
(_pkt)->layers_used++; \
PACKET_LOG_DEBUG("layer[%d/%d]: %s, hdr_offset: %d, hdr_ptr: %p, hdr_len: %d, pld_ptr: %p, pld_len: %d", \
(_pkt)->layers_used - 1, (_pkt)->layers_size, layer_type_to_str((_type)), \
@@ -750,7 +751,7 @@ static inline const char *parse_ether(struct packet *pkt, const char *data, uint
return data;
}
uint16_t next_proto = ntohs(((struct ethhdr *)data)->h_proto);
SET_LAYER(pkt, layer, LAYER_TYPE_ETHER, sizeof(struct ethhdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_ETHER, sizeof(struct ethhdr), data, len, 0);
// TESTED
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
@@ -770,7 +771,7 @@ static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16
return data;
}
uint16_t next_proto = ntohs(*((uint16_t *)data + 1));
SET_LAYER(pkt, layer, LAYER_TYPE_PPP, 4, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_PPP, 4, data, len, 0);
switch (next_proto)
{
@@ -801,7 +802,7 @@ static inline const char *parse_l2tpv2(struct packet *pkt, const char *data, uin
{
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_L2TP, hdr_len, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_L2TP, hdr_len, data, len, 0);
uint16_t control = ntohs(*((uint16_t *)data));
if (CONTROL_BIT(control))
@@ -846,7 +847,7 @@ static inline const char *parse_vlan(struct packet *pkt, const char *data, uint1
return data;
}
uint16_t next_proto = ntohs(((struct vlan_hdr *)data)->protocol);
SET_LAYER(pkt, layer, LAYER_TYPE_VLAN, sizeof(struct vlan_hdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_VLAN, sizeof(struct vlan_hdr), data, len, 0);
// TESTED
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
@@ -869,7 +870,7 @@ static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data,
return data;
}
uint16_t next_proto = *((uint16_t *)data + 3);
SET_LAYER(pkt, layer, LAYER_TYPE_PPPOE, 8, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_PPPOE, 8, data, len, 0);
switch (next_proto)
{
@@ -966,7 +967,7 @@ static inline const char *parse_mpls(struct packet *pkt, const char *data, uint1
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_MPLS);
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_MPLS, hdr_len, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_MPLS, hdr_len, data, len, 0);
switch (next_proto)
{
@@ -1001,14 +1002,21 @@ static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint1
return data;
}
struct ip *hdr = (struct ip *)data;
uint8_t next_proto = ipv4_hdr_get_proto(hdr);
uint16_t hdr_len = ipv4_hdr_get_hdr_len(hdr);
if (unlikely(hdr_len > len))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV4);
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_IPV4, hdr_len, data, len);
uint16_t total_len = ipv4_hdr_get_total_len(hdr);
if (unlikely(total_len > len))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV4);
return data;
}
uint16_t trim_len = len - total_len;
SET_LAYER(pkt, layer, LAYER_TYPE_IPV4, hdr_len, data, len, trim_len);
// ip fragmented
if (ipv4_hdr_get_mf_flag(hdr) || ipv4_hdr_get_frag_offset(hdr))
@@ -1019,6 +1027,7 @@ static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint1
}
// TESTED
uint8_t next_proto = ipv4_hdr_get_proto(hdr);
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
}
@@ -1035,8 +1044,15 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
{
return data;
}
uint16_t pld_len = ipv6_hdr_get_payload_len((const struct ip6_hdr *)data);
if (unlikely(pld_len + sizeof(struct ip6_hdr) > len))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
return data;
}
uint16_t trim_len = len - pld_len - sizeof(struct ip6_hdr);
uint8_t next_proto = ipv6_hdr_get_next_header((const struct ip6_hdr *)data);
SET_LAYER(pkt, layer, LAYER_TYPE_IPV6, sizeof(struct ip6_hdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_IPV6, sizeof(struct ip6_hdr), data, len, trim_len);
// ipv6 fragment
if (next_proto == IPPROTO_FRAGMENT)
@@ -1072,7 +1088,7 @@ static inline const char *parse_gre(struct packet *pkt, const char *data, uint16
return data;
}
uint16_t next_proto = ntohs(*((uint16_t *)data + 1));
SET_LAYER(pkt, layer, LAYER_TYPE_GRE, hdr_len, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_GRE, hdr_len, data, len, 0);
switch (next_proto)
{
@@ -1103,7 +1119,7 @@ static inline const char *parse_udp(struct packet *pkt, const char *data, uint16
return data;
}
struct udphdr *hdr = (struct udphdr *)data;
SET_LAYER(pkt, layer, LAYER_TYPE_UDP, sizeof(struct udphdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_UDP, sizeof(struct udphdr), data, len, 0);
if (udp_hdr_get_dst_port(hdr) == 4789)
{
@@ -1162,7 +1178,7 @@ static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_TCP);
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_TCP, hdr_len, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_TCP, hdr_len, data, len, 0);
return layer->pld_ptr;
}
@@ -1180,7 +1196,7 @@ static inline const char *parse_icmp(struct packet *pkt, const char *data, uint1
{
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_ICMP, sizeof(struct icmphdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_ICMP, sizeof(struct icmphdr), data, len, 0);
return layer->pld_ptr;
}
@@ -1198,7 +1214,7 @@ static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint
{
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_ICMP6, sizeof(struct icmp6_hdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_ICMP6, sizeof(struct icmp6_hdr), data, len, 0);
return layer->pld_ptr;
}
@@ -1224,7 +1240,7 @@ static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint
{
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_VXLAN, sizeof(struct vxlan_hdr), data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_VXLAN, sizeof(struct vxlan_hdr), data, len, 0);
// TESTED
return parse_ether(pkt, layer->pld_ptr, layer->pld_len);
@@ -1245,7 +1261,7 @@ static inline const char *parse_gtpv1_u(struct packet *pkt, const char *data, ui
return data;
}
uint8_t next_proto = (((const uint8_t *)(data + hdr_len))[0]) >> 4;
SET_LAYER(pkt, layer, LAYER_TYPE_GTPV1_U, hdr_len, data, len);
SET_LAYER(pkt, layer, LAYER_TYPE_GTPV1_U, hdr_len, data, len, 0);
switch (next_proto)
{
@@ -1334,12 +1350,13 @@ const char *packet_parse(struct packet *pkt, const char *data, uint16_t len)
pkt->layers_size = PACKET_MAX_LAYERS;
pkt->data_ptr = data;
pkt->data_len = len;
pkt->trim_len = 0;
// TESTED
return parse_ether(pkt, data, len);
}
void packet_print(const struct packet *pkt)
void packet_print_str(const struct packet *pkt)
{
if (pkt == NULL)
{
@@ -1363,6 +1380,38 @@ void packet_print(const struct packet *pkt)
printf("\n");
}
void packet_print_table(const struct packet *pkt)
{
if (pkt == NULL)
{
return;
}
printf("packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
pkt->layers_used, pkt->layers_size);
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
printf("| %-10s | %-10s | %-10s | %-10s | %-10s | %-10s | %-10s |\n",
"index", "type", "hdr ptr", "hdr offset", "hdr len", "pld ptr", "pld len");
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
for (uint8_t i = 0; i < pkt->layers_used; i++)
{
const struct packet_layer *layer = &pkt->layers[i];
printf("| %-10u | %-10s | %-10p | %-10u | %-10u | %-10p | %-10u |\n",
i, layer_type_to_str(layer->type),
layer->hdr_ptr, layer->hdr_offset, layer->hdr_len,
layer->pld_ptr, layer->pld_len);
printf("+------------+------------+------------+------------+------------+------------+------------+\n");
}
printf("data: ");
for (uint16_t i = 0; i < pkt->data_len; i++)
{
printf("0x%02x, ", (uint8_t)pkt->data_ptr[i]);
}
printf("\n");
}
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)