packet parser suppoort skip IPv6 extension headers
This commit is contained in:
@@ -7,6 +7,7 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/ip6.h>
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1033,6 +1033,25 @@ static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint1
|
|||||||
|
|
||||||
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len)
|
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* IP6 Extension Headers
|
||||||
|
*
|
||||||
|
* Internet Protocol, Version 6 (IPv6) : https://datatracker.ietf.org/doc/html/rfc2460
|
||||||
|
* IP Encapsulating Security Payload (ESP) : https://datatracker.ietf.org/doc/html/rfc2406
|
||||||
|
* IP Authentication Header : https://datatracker.ietf.org/doc/html/rfc4302
|
||||||
|
*
|
||||||
|
* skip next header
|
||||||
|
* #define IPPROTO_HOPOPTS 0 // IP6 hop-by-hop options
|
||||||
|
* #define IPPROTO_ROUTING 43 // IP6 routing header
|
||||||
|
* #define IPPROTO_AH 51 // IP6 Auth Header
|
||||||
|
* #define IPPROTO_DSTOPTS 60 // IP6 destination option
|
||||||
|
*
|
||||||
|
* not skip next header
|
||||||
|
* #define IPPROTO_FRAGMENT 44 // IP6 fragmentation header
|
||||||
|
* #define IPPROTO_ESP 50 // IP6 Encap Sec. Payload
|
||||||
|
* #define IPPROTO_NONE 59 // IP6 no next header
|
||||||
|
*/
|
||||||
|
|
||||||
if (unlikely(len < sizeof(struct ip6_hdr)))
|
if (unlikely(len < sizeof(struct ip6_hdr)))
|
||||||
{
|
{
|
||||||
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
||||||
@@ -1050,9 +1069,30 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
|
|||||||
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
||||||
return data;
|
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);
|
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, trim_len);
|
uint16_t hdr_len = sizeof(struct ip6_hdr);
|
||||||
|
uint16_t trim_len = len - pld_len - sizeof(struct ip6_hdr);
|
||||||
|
const char *next_hdr_ptr = data + hdr_len;
|
||||||
|
while (next_proto == IPPROTO_HOPOPTS || next_proto == IPPROTO_ROUTING || next_proto == IPPROTO_AH || next_proto == IPPROTO_DSTOPTS)
|
||||||
|
{
|
||||||
|
if (unlikely(pld_len < 2))
|
||||||
|
{
|
||||||
|
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr;
|
||||||
|
uint16_t skip_len = ext->ip6e_len * 8 + 8;
|
||||||
|
if (unlikely(skip_len > pld_len))
|
||||||
|
{
|
||||||
|
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_IPV6);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
hdr_len += skip_len;
|
||||||
|
pld_len -= skip_len;
|
||||||
|
next_hdr_ptr += skip_len;
|
||||||
|
next_proto = ext->ip6e_nxt;
|
||||||
|
}
|
||||||
|
SET_LAYER(pkt, layer, LAYER_TYPE_IPV6, hdr_len, data, len, trim_len);
|
||||||
|
|
||||||
// ipv6 fragment
|
// ipv6 fragment
|
||||||
if (next_proto == IPPROTO_FRAGMENT)
|
if (next_proto == IPPROTO_FRAGMENT)
|
||||||
@@ -1062,8 +1102,6 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
|
|||||||
// try continue parse
|
// try continue parse
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO parse ipv6 extension headers
|
|
||||||
|
|
||||||
// TESTED
|
// TESTED
|
||||||
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
|
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
|
||||||
}
|
}
|
||||||
@@ -1364,8 +1402,8 @@ void packet_print_str(const struct packet *pkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buffer[2048] = {0};
|
char buffer[2048] = {0};
|
||||||
printf("packet: %p, data_ptr: %p, data_len: %u, layers_used: %u, layers_size: %u\n",
|
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, pkt->data_ptr, pkt->data_len, pkt->trim_len,
|
||||||
pkt->layers_used, pkt->layers_size);
|
pkt->layers_used, pkt->layers_size);
|
||||||
for (uint8_t i = 0; i < pkt->layers_used; i++)
|
for (uint8_t i = 0; i < pkt->layers_used; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,9 +224,9 @@ static inline void calc_tcp_fingerprint(struct tcp_fingerprint *finger)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return packet length
|
// return packet length
|
||||||
int build_tcp_packet(const struct packet *first, uint16_t ip_id, uint8_t ip_ttl,
|
static int build_tcp_packet(const struct packet *first, uint16_t ip_id, uint8_t ip_ttl,
|
||||||
uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, uint16_t tcp_win,
|
uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, uint16_t tcp_win,
|
||||||
const char *tcp_pld, int pld_len, char *pkt_buff, int buff_size)
|
const char *tcp_pld, int pld_len, char *pkt_buff, int buff_size)
|
||||||
{
|
{
|
||||||
int trim = 0;
|
int trim = 0;
|
||||||
struct tcphdr *tcphdr;
|
struct tcphdr *tcphdr;
|
||||||
@@ -314,7 +314,7 @@ int build_tcp_packet(const struct packet *first, uint16_t ip_id, uint8_t ip_ttl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return packet length
|
// return packet length
|
||||||
int build_udp_packet(const struct packet *first, const char *udp_pld, int pld_len, char *pkt_buff, int buff_size)
|
static int build_udp_packet(const struct packet *first, const char *udp_pld, int pld_len, char *pkt_buff, int buff_size)
|
||||||
{
|
{
|
||||||
int trim = 0;
|
int trim = 0;
|
||||||
struct udphdr *udphdr;
|
struct udphdr *udphdr;
|
||||||
@@ -386,7 +386,7 @@ int build_udp_packet(const struct packet *first, const char *udp_pld, int pld_le
|
|||||||
return len - trim;
|
return len - trim;
|
||||||
}
|
}
|
||||||
|
|
||||||
int inject_tcp_packet(struct stellar *st, const struct session *sess, enum flow_direction inject_dir, uint8_t tcp_flags, const char *payload, uint16_t len)
|
static int inject_tcp_packet(struct stellar *st, const struct session *sess, enum flow_direction inject_dir, uint8_t tcp_flags, const char *payload, uint16_t len)
|
||||||
{
|
{
|
||||||
#define TCP_FLAGS_LOG_FORMAT "URG:%d, ACK:%d, PSH:%d, RST:%d, SYN:%d, FIN:%d"
|
#define TCP_FLAGS_LOG_FORMAT "URG:%d, ACK:%d, PSH:%d, RST:%d, SYN:%d, FIN:%d"
|
||||||
#define TCP_FLAGS_LOG_VALUE(flags) \
|
#define TCP_FLAGS_LOG_VALUE(flags) \
|
||||||
@@ -464,7 +464,7 @@ int inject_tcp_packet(struct stellar *st, const struct session *sess, enum flow_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int inject_udp_packet(struct stellar *st, const struct session *sess, enum flow_direction inject_dir, const char *payload, uint16_t len)
|
static int inject_udp_packet(struct stellar *st, const struct session *sess, enum flow_direction inject_dir, const char *payload, uint16_t len)
|
||||||
{
|
{
|
||||||
uint16_t thr_idx = stellar_get_current_thread_index();
|
uint16_t thr_idx = stellar_get_current_thread_index();
|
||||||
uint64_t time_ms = stellar_get_monotonic_time_msec();
|
uint64_t time_ms = stellar_get_monotonic_time_msec();
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef _INJECT_PRIV_H
|
|
||||||
#define _INJECT_PRIV_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "stellar/stellar.h"
|
|
||||||
|
|
||||||
// return packet length
|
|
||||||
int build_tcp_packet(const struct packet *first, uint16_t ip_id, uint8_t ip_ttl,
|
|
||||||
uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, uint16_t tcp_win,
|
|
||||||
const char *tcp_pld, int pld_len, char *pkt_buff, int buff_size);
|
|
||||||
int build_udp_packet(const struct packet *first, const char *udp_pld, int pld_len, char *pkt_buff, int buff_size);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# build packet_injector
|
# build packet_injector
|
||||||
add_executable(packet_injector packet_inject_main.cpp packet_inject_plugin.cpp)
|
add_executable(packet_injector packet_inject_main.cpp packet_inject_plugin.cpp)
|
||||||
target_link_libraries(packet_injector "-rdynamic")
|
target_link_libraries(packet_injector "-rdynamic")
|
||||||
target_link_libraries(packet_injector stellar_devel)
|
target_link_libraries(packet_injector stellar_core)
|
||||||
|
|
||||||
# build libpacket_inject_plugin.so
|
# build libpacket_inject_plugin.so
|
||||||
add_library(packet_inject_plugin SHARED packet_inject_plugin.cpp)
|
add_library(packet_inject_plugin SHARED packet_inject_plugin.cpp)
|
||||||
@@ -12,7 +12,7 @@ set_target_properties(packet_inject_plugin PROPERTIES LINK_FLAGS "-Wl,--version-
|
|||||||
function(packet_inject_add_case EXEC_NAME)
|
function(packet_inject_add_case EXEC_NAME)
|
||||||
add_executable(${EXEC_NAME} ${EXEC_NAME}.cpp packet_inject_main.cpp packet_inject_plugin.cpp packet_inject_test.cpp)
|
add_executable(${EXEC_NAME} ${EXEC_NAME}.cpp packet_inject_main.cpp packet_inject_plugin.cpp packet_inject_test.cpp)
|
||||||
target_link_libraries(${EXEC_NAME} "-rdynamic")
|
target_link_libraries(${EXEC_NAME} "-rdynamic")
|
||||||
target_link_libraries(${EXEC_NAME} stellar_devel gtest)
|
target_link_libraries(${EXEC_NAME} stellar_core gtest)
|
||||||
gtest_discover_tests(${EXEC_NAME})
|
gtest_discover_tests(${EXEC_NAME})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pcap/pcap.h>
|
#include <pcap/pcap.h>
|
||||||
|
#include "ipv6_utils.h"
|
||||||
#include "packet_priv.h"
|
#include "packet_priv.h"
|
||||||
|
|
||||||
struct options
|
struct options
|
||||||
@@ -11,6 +12,42 @@ struct options
|
|||||||
|
|
||||||
static uint64_t number = 0;
|
static uint64_t number = 0;
|
||||||
|
|
||||||
|
static int ipv6_proto_to_str(const struct packet_layer *ipv6_layer, char *buff, int size)
|
||||||
|
{
|
||||||
|
int used = snprintf(buff, size, "ipv6");
|
||||||
|
uint16_t skip_len = sizeof(struct ip6_hdr);
|
||||||
|
uint8_t next_hdr = ipv6_hdr_get_next_header((const struct ip6_hdr *)ipv6_layer->hdr_ptr);
|
||||||
|
while (skip_len < ipv6_layer->hdr_len)
|
||||||
|
{
|
||||||
|
if (next_hdr == IPPROTO_HOPOPTS)
|
||||||
|
{
|
||||||
|
used += snprintf(buff + used, size - used, ":ipv6.hopopt");
|
||||||
|
}
|
||||||
|
else if (next_hdr == IPPROTO_ROUTING)
|
||||||
|
{
|
||||||
|
used += snprintf(buff + used, size - used, ":ipv6.routing");
|
||||||
|
}
|
||||||
|
else if (next_hdr == IPPROTO_AH)
|
||||||
|
{
|
||||||
|
used += snprintf(buff + used, size - used, ":ipv6.ah");
|
||||||
|
}
|
||||||
|
else if (next_hdr == IPPROTO_DSTOPTS)
|
||||||
|
{
|
||||||
|
used += snprintf(buff + used, size - used, ":ipv6.dstopts");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ip6_ext *ext = (struct ip6_ext *)ipv6_layer->hdr_ptr + skip_len;
|
||||||
|
skip_len += ext->ip6e_len * 8 + 8;
|
||||||
|
next_hdr = ext->ip6e_nxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
static int packet_proto_to_str(const struct packet *pkt, char *buff, int size)
|
static int packet_proto_to_str(const struct packet *pkt, char *buff, int size)
|
||||||
{
|
{
|
||||||
int used = 0;
|
int used = 0;
|
||||||
@@ -45,7 +82,7 @@ static int packet_proto_to_str(const struct packet *pkt, char *buff, int size)
|
|||||||
used += snprintf(buff + used, size - used, "ip");
|
used += snprintf(buff + used, size - used, "ip");
|
||||||
break;
|
break;
|
||||||
case LAYER_TYPE_IPV6:
|
case LAYER_TYPE_IPV6:
|
||||||
used += snprintf(buff + used, size - used, "ipv6");
|
used += ipv6_proto_to_str(layer, buff + used, size - used);
|
||||||
break;
|
break;
|
||||||
case LAYER_TYPE_GRE:
|
case LAYER_TYPE_GRE:
|
||||||
used += snprintf(buff + used, size - used, "gre");
|
used += snprintf(buff + used, size - used, "gre");
|
||||||
|
|||||||
Reference in New Issue
Block a user