diff --git a/src/packet/ipv6_utils.h b/src/packet/ipv6_utils.h index 1811314..438f45a 100644 --- a/src/packet/ipv6_utils.h +++ b/src/packet/ipv6_utils.h @@ -7,6 +7,7 @@ extern "C" #endif #include +#include #include #include diff --git a/src/packet/packet.cpp b/src/packet/packet.cpp index 261ae4a..ccadc9b 100644 --- a/src/packet/packet.cpp +++ b/src/packet/packet.cpp @@ -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) { + /* + * 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))) { 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); 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, 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 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 } - // TODO parse ipv6 extension headers - // TESTED 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}; - printf("packet: %p, data_ptr: %p, data_len: %u, layers_used: %u, layers_size: %u\n", - pkt, pkt->data_ptr, pkt->data_len, + 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); for (uint8_t i = 0; i < pkt->layers_used; i++) { diff --git a/src/stellar/inject.cpp b/src/stellar/inject.cpp index 9fed296..a3828c5 100644 --- a/src/stellar/inject.cpp +++ b/src/stellar/inject.cpp @@ -224,9 +224,9 @@ static inline void calc_tcp_fingerprint(struct tcp_fingerprint *finger) } // 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) +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, + const char *tcp_pld, int pld_len, char *pkt_buff, int buff_size) { int trim = 0; 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 -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; 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; } -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_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(); uint64_t time_ms = stellar_get_monotonic_time_msec(); diff --git a/src/stellar/inject_priv.h b/src/stellar/inject_priv.h deleted file mode 100644 index 80d3d98..0000000 --- a/src/stellar/inject_priv.h +++ /dev/null @@ -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 diff --git a/test/packet_inject/CMakeLists.txt b/test/packet_inject/CMakeLists.txt index 63af63e..d38d5fd 100644 --- a/test/packet_inject/CMakeLists.txt +++ b/test/packet_inject/CMakeLists.txt @@ -1,7 +1,7 @@ # build packet_injector add_executable(packet_injector packet_inject_main.cpp packet_inject_plugin.cpp) 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 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) 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} stellar_devel gtest) + target_link_libraries(${EXEC_NAME} stellar_core gtest) gtest_discover_tests(${EXEC_NAME}) endfunction() diff --git a/test/packet_parser/packet_parser.cpp b/test/packet_parser/packet_parser.cpp index fca3958..2d00575 100644 --- a/test/packet_parser/packet_parser.cpp +++ b/test/packet_parser/packet_parser.cpp @@ -1,5 +1,6 @@ #include #include +#include "ipv6_utils.h" #include "packet_priv.h" struct options @@ -11,6 +12,42 @@ struct options 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) { 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"); break; case LAYER_TYPE_IPV6: - used += snprintf(buff + used, size - used, "ipv6"); + used += ipv6_proto_to_str(layer, buff + used, size - used); break; case LAYER_TYPE_GRE: used += snprintf(buff + used, size - used, "gre");