TSG-16531 PacketAdapter适配容器环境,使用mrzcpd收包,通过RAW Socket注RST包

This commit is contained in:
luwenpeng
2023-08-09 18:47:16 +08:00
parent 1063574ca0
commit e34aa3f5e2
65 changed files with 4379 additions and 1174 deletions

View File

@@ -1,2 +1,11 @@
add_library(common src/decode_ipv4.c src/decode_ipv6.c src/decode_tcp.c src/decode_udp.c src/decode_gtp.c)
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
add_library(common
src/log.cpp
src/packet_io.cpp
src/packet_parser.cpp
src/packet_inject.cpp)
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(common PUBLIC mrzcpd)
target_link_libraries(common PUBLIC MESA_prof_load)
target_link_libraries(common PUBLIC MESA_handle_logger)
add_subdirectory(test)

View File

@@ -1,36 +0,0 @@
#ifndef _DECODE_GTP_H
#define _DECODE_GTP_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
/* According to 3GPP TS 29.060. */
typedef struct gtp1_header_s
{
uint8_t flags;
uint8_t type;
uint16_t length;
uint32_t tid;
} __attribute__((packed)) gtp1_header_t;
typedef struct gtp_info_s
{
gtp1_header_t *hdr;
uint8_t *payload;
uint32_t hdr_len;
uint32_t payload_len;
} gtp_info_t;
int decode_gtp(gtp_info_t *packet, const uint8_t *data, uint32_t len);
int dump_gtp_info(gtp_info_t *packet, char *buff, size_t size);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,55 +0,0 @@
#ifndef _DECODE_IPV4_H
#define _DECODE_IPV4_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
#define IPV4_HEADER_LEN 20
typedef struct ipv4_header_s
{
uint8_t ip_verhl; // version & header length
uint8_t ip_tos;
uint16_t ip_len;
uint16_t ip_id;
uint16_t ip_off;
uint8_t ip_ttl;
uint8_t ip_proto;
uint16_t ip_csum;
union
{
struct
{
struct in_addr ip_src;
struct in_addr ip_dst;
} ip4_un1;
uint16_t ip_addrs[4];
} ip4_hdrun1;
} __attribute__((__packed__)) ipv4_header_t;
typedef struct ipv4_info_s
{
char src_addr[INET_ADDRSTRLEN];
char dst_addr[INET_ADDRSTRLEN];
ipv4_header_t *hdr;
uint8_t *payload;
uint8_t next_protocol;
uint32_t hdr_len;
uint32_t opts_len;
uint32_t payload_len;
} ipv4_info_t;
int decode_ipv4(ipv4_info_t *packet, const uint8_t *data, uint32_t len);
int dump_ipv4_info(ipv4_info_t *packet, char *buff, size_t size);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,58 +0,0 @@
#ifndef _DECODE_IPV6_H
#define _DECODE_IPV6_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
#define IPV6_HEADER_LEN 40
typedef struct ipv6_header_s
{
union
{
struct ip6_un1_
{
uint32_t ip6_un1_flow; /* 20 bits of flow-ID */
uint16_t ip6_un1_plen; /* payload length */
uint8_t ip6_un1_nxt; /* next header */
uint8_t ip6_un1_hlim; /* hop limit */
} ip6_un1;
uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */
} ip6_hdrun;
union
{
struct
{
uint32_t ip6_src[4];
uint32_t ip6_dst[4];
} ip6_un2;
uint16_t ip6_addrs[16];
} ip6_hdrun2;
} __attribute__((__packed__)) ipv6_header_t;
typedef struct ipv6_info_s
{
char src_addr[INET6_ADDRSTRLEN];
char dst_addr[INET6_ADDRSTRLEN];
ipv6_header_t *hdr;
uint8_t *payload;
uint8_t next_protocol;
uint32_t hdr_len;
uint32_t payload_len;
} ipv6_info_t;
int decode_ipv6(ipv6_info_t *packet, const uint8_t *data, uint32_t len);
int dump_ipv6_info(ipv6_info_t *packet, char *buff, size_t size);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,46 +0,0 @@
#ifndef _DECODE_TCP_H
#define _DECODE_TCP_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
#define TCP_HEADER_LEN 20
typedef struct tcp_header_s
{
uint16_t th_sport; /**< source port */
uint16_t th_dport; /**< destination port */
uint32_t th_seq; /**< sequence number */
uint32_t th_ack; /**< acknowledgement number */
uint8_t th_offx2; /**< offset and reserved */
uint8_t th_flags; /**< pkt flags */
uint16_t th_win; /**< pkt window */
uint16_t th_sum; /**< checksum */
uint16_t th_urp; /**< urgent pointer */
} __attribute__((__packed__)) tcp_header_t;
typedef struct tcp_info_s
{
uint16_t src_port;
uint16_t dst_port;
tcp_header_t *hdr;
uint8_t *payload;
uint32_t opt_len;
uint32_t hdr_len;
uint32_t payload_len;
} tcp_info_t;
int decode_tcp(tcp_info_t *packet, const uint8_t *data, uint32_t len);
int dump_tcp_info(tcp_info_t *packet, char *buff, size_t size);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,40 +0,0 @@
#ifndef _DECODE_UDP_H
#define _DECODE_UDP_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
#define UDP_HEADER_LEN 8
typedef struct udp_header_s
{
uint16_t udp_src_port;
uint16_t udp_dst_port;
uint16_t udp_len;
uint16_t udp_sum;
} __attribute__((__packed__)) udp_header_t;
typedef struct udp_info_s
{
uint16_t src_port;
uint16_t dst_port;
udp_header_t *hdr;
uint8_t *payload;
uint32_t hdr_len;
uint32_t payload_len;
} udp_info_t;
int decode_udp(udp_info_t *packet, const uint8_t *data, uint32_t len);
int dump_udp_info(udp_info_t *packet, char *buff, size_t size);
#ifdef __cpluscplus
}
#endif
#endif

73
common/include/log.h Normal file
View File

@@ -0,0 +1,73 @@
#ifndef _LOG_H
#define _LOG_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdio.h>
#include <MESA/MESA_handle_logger.h>
extern void *default_logger;
int LOG_INIT(const char *profile);
void LOG_CLOSE(void);
void LOG_RELOAD(void);
#define LOG_DEBUG(format, ...) \
do \
{ \
if (default_logger == NULL) \
{ \
fprintf(stdout, "[DEBUG] " format "\n", ##__VA_ARGS__); \
fflush(stdout); \
} \
else \
{ \
if (MESA_handle_runtime_log_level_enabled(default_logger, RLOG_LV_DEBUG)) \
{ \
MESA_handle_runtime_log(default_logger, RLOG_LV_DEBUG, __FUNCTION__, format, ##__VA_ARGS__); \
} \
} \
} while (0)
#define LOG_INFO(format, ...) \
do \
{ \
if (default_logger == NULL) \
{ \
fprintf(stdout, "[INFOR] " format "\n", ##__VA_ARGS__); \
fflush(stdout); \
} \
else \
{ \
if (MESA_handle_runtime_log_level_enabled(default_logger, RLOG_LV_INFO)) \
{ \
MESA_handle_runtime_log(default_logger, RLOG_LV_INFO, __FUNCTION__, format, ##__VA_ARGS__); \
} \
} \
} while (0)
#define LOG_ERROR(format, ...) \
do \
{ \
if (default_logger == NULL) \
{ \
fprintf(stdout, "[ERROR] " format "\n", ##__VA_ARGS__); \
fflush(stdout); \
} \
else \
{ \
if (MESA_handle_runtime_log_level_enabled(default_logger, RLOG_LV_FATAL)) \
{ \
MESA_handle_runtime_log(default_logger, RLOG_LV_FATAL, __FUNCTION__, format, ##__VA_ARGS__); \
} \
} \
} while (0)
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -0,0 +1,19 @@
#ifndef _PACKET_INJECT_H
#define _PACKET_INJECT_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <netinet/ip.h>
#include <netinet/ip6.h>
int packet_inject_ipv4(struct in_addr *ip_dst, const char *data, int len);
int packet_inject_ipv6(struct in6_addr *ip6_dst, const char *data, int len);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -0,0 +1,35 @@
#ifndef _PACKET_IO_H
#define _PACKET_IO_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <marsio.h>
#define MAX_THREAD_NUM 128
enum action
{
ACTION_BYPASS = 0x1,
ACTION_DROP = 0x2,
};
struct packet_io;
typedef enum action packet_handle_cb(const char *data, int len, void *args);
void packet_io_set_callback(struct packet_io *handle, packet_handle_cb *cb, void *args);
struct packet_io *packet_io_create(const char *profile);
void packet_io_destory(struct packet_io *handle);
int packet_io_thread_init(struct packet_io *handle, int thread_index);
void packet_io_thread_wait(struct packet_io *handle, int thread_index, int timeout_ms);
int packet_io_thread_polling(struct packet_io *handle, int thread_index);
int packet_io_thread_number(struct packet_io *handle);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -0,0 +1,85 @@
#ifndef _PACKET_PARSER_H
#define _PACKET_PARSER_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdint.h>
enum layer_type
{
// 数据链路层
LAYER_TYPE_ETHER = 1 << 0,
LAYER_TYPE_PPP = 1 << 1,
LAYER_TYPE_HDLC = 1 << 2,
LAYER_TYPE_L2 = (LAYER_TYPE_ETHER | LAYER_TYPE_PPP | LAYER_TYPE_HDLC),
// 数据链路层 -- 隧道
LAYER_TYPE_VLAN = 1 << 3,
LAYER_TYPE_PPPOE = 1 << 4,
LAYER_TYPE_MPLS = 1 << 5,
LAYER_TYPE_L2_TUN = (LAYER_TYPE_VLAN | LAYER_TYPE_PPPOE | LAYER_TYPE_MPLS),
// 网络层
LAYER_TYPE_IPV4 = 1 << 6,
LAYER_TYPE_IPV6 = 1 << 7,
LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6),
// 网络层 -- 隧道
// 传输层
LAYER_TYPE_UDP = 1 << 8,
LAYER_TYPE_TCP = 1 << 9,
LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP),
// 传输层 -- 隧道
LAYER_TYPE_G_VXLAN = 1 << 10,
LAYER_TYPE_GTPV1_U = 1 << 11,
// ALL
LAYER_TYPE_ALL = (LAYER_TYPE_L2 | LAYER_TYPE_L2_TUN | LAYER_TYPE_L3 | LAYER_TYPE_L4 | LAYER_TYPE_G_VXLAN | LAYER_TYPE_GTPV1_U),
// UNKNOWN
LAYER_TYPE_UNKNOWN,
};
struct layer_record
{
enum layer_type type;
uint16_t hdr_offset;
uint16_t hdr_len;
uint16_t pld_len;
};
struct parser_result
{
struct layer_record layers[16];
uint16_t used;
uint16_t size;
};
struct packet_parser
{
struct parser_result result;
const void *packet_data;
uint16_t packet_len;
uint64_t packet_id;
};
void packet_parser_init(struct packet_parser *handler);
const void *packet_parser_parse(struct packet_parser *handler, const void *packet_data, uint16_t packet_len, uint64_t packet_id); // return most inner payload
const struct layer_record *packet_parser_get_most_inner(struct packet_parser *handler, enum layer_type type);
const struct layer_record *packet_parser_get_most_outer(struct packet_parser *handler, enum layer_type type);
// return 4: IPv4
// return 6: IPv6
uint8_t gtp_next_proto(const char *data);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,38 +0,0 @@
#ifndef _PUBLIC_H
#define _PUBLIC_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define IP_GET_RAW_VER(raw_pkt) ((((raw_pkt)[0] & 0xf0) >> 4))
#define LOG_DEBUG(format, ...) \
{ \
fprintf(stdout, format "\n", ##__VA_ARGS__); \
fflush(stdout); \
}
#define LOG_ERROR(format, ...) \
{ \
fprintf(stderr, format "\n", ##__VA_ARGS__); \
fflush(stderr); \
}
#ifdef __cpluscplus
}
#endif
#endif

61
common/include/utils.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef _UTILS_H
#define _UTILS_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdio.h>
struct metrics
{
uint64_t rx_pkts;
uint64_t rx_bytes;
uint64_t rx_err_pkts;
uint64_t rx_err_bytes;
uint64_t succ_tx_v4_pkts;
uint64_t succ_tx_v4_bytes;
uint64_t succ_tx_v6_pkts;
uint64_t succ_tx_v6_bytes;
uint64_t err_tx_v4_pkts;
uint64_t err_tx_v4_bytes;
uint64_t err_tx_v6_pkts;
uint64_t err_tx_v6_bytes;
};
inline void metrics_dump(struct metrics *metrics)
{
printf(" rx_pkts : %ld\n", metrics->rx_pkts);
printf(" rx_bytes : %ld\n", metrics->rx_bytes);
printf(" rx_err_pkts : %ld\n", metrics->rx_err_pkts);
printf(" rx_err_bytes : %ld\n", metrics->rx_err_bytes);
printf(" succ_tx_v4_pkts : %ld\n", metrics->succ_tx_v4_pkts);
printf(" succ_tx_v4_bytes : %ld\n", metrics->succ_tx_v4_bytes);
printf(" succ_tx_v6_pkts : %ld\n", metrics->succ_tx_v6_pkts);
printf(" succ_tx_v6_bytes : %ld\n", metrics->succ_tx_v6_bytes);
printf(" err_tx_v4_pkts : %ld\n", metrics->err_tx_v4_pkts);
printf(" err_tx_v4_bytes : %ld\n", metrics->err_tx_v4_bytes);
printf(" err_tx_v6_pkts : %ld\n", metrics->err_tx_v6_pkts);
printf(" err_tx_v6_bytes : %ld\n", metrics->err_tx_v6_bytes);
}
#define ATOMIC_READ(x) __atomic_fetch_add(x, 0, __ATOMIC_RELAXED)
#define ATOMIC_ADD(x, y) __atomic_fetch_add(x, y, __ATOMIC_RELAXED)
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -1,56 +0,0 @@
#include "decode_gtp.h"
#define GTP_TPDU 255
#define GTP1U_PORT 2152
#define GTP1_F_MASK 0x07
#define GTP1_GET_TYPE(gtp1_hdr) ((gtp1_hdr)->type)
#define GTP1_GET_FLAGS(gtp1_hdr) ((gtp1_hdr)->flags >> 5)
#define GTP1_GET_HLEN(gtp1_hdr) (((gtp1_hdr)->flags & GTP1_F_MASK) > 0 ? 12 : 8)
enum gtp_version_e
{
GTP_V0 = 0,
GTP_V1,
};
int decode_gtp(gtp_info_t *packet, const uint8_t *data, uint32_t len)
{
if (len < sizeof(gtp1_header_t))
{
LOG_ERROR("Parser GTP Header: packet length too small %d", len);
return -1;
}
packet->hdr = (gtp1_header_t *)data;
if (GTP1_GET_FLAGS(packet->hdr) != GTP_V1)
{
LOG_ERROR("Parser GTP Header: invalid gtp flags %d", GTP1_GET_FLAGS(packet->hdr));
return -1;
}
if (GTP1_GET_TYPE(packet->hdr) != GTP_TPDU)
{
LOG_ERROR("Parser GTP Header: invalid gtp type %d", GTP1_GET_TYPE(packet->hdr));
return -1;
}
/* From 29.060: "This field shall be present if and only if any one or
* more of the S, PN and E flags are set.".
*
* If any of the bit is set, then the remaining ones also have to be set.
*/
packet->hdr_len = GTP1_GET_HLEN(packet->hdr);
packet->payload = (uint8_t *)data + packet->hdr_len;
packet->payload_len = len - packet->hdr_len;
return 0;
}
int dump_gtp_info(gtp_info_t *packet, char *buff, size_t size)
{
return snprintf(buff, size,
"{\"hdr_len\":%u,\"data_len\":%u}",
packet->hdr_len,
packet->payload_len);
}

View File

@@ -1,68 +0,0 @@
#include "decode_ipv4.h"
#define IPV4_GET_HLEN(ip4_hdr) (((ip4_hdr)->ip_verhl & 0x0f) << 2)
#define IPV4_GET_IPPROTO(ip4_hdr) ((ip4_hdr)->ip_proto)
#define IPV4_GET_IPLEN(ip4_hdr) ((uint16_t)ntohs((ip4_hdr)->ip_len))
#define IPV4_GET_SRC_ADDR(ip4_hdr) ((ip4_hdr)->ip4_hdrun1.ip4_un1.ip_src)
#define IPV4_GET_DST_ADDR(ip4_hdr) ((ip4_hdr)->ip4_hdrun1.ip4_un1.ip_dst)
int decode_ipv4(ipv4_info_t *packet, const uint8_t *data, uint32_t len)
{
// 检查包长是否大于 IPv4 header
if (len < IPV4_HEADER_LEN)
{
LOG_ERROR("Parser IPv4 Header: packet length too small %d", len);
return -1;
}
// 检查 IPv4 header version
if (IP_GET_RAW_VER(data) != 4)
{
LOG_ERROR("Parser IPv4 Header: invalid IP version %d", IP_GET_RAW_VER(data));
return -1;
}
packet->hdr = (ipv4_header_t *)data;
// 检查 IPv4 header length
if (IPV4_GET_HLEN(packet->hdr) < IPV4_HEADER_LEN)
{
LOG_ERROR("Parser IPv4 Header: invalid IP header length %d", IPV4_GET_HLEN(packet->hdr));
return -1;
}
// 检查 IPv4 header total length
if (IPV4_GET_IPLEN(packet->hdr) < IPV4_GET_HLEN(packet->hdr))
{
LOG_ERROR("Parser IPv4 Header: invalid IP header total length %d", IPV4_GET_IPLEN(packet->hdr));
return -1;
}
// 检查是否 IP 分片
if (len < IPV4_GET_IPLEN(packet->hdr))
{
LOG_ERROR("Parser IPv4 Header: trunc packet");
return -1;
}
inet_ntop(AF_INET, &IPV4_GET_SRC_ADDR(packet->hdr), packet->src_addr, sizeof(packet->src_addr));
inet_ntop(AF_INET, &IPV4_GET_DST_ADDR(packet->hdr), packet->dst_addr, sizeof(packet->dst_addr));
packet->next_protocol = IPV4_GET_IPPROTO(packet->hdr);
packet->hdr_len = IPV4_GET_HLEN(packet->hdr);
packet->opts_len = packet->hdr_len - IPV4_HEADER_LEN;
packet->payload_len = len - packet->hdr_len;
packet->payload = (uint8_t *)data + packet->hdr_len;
return 0;
}
int dump_ipv4_info(ipv4_info_t *packet, char *buff, size_t size)
{
return snprintf(buff, size,
"{\"src_addr\":\"%s\",\"dst_addr\":\"%s\",\"hdr_len\":%u,\"opts_len\":%u,\"data_len\":%u}",
packet->src_addr,
packet->dst_addr,
packet->hdr_len,
packet->opts_len,
packet->payload_len);
}

View File

@@ -1,55 +0,0 @@
#include "decode_ipv6.h"
#define IPV6_GET_PLEN(ip6_hdr) ((uint16_t)ntohs((ip6_hdr)->ip6_hdrun.ip6_un1.ip6_un1_plen))
#define IPV6_GET_NH(ip6_hdr) ((ip6_hdr)->ip6_hdrun.ip6_un1.ip6_un1_nxt)
#define IPV6_GET_SRC_ADDR(ip6_hdr) ((ip6_hdr)->ip6_hdrun2.ip6_un2.ip6_src)
#define IPV6_GET_DST_ADDR(ip6_hdr) ((ip6_hdr)->ip6_hdrun2.ip6_un2.ip6_dst)
int decode_ipv6(ipv6_info_t *packet, const uint8_t *data, uint32_t len)
{
if (len < IPV6_HEADER_LEN)
{
LOG_ERROR("Parser IPv6 Header: packet length too small %d", len);
return -1;
}
// 检查 IPv6 header version
if (IP_GET_RAW_VER(data) != 6)
{
LOG_ERROR("Parser IPv6 Header: invalid IP version %d", IP_GET_RAW_VER(data));
return -1;
}
packet->hdr = (ipv6_header_t *)data;
if (len < (IPV6_HEADER_LEN + IPV6_GET_PLEN(packet->hdr)))
{
LOG_ERROR("Parser IPv6 Header: trunc packet");
return -1;
}
if (len != (IPV6_HEADER_LEN + IPV6_GET_PLEN(packet->hdr)))
{
LOG_ERROR("Parser IPv6 Header: invalid payload length %d", IPV6_GET_PLEN(packet->hdr));
return -1;
}
inet_ntop(AF_INET6, &IPV6_GET_SRC_ADDR(packet->hdr), packet->src_addr, sizeof(packet->src_addr));
inet_ntop(AF_INET6, &IPV6_GET_DST_ADDR(packet->hdr), packet->dst_addr, sizeof(packet->dst_addr));
packet->next_protocol = IPV6_GET_NH(packet->hdr);
packet->hdr_len = IPV6_HEADER_LEN;
packet->payload = (uint8_t *)data + packet->hdr_len;
packet->payload_len = len - packet->hdr_len;
return 0;
}
int dump_ipv6_info(ipv6_info_t *packet, char *buff, size_t size)
{
return snprintf(buff, size,
"{\"src_addr\":\"%s\",\"dst_addr\":\"%s\",\"hdr_len\":%u,\"data_len\":%u}",
packet->src_addr,
packet->dst_addr,
packet->hdr_len,
packet->payload_len);
}

View File

@@ -1,52 +0,0 @@
#include "decode_tcp.h"
#define TCP_OPTLENMAX 40
#define TCP_GET_HLEN(tcp_hdr) ((((tcp_hdr)->th_offx2 & 0xf0) >> 4) << 2)
#define TCP_GET_SRC_PORT(tcp_hdr) ((uint16_t)ntohs((tcp_hdr)->th_sport))
#define TCP_GET_DST_PORT(tcp_hdr) ((uint16_t)ntohs((tcp_hdr)->th_dport))
int decode_tcp(tcp_info_t *packet, const uint8_t *data, uint32_t len)
{
if (len < TCP_HEADER_LEN)
{
LOG_ERROR("Parser TCP Header: packet length too small %d", len);
return -1;
}
packet->hdr = (tcp_header_t *)data;
uint8_t hlen = TCP_GET_HLEN(packet->hdr);
if (len < hlen)
{
LOG_ERROR("Parser TCP Header: TCP packet too small %d", len);
return -1;
}
uint8_t tcp_opt_len = hlen - TCP_HEADER_LEN;
if (tcp_opt_len > TCP_OPTLENMAX)
{
LOG_ERROR("Parser TCP Header: invalid opt length %d", tcp_opt_len);
return -1;
}
packet->opt_len = tcp_opt_len;
packet->src_port = TCP_GET_SRC_PORT(packet->hdr);
packet->dst_port = TCP_GET_DST_PORT(packet->hdr);
packet->hdr_len = hlen;
packet->payload = (uint8_t *)data + packet->hdr_len;
packet->payload_len = len - packet->hdr_len;
return 0;
}
int dump_tcp_info(tcp_info_t *packet, char *buff, size_t size)
{
return snprintf(buff, size,
"{\"src_port\":%u,\"dst_port\":%u,\"hdr_len\":%u,\"opt_len\":%u,\"data_len\":%u}",
packet->src_port,
packet->dst_port,
packet->hdr_len,
packet->opt_len,
packet->payload_len);
}

View File

@@ -1,48 +0,0 @@
#include "decode_udp.h"
#define UDP_GET_LEN(udp_hdr) ((uint16_t)ntohs((udp_hdr)->udp_len))
#define UDP_GET_SRC_PORT(udp_hdr) ((uint16_t)ntohs((udp_hdr)->udp_src_port))
#define UDP_GET_DST_PORT(udp_hdr) ((uint16_t)ntohs((udp_hdr)->udp_dst_port))
int decode_udp(udp_info_t *packet, const uint8_t *data, uint32_t len)
{
if (len < UDP_HEADER_LEN)
{
LOG_ERROR("Parser UDP Header: packet length too small %d", len);
return -1;
}
packet->hdr = (udp_header_t *)data;
// 检查 UDP header len
if (len < UDP_GET_LEN(packet->hdr))
{
LOG_ERROR("Parser UDP Header: UDP packet too small %d", len);
return -1;
}
// 检查 UDP header len
if (len != UDP_GET_LEN(packet->hdr))
{
LOG_ERROR("Parser UDP Header: invalid UDP header length %d", UDP_GET_LEN(packet->hdr));
return -1;
}
packet->src_port = UDP_GET_SRC_PORT(packet->hdr);
packet->dst_port = UDP_GET_DST_PORT(packet->hdr);
packet->hdr_len = UDP_HEADER_LEN;
packet->payload = (uint8_t *)data + UDP_HEADER_LEN;
packet->payload_len = len - UDP_HEADER_LEN;
return 0;
}
int dump_udp_info(udp_info_t *packet, char *buff, size_t size)
{
return snprintf(buff, size,
"{\"src_port\":%u,\"dst_port\":%u,\"hdr_len\":%u,\"data_len\":%u}",
packet->src_port,
packet->dst_port,
packet->hdr_len,
packet->payload_len);
}

33
common/src/log.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include "log.h"
void *default_logger = NULL;
// return 0 : success
// return -1 : error
int LOG_INIT(const char *profile)
{
if (0 != MESA_handle_runtime_log_creation(profile))
{
fprintf(stderr, "FATAL: unable to create runtime logger\n");
return -1;
}
default_logger = MESA_create_runtime_log_handle("packet_adapter", RLOG_LV_DEBUG);
if (default_logger == NULL)
{
fprintf(stderr, "FATAL: unable to create log handle\n");
return -1;
}
return 0;
}
void LOG_CLOSE(void)
{
MESA_handle_runtime_log_destruction();
}
void LOG_RELOAD(void)
{
MESA_handle_runtime_log_reconstruction(NULL);
}

View File

@@ -0,0 +1,58 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "log.h"
int packet_inject_ipv4(struct in_addr *ip_dst, const char *data, int len)
{
struct sockaddr_in saddr4 = {0};
saddr4.sin_family = PF_INET;
memcpy(&saddr4.sin_addr, ip_dst, sizeof(struct in_addr));
int fd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (fd == -1)
{
LOG_ERROR("Failed at socket(PF_INET, SOCK_RAW), %d: %s", errno, strerror(errno));
return -1;
}
if (sendto(fd, data, len, 0, (struct sockaddr *)&saddr4, sizeof(saddr4)) == -1)
{
char string[256] = {0};
inet_ntop(PF_INET, ip_dst, string, sizeof(string));
LOG_ERROR("Failed at send() %s, (%d: %s)", string, errno, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}
int packet_inject_ipv6(struct in6_addr *ip6_dst, const char *data, int len)
{
struct sockaddr_in6 saddr6 = {0};
saddr6.sin6_family = PF_INET6;
memcpy(&saddr6.sin6_addr, ip6_dst, sizeof(struct in6_addr));
int fd = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
if (fd == -1)
{
LOG_ERROR("Failed at socket(PF_INET6, SOCK_RAW), %d: %s", errno, strerror(errno));
return -1;
}
if (sendto(fd, data, len, 0, (struct sockaddr *)&saddr6, sizeof(saddr6)) == -1)
{
char string[256] = {0};
inet_ntop(PF_INET6, ip6_dst, string, sizeof(string));
LOG_ERROR("Failed at send() %s, (%d: %s)", string, errno, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}

280
common/src/packet_io.cpp Normal file
View File

@@ -0,0 +1,280 @@
#include <sched.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <netinet/ether.h>
#include <MESA/MESA_prof_load.h>
#include "log.h"
#include "packet_io.h"
#define MAX_RX_BURST 128
#define LOG_PKTIO "PACKET_IO"
#define MIN(a, b) ((a) > (b) ? (b) : (a))
struct config
{
int thread_num;
int cpu_mask[MAX_THREAD_NUM];
int rx_burst_max;
int bypass_traffic;
char app_symbol[256];
char app_device[256];
};
struct packet_io
{
struct config config;
struct mr_vdev *mr_dev;
struct mr_sendpath *mr_path;
struct mr_instance *mr_instance;
void *cb_args;
packet_handle_cb *callback;
};
static int packet_io_config(const char *profile, struct config *config)
{
MESA_load_profile_int_def(profile, "PACKET_IO", "thread_num", (int *)&(config->thread_num), 1);
MESA_load_profile_uint_range(profile, "PACKET_IO", "cpu_mask", MAX_THREAD_NUM, (unsigned int *)config->cpu_mask);
MESA_load_profile_int_def(profile, "PACKET_IO", "rx_burst_max", (int *)&(config->rx_burst_max), 1);
MESA_load_profile_int_def(profile, "PACKET_IO", "bypass_traffic", (int *)&(config->bypass_traffic), 0);
MESA_load_profile_string_nodef(profile, "PACKET_IO", "app_symbol", config->app_symbol, sizeof(config->app_symbol));
MESA_load_profile_string_nodef(profile, "PACKET_IO", "app_device", config->app_device, sizeof(config->app_device));
config->thread_num = MIN(config->thread_num, MAX_THREAD_NUM);
if (config->rx_burst_max > MAX_RX_BURST)
{
LOG_ERROR("%s: invalid rx_burst_max, exceeds limit %d", LOG_PKTIO, MAX_RX_BURST);
return -1;
}
if (strlen(config->app_symbol) == 0)
{
LOG_ERROR("%s: invalid app_symbol in %s", LOG_PKTIO, profile);
return -1;
}
if (strlen(config->app_device) == 0)
{
LOG_ERROR("%s: invalid app_device in %s", LOG_PKTIO, profile);
return -1;
}
LOG_DEBUG("%s: PACKET_IO->thread_num : %d", LOG_PKTIO, config->thread_num);
LOG_DEBUG("%s: PACKET_IO->rx_burst_max : %d", LOG_PKTIO, config->rx_burst_max);
LOG_DEBUG("%s: PACKET_IO->bypass_traffic : %d", LOG_PKTIO, config->bypass_traffic);
LOG_DEBUG("%s: PACKET_IO->app_symbol : %s", LOG_PKTIO, config->app_symbol);
LOG_DEBUG("%s: PACKET_IO->app_device : %s", LOG_PKTIO, config->app_device);
return 0;
}
static int marsio_buff_is_keepalive(char *raw_data, int raw_len)
{
if (raw_data == NULL || raw_len < (int)(sizeof(struct ethhdr)))
{
return 0;
}
struct ethhdr *eth_hdr = (struct ethhdr *)raw_data;
if (eth_hdr->h_proto == 0xAAAA)
{
return 1;
}
else
{
return 0;
}
}
struct packet_io *packet_io_create(const char *profile)
{
int opt = 1;
cpu_set_t coremask;
struct packet_io *handle = (struct packet_io *)calloc(1, sizeof(struct packet_io));
assert(handle != NULL);
if (packet_io_config(profile, &(handle->config)) != 0)
{
goto error_out;
}
CPU_ZERO(&coremask);
for (int i = 0; i < handle->config.thread_num; i++)
{
CPU_SET(handle->config.cpu_mask[i], &coremask);
}
handle->mr_instance = marsio_create();
if (handle->mr_instance == NULL)
{
LOG_ERROR("%s: unable to create marsio instance", LOG_PKTIO);
goto error_out;
}
if (marsio_option_set(handle->mr_instance, MARSIO_OPT_THREAD_MASK_IN_CPUSET, &coremask, sizeof(cpu_set_t)) != 0)
{
LOG_ERROR("%s: unable to set MARSIO_OPT_EXIT_WHEN_ERR option for marsio instance", LOG_PKTIO);
goto error_out;
}
if (marsio_option_set(handle->mr_instance, MARSIO_OPT_EXIT_WHEN_ERR, &opt, sizeof(opt)) != 0)
{
LOG_ERROR("%s: unable to set MARSIO_OPT_EXIT_WHEN_ERR option for marsio instance", LOG_PKTIO);
goto error_out;
}
if (marsio_init(handle->mr_instance, handle->config.app_symbol) != 0)
{
LOG_ERROR("%s: unable to initialize marsio instance", LOG_PKTIO);
goto error_out;
}
handle->mr_dev = marsio_open_device(handle->mr_instance, handle->config.app_device, handle->config.thread_num, handle->config.thread_num);
if (handle->mr_dev == NULL)
{
LOG_ERROR("%s: unable to open device %s", LOG_PKTIO, handle->config.app_device);
goto error_out;
}
handle->mr_path = marsio_sendpath_create_by_vdev(handle->mr_dev);
if (handle->mr_path == NULL)
{
LOG_ERROR("%s: unable to create sendpath for device %s", LOG_PKTIO, handle->config.app_device);
goto error_out;
}
return handle;
error_out:
packet_io_destory(handle);
return NULL;
}
void packet_io_destory(struct packet_io *handle)
{
if (handle)
{
if (handle->mr_path)
{
marsio_sendpath_destory(handle->mr_path);
handle->mr_path = NULL;
}
if (handle->mr_dev)
{
marsio_close_device(handle->mr_dev);
handle->mr_dev = NULL;
}
if (handle->mr_instance)
{
marsio_destory(handle->mr_instance);
handle->mr_instance = NULL;
}
free(handle);
handle = NULL;
}
}
void packet_io_set_callback(struct packet_io *handle, packet_handle_cb *cb, void *args)
{
handle->callback = cb;
handle->cb_args = args;
}
int packet_io_thread_init(struct packet_io *handle, int thread_index)
{
if (marsio_thread_init(handle->mr_instance) != 0)
{
LOG_ERROR("%s: unable to init marsio thread %d", LOG_PKTIO, thread_index);
return -1;
}
return 0;
}
void packet_io_thread_wait(struct packet_io *handle, int thread_index, int timeout_ms)
{
struct mr_vdev *vdevs[] = {
handle->mr_dev,
};
marsio_poll_wait(handle->mr_instance, vdevs, 1, thread_index, timeout_ms);
}
int packet_io_thread_polling(struct packet_io *handle, int thread_index)
{
int raw_len;
char *raw_data;
marsio_buff_t *rx_buff;
marsio_buff_t *rx_buffs[MAX_RX_BURST];
int nr_recv = marsio_recv_burst(handle->mr_dev, thread_index, rx_buffs, handle->config.rx_burst_max);
if (nr_recv <= 0)
{
return 0;
}
if (handle->config.bypass_traffic == 1)
{
marsio_send_burst(handle->mr_path, thread_index, rx_buffs, nr_recv);
return nr_recv;
}
for (int j = 0; j < nr_recv; j++)
{
rx_buff = rx_buffs[j];
raw_len = marsio_buff_datalen(rx_buff);
raw_data = marsio_buff_mtod(rx_buff);
if (marsio_buff_is_keepalive(raw_data, raw_len))
{
marsio_send_burst(handle->mr_path, thread_index, &rx_buff, 1);
}
else if (marsio_buff_is_ctrlbuf(rx_buff))
{
marsio_send_burst(handle->mr_path, thread_index, &rx_buff, 1);
}
else
{
if (handle->callback)
{
if (handle->callback(raw_data, raw_len, handle->cb_args) == ACTION_BYPASS)
{
marsio_send_burst(handle->mr_path, thread_index, &rx_buff, 1);
}
else
{
marsio_buff_free(handle->mr_instance, &rx_buff, 1, 0, thread_index);
}
}
else
{
marsio_send_burst(handle->mr_path, thread_index, &rx_buff, 1);
}
}
}
return nr_recv;
}
int packet_io_thread_number(struct packet_io *handle)
{
if (handle)
{
return handle->config.thread_num;
}
else
{
return 0;
}
}

View File

@@ -0,0 +1,668 @@
#include <string.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#define __FAVOR_BSD 1
#include <netinet/tcp.h>
#include <netinet/ether.h>
#include "log.h"
#include "packet_parser.h"
#define LOG_PKT_PARSER "PACKET_PARSER"
/******************************************************************************
* Struct
******************************************************************************/
struct udp_hdr
{
uint16_t uh_sport; /* source port */
uint16_t uh_dport; /* destination port */
uint16_t uh_ulen; /* udp length */
uint16_t uh_sum; /* udp checksum */
} __attribute__((__packed__));
struct vlan_hdr
{
uint16_t vlan_cfi;
uint16_t protocol;
} __attribute__((__packed__));
struct vxlan_hdr
{
uint8_t flags[2];
uint16_t gdp; // group policy id
uint8_t vni[3];
uint8_t reserved;
} __attribute__((__packed__));
struct gtp_hdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned char flags;
unsigned char msg_type;
unsigned short len;
unsigned int teid;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int teid;
unsigned short len;
unsigned char msg_type;
unsigned char flags;
#else
#error "Please check <endian.h>"
#endif
} __attribute__((__packed__));
#define GTP_HDR_VER_MASK (0xE0)
#define GTP_HDR_FLAG_N_PDU (0x01)
#define GTP_HDR_FLAG_SEQ_NUM (0x02)
#define GTP_HDR_FLAG_NEXT_EXT_HDR (0x04)
/******************************************************************************
* Static API
******************************************************************************/
static int packet_parser_push(struct packet_parser *handler, enum layer_type type, uint16_t hdr_offset, uint16_t hdr_len, uint16_t payload_len);
// parser utils
static const char *layer2str(enum layer_type type);
static uint16_t parse_gtphdr_len(const struct gtp_hdr *gtph);
// parser protocol
static const void *parse_ether(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_ipv4(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_ipv6(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_tcp(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_udp(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_pppoe_ses(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_vxlan(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_vlan8021q(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_gtpv1_u(struct packet_parser *handler, const void *data, uint16_t length);
static const void *parse_mpls(struct packet_parser *handler, const void *data, uint16_t length);
/******************************************************************************
* Public API
******************************************************************************/
void packet_parser_init(struct packet_parser *handler)
{
memset(handler, 0, sizeof(struct packet_parser));
handler->result.used = 0;
handler->result.size = sizeof(handler->result.layers) / sizeof(handler->result.layers[0]);
handler->packet_data = NULL;
handler->packet_len = 0;
handler->packet_id = 0;
}
// return most inner payload
const void *packet_parser_parse(struct packet_parser *handler, const void *packet_data, uint16_t packet_len, uint64_t packet_id)
{
handler->packet_data = packet_data;
handler->packet_len = packet_len;
handler->packet_id = packet_id;
// TESTED OK BY LWP
return parse_ether(handler, handler->packet_data, handler->packet_len);
}
const struct layer_record *packet_parser_get_most_inner(struct packet_parser *handler, enum layer_type type)
{
struct parser_result *result = &handler->result;
for (int16_t i = result->used - 1; i >= 0; i--)
{
const struct layer_record *layer = &result->layers[i];
if (layer->type & type)
{
return layer;
}
}
return NULL;
}
const struct layer_record *packet_parser_get_most_outer(struct packet_parser *handler, enum layer_type type)
{
struct parser_result *result = &handler->result;
for (int16_t i = 0; i <= result->used - 1; i++)
{
const struct layer_record *layer = &result->layers[i];
if (layer->type & type)
{
return layer;
}
}
return NULL;
}
// return 4: IPv4
// return 6: IPv6
uint8_t gtp_next_proto(const char *data)
{
uint16_t hdr_len = parse_gtphdr_len((const struct gtp_hdr *)data);
if (hdr_len < 0)
{
return 0;
}
uint8_t next_proto = (((const uint8_t *)(data + hdr_len))[0]) >> 4;
return next_proto;
}
/******************************************************************************
* Private API
******************************************************************************/
static int packet_parser_push(struct packet_parser *handler, enum layer_type type, uint16_t hdr_offset, uint16_t hdr_len, uint16_t payload_len)
{
struct parser_result *result = &handler->result;
if (result->used >= result->size)
{
return -1;
}
result->layers[result->used].type = type;
result->layers[result->used].hdr_offset = hdr_offset;
result->layers[result->used].hdr_len = hdr_len;
result->layers[result->used].pld_len = payload_len;
result->used++;
return 0;
}
static const char *layer2str(enum layer_type type)
{
switch (type)
{
case LAYER_TYPE_ETHER:
return "ETHER";
case LAYER_TYPE_PPP:
return "PPP";
case LAYER_TYPE_HDLC:
return "HDLC";
case LAYER_TYPE_VLAN:
return "VLAN";
case LAYER_TYPE_PPPOE:
return "PPPOE";
case LAYER_TYPE_MPLS:
return "MPLS";
case LAYER_TYPE_IPV4:
return "IPV4";
case LAYER_TYPE_IPV6:
return "IPV6";
case LAYER_TYPE_UDP:
return "UDP";
case LAYER_TYPE_TCP:
return "TCP";
case LAYER_TYPE_G_VXLAN:
return "G_VXLAN";
case LAYER_TYPE_GTPV1_U:
return "GTPV1_U";
default:
return "UNKNOWN";
}
}
// FROM SAPP
static uint16_t parse_gtphdr_len(const struct gtp_hdr *gtph)
{
const unsigned char *p_ext_hdr = (unsigned char *)gtph + sizeof(struct gtp_hdr);
unsigned char next_hdr_type;
unsigned char this_ext_field_cont_len;
// v0 太古老已废弃,目前仅支持 GTPv1 版本
if (((gtph->flags & GTP_HDR_VER_MASK) >> 5) != 1)
{
return -1;
}
if (gtph->flags & (GTP_HDR_FLAG_SEQ_NUM | GTP_HDR_FLAG_N_PDU | GTP_HDR_FLAG_NEXT_EXT_HDR))
{
// skip seq field (2 bytes)
p_ext_hdr += 2;
// skip N-PDU field (1 byte)
p_ext_hdr++;
// 解析 GTP 扩展头部字段,参考 wireshark 源码 packet-gtp.c->dissect_gtp_common()
next_hdr_type = *p_ext_hdr;
if (gtph->flags & GTP_HDR_FLAG_NEXT_EXT_HDR)
{
while (next_hdr_type != 0)
{
// 指向长度字段, 以4个字节为单位
p_ext_hdr++;
this_ext_field_cont_len = *p_ext_hdr * 4 - 2;
// 指向数据部分第一个字节
p_ext_hdr++;
p_ext_hdr += this_ext_field_cont_len;
// 指向下一个头部字段
next_hdr_type = *p_ext_hdr;
p_ext_hdr++;
}
}
else
{
p_ext_hdr++;
}
}
return (char *)p_ext_hdr - (char *)gtph;
}
static const void *parse_ether(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct ethhdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_ETHER));
return data;
}
struct ethhdr *hdr = (struct ethhdr *)data;
uint16_t next_proto = ntohs(hdr->h_proto);
uint16_t hdr_len = sizeof(struct ethhdr);
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_ETHER, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_ETHER), payload_len, length);
switch (next_proto)
{
case ETH_P_8021Q:
// TESTED OK BY LWP
return parse_vlan8021q(handler, payload_data, payload_len);
case ETH_P_8021AD:
return parse_ether(handler, payload_data, payload_len);
case ETH_P_IP:
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case ETH_P_IPV6:
// TESTED OK BY LWP
return parse_ipv6(handler, payload_data, payload_len);
case ETH_P_PPP_SES:
return parse_pppoe_ses(handler, payload_data, payload_len);
case ETH_P_MPLS_UC:
// TESTED OK BY LWP
return parse_mpls(handler, payload_data, payload_len);
default:
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_ETHER), next_proto);
return payload_data;
}
}
static const void *parse_ipv4(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct ip))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV4));
return data;
}
struct ip *hdr = (struct ip *)data;
uint16_t next_proto = hdr->ip_p;
uint16_t hdr_len = (hdr->ip_hl & 0xf) * 4u;
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_IPV4, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV4), payload_len, length);
switch (next_proto)
{
case IPPROTO_TCP:
// TESTED OK BY LWP
return parse_tcp(handler, payload_data, payload_len);
case IPPROTO_UDP:
// TESTED OK BY LWP
return parse_udp(handler, payload_data, payload_len);
case IPPROTO_IPIP:
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case IPPROTO_IPV6:
// TESTED OK BY LWP
return parse_ipv6(handler, payload_data, payload_len);
default:
// TODO GRE
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV4), next_proto);
return payload_data;
}
}
static const void *parse_ipv6(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct ip6_hdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV6));
return data;
}
struct ip6_hdr *hdr = (struct ip6_hdr *)data;
uint16_t next_proto = hdr->ip6_nxt;
uint16_t hdr_len = sizeof(struct ip6_hdr);
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_IPV6, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV6), payload_len, length);
switch (next_proto)
{
case IPPROTO_TCP:
// TESTED OK BY LWP
return parse_tcp(handler, payload_data, payload_len);
case IPPROTO_UDP:
// TESTED OK BY LWP
return parse_udp(handler, payload_data, payload_len);
case IPPROTO_IPIP:
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case IPPROTO_IPV6:
// TESTED OK BY LWP
return parse_ipv6(handler, payload_data, payload_len);
default:
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_IPV6), next_proto);
return payload_data;
}
}
static const void *parse_tcp(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct tcphdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_TCP));
return data;
}
struct tcphdr *hdr = (struct tcphdr *)data;
uint16_t hdr_len = hdr->th_off << 2;
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_TCP, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_TCP), payload_len, length);
// TESTED OK BY LWP
return payload_data;
}
static const void *parse_udp(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct udp_hdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_UDP));
return data;
}
struct udp_hdr *hdr = (struct udp_hdr *)data;
uint16_t hdr_len = sizeof(struct udp_hdr);
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_UDP, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_UDP), payload_len, length);
switch (ntohs(hdr->uh_dport))
{
case 4789: // VXLAN_DPORT
// TESTED OK BY LWP
return parse_vxlan(handler, payload_data, payload_len);
case 2152: // GTP1U_PORT
// TESTED OK BY LWP
return parse_gtpv1_u(handler, payload_data, payload_len);
default:
// TESTED OK BY LWP
return payload_data;
}
}
static const void *parse_pppoe_ses(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < 8)
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_PPPOE));
return data;
}
uint16_t next_proto = *((uint16_t *)data + 3);
uint16_t hdr_len = 8;
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_PPPOE, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_PPPOE), payload_len, length);
switch (next_proto)
{
case 0x2100: // PPPOE_TYPE_IPV4
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case 0x5700: // PPPOE_TYPE_IPV6
return parse_ipv6(handler, payload_data, payload_len);
default:
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_PPPOE), next_proto);
return payload_data;
}
}
static const void *parse_vxlan(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct vxlan_hdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_G_VXLAN));
return NULL;
}
// struct vxlan_hdr *vxlan_hdr = (struct vxlan_hdr *)data;
uint16_t hdr_len = sizeof(struct vxlan_hdr);
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_G_VXLAN, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_G_VXLAN), payload_len, length);
// TESTED OK BY LWP
return parse_ether(handler, payload_data, payload_len);
}
static const void *parse_vlan8021q(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct vlan_hdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_VLAN));
return NULL;
}
struct vlan_hdr *hdr = (struct vlan_hdr *)data;
uint16_t next_proto = ntohs(hdr->protocol);
uint16_t hdr_len = sizeof(struct vlan_hdr);
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_VLAN, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_VLAN), payload_len, length);
switch (next_proto)
{
case ETH_P_8021Q:
// TESTED OK BY LWP
return parse_vlan8021q(handler, payload_data, payload_len);
case ETH_P_IP:
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case ETH_P_IPV6:
// TESTED OK BY LWP
return parse_ipv6(handler, payload_data, payload_len);
case ETH_P_PPP_SES:
// TESTED OK BY LWP
return parse_pppoe_ses(handler, payload_data, payload_len);
case ETH_P_MPLS_UC:
return parse_mpls(handler, payload_data, payload_len);
default:
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_VLAN), next_proto);
return payload_data;
}
}
static const void *parse_gtpv1_u(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < sizeof(struct gtp_hdr))
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_GTPV1_U));
return NULL;
}
uint16_t hdr_len = parse_gtphdr_len((const struct gtp_hdr *)data);
if (hdr_len < 0)
{
return data;
}
uint8_t next_proto = (((const uint8_t *)((const char *)data + hdr_len))[0]) >> 4;
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_GTPV1_U, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_GTPV1_U), payload_len, length);
switch (next_proto)
{
case 4:
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
case 6:
// TESTED OK BY LWP
return parse_ipv6(handler, payload_data, payload_len);
default:
LOG_ERROR("%s: trace id: %lu, layer: %s, stop parse next protocol %d", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_GTPV1_U), next_proto);
return payload_data;
}
}
static const void *parse_mpls(struct packet_parser *handler, const void *data, uint16_t length)
{
if (length < 4)
{
LOG_ERROR("%s: trace id: %lu, layer: %s, err: data not enough", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS));
return data;
}
#define MPLS_LABEL_MASK (0xFFFFF000)
#define MPLS_EXP_MASK (0x00000E00)
#define MPLS_BLS_MASK (0x00000100)
#define MPLS_TTL_MASK (0x000000FF)
/*
* MPLS Format
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Label | Exp |S| TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* Label : Label Value 20 bits
* Exp : Experimental Use 3 bits
* S : Bottom of Stack 1 bit
* TTL : Time to Live 8 bits
*/
uint32_t *hdr = (uint32_t *)data;
// unsigned int mpls_label = (ntohl(*hdr) & MPLS_LABEL_MASK) >> 12;
// unsigned int mpls_exp = (ntohl(*hdr) & MPLS_EXP_MASK) >> 9;
unsigned int mpls_bls = (ntohl(*hdr) & MPLS_BLS_MASK) >> 8;
// unsigned int mpls_ttl = (ntohl(*hdr) & MPLS_TTL_MASK);
uint16_t hdr_len = 4;
uint16_t hdr_offset = (uintptr_t)data - (uintptr_t)(handler->packet_data);
uint16_t payload_len = length - hdr_len;
const void *payload_data = (const char *)data + hdr_len;
if (packet_parser_push(handler, LAYER_TYPE_MPLS, hdr_offset, hdr_len, payload_len) != 0)
{
return data;
}
if (mpls_bls == 1)
{
uint8_t ip_version = (((uint8_t *)payload_data)[0]) >> 4;
if (ip_version == 0)
{
/*
* PW Ethernet Control Word
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |0 0 0 0| Reserved | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* Reference: https://tools.ietf.org/html/rfc4448
*/
payload_data = (const char *)payload_data + 4;
payload_len = payload_len - 4;
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS), payload_len, length);
return parse_ether(handler, payload_data, payload_len);
}
else if (ip_version == 4)
{
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS), payload_len, length);
// TESTED OK BY LWP
return parse_ipv4(handler, payload_data, payload_len);
}
else if (ip_version == 6)
{
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS), payload_len, length);
return parse_ipv6(handler, payload_data, payload_len);
}
else
{
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS), payload_len, length);
// TESTED OK BY LWP
return parse_ether(handler, payload_data, payload_len);
}
}
else
{
LOG_DEBUG("%s: trace id: %lu, layer: %s, payload len: [%u/%u]", LOG_PKT_PARSER, handler->packet_id, layer2str(LAYER_TYPE_MPLS), payload_len, length);
// TESTED OK BY LWP
return parse_mpls(handler, payload_data, payload_len);
}
}

View File

@@ -0,0 +1,23 @@
###############################################################################
# gtest_packet_parser
###############################################################################
add_executable(gtest_packet_parser gtest_packet_parser.cpp)
target_include_directories(gtest_packet_parser PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
target_link_libraries(gtest_packet_parser common gtest)
###############################################################################
# gtest_packet_inject
###############################################################################
add_executable(gtest_packet_inject gtest_packet_inject.cpp)
target_include_directories(gtest_packet_inject PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
target_link_libraries(gtest_packet_inject common gtest)
###############################################################################
# gtest_discover_tests
###############################################################################
include(GoogleTest)
gtest_discover_tests(gtest_packet_parser)
gtest_discover_tests(gtest_packet_inject)

View File

@@ -0,0 +1,178 @@
#include <gtest/gtest.h>
#include "packet_inject.h"
/******************************************************************************
* Pcap file: 2-ETH_IP6_IP4_TCP_SSH.pcap
* [Protocols in frame: eth:ethertype:ipv6:ip:tcp:ssh]
******************************************************************************
*
* Frame 1: 726 bytes on wire (5808 bits), 726 bytes captured (5808 bits)
* Ethernet II, Src: EvocInte_36:51:3c (00:22:46:36:51:3c), Dst: EvocInte_36:51:38 (00:22:46:36:51:38)
* Destination: EvocInte_36:51:38 (00:22:46:36:51:38)
* Source: EvocInte_36:51:3c (00:22:46:36:51:3c)
* Type: IPv6 (0x86dd)
* Internet Protocol Version 6, Src: 2001::192:168:40:134, Dst: 2001::192:168:40:133
* 0110 .... = Version: 6
* .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
* .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
* Payload Length: 672
* Next Header: IPIP (4)
* Hop Limit: 64
* Source Address: 2001::192:168:40:134
* Destination Address: 2001::192:168:40:133
* [Source Teredo Server IPv4: 0.0.0.0]
* [Source Teredo Port: 65175]
* [Source Teredo Client IPv4: 255.191.254.203]
* [Destination Teredo Server IPv4: 0.0.0.0]
* [Destination Teredo Port: 65175]
* [Destination Teredo Client IPv4: 255.191.254.204]
* Internet Protocol Version 4, Src: 1.1.1.1, Dst: 2.2.2.2
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* Total Length: 672
* Identification: 0x0968 (2408)
* 000. .... = Flags: 0x0
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 212
* Protocol: TCP (6)
* Header Checksum: 0xd4ea [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 1.1.1.1
* Destination Address: 2.2.2.2
* Transmission Control Protocol, Src Port: 57639, Dst Port: 22, Seq: 1, Ack: 1, Len: 632
* Source Port: 57639
* Destination Port: 22
* [Stream index: 0]
* [Conversation completeness: Incomplete (8)]
* [TCP Segment Len: 632]
* Sequence Number: 1 (relative sequence number)
* Sequence Number (raw): 1508621024
* [Next Sequence Number: 633 (relative sequence number)]
* Acknowledgment Number: 1 (relative ack number)
* Acknowledgment number (raw): 2828957019
* 0101 .... = Header Length: 20 bytes (5)
* Flags: 0x018 (PSH, ACK)
* Window: 28584
* [Calculated window size: 28584]
* [Window size scaling factor: -1 (unknown)]
* Checksum: 0xc51f [unverified]
* [Checksum Status: Unverified]
* Urgent Pointer: 0
* [Timestamps]
* [SEQ/ACK analysis]
* TCP payload (632 bytes)
* SSH Protocol
*/
unsigned char data2[] = {
0x00, 0x22, 0x46, 0x36, 0x51, 0x38, 0x00, 0x22, 0x46, 0x36, 0x51, 0x3c, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x04, 0x40, 0x20, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x01, 0x68, 0x00, 0x40, 0x01, 0x34, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x01, 0x68, 0x00, 0x40,
0x01, 0x33, 0x45, 0x00, 0x02, 0xa0, 0x09, 0x68, 0x00, 0x00, 0xd4, 0x06, 0xd4, 0xea, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0xe1, 0x27, 0x00, 0x16,
0x59, 0xeb, 0xba, 0xe0, 0xa8, 0x9e, 0x75, 0x5b, 0x50, 0x18, 0x6f, 0xa8, 0xc5, 0x1f, 0x00, 0x00, 0x4f, 0xe3, 0xa9, 0x48, 0x9b, 0xbe, 0xa8, 0x07, 0x0e, 0xbb,
0x5b, 0xf1, 0x15, 0x1d, 0xc9, 0xbe, 0xdf, 0x78, 0x89, 0xa2, 0x8f, 0x12, 0x5f, 0xad, 0x51, 0xd5, 0xfa, 0xa7, 0x0b, 0xf2, 0x34, 0x00, 0x5b, 0x77, 0xae, 0xab,
0xe4, 0x49, 0xa7, 0xa5, 0xa7, 0x1f, 0xda, 0x90, 0xcc, 0xe1, 0x8e, 0x9f, 0xe9, 0xee, 0x53, 0x59, 0xa4, 0x17, 0xf8, 0x0d, 0x40, 0xe5, 0x75, 0x97, 0xf0, 0x29,
0xfa, 0x7c, 0xb8, 0x12, 0x7e, 0x93, 0xbc, 0x7e, 0x0a, 0x69, 0x8f, 0x1d, 0x7b, 0x1a, 0x2e, 0xf6, 0xa6, 0x78, 0x67, 0x26, 0xfe, 0x8f, 0xcf, 0x5a, 0x02, 0x7d,
0xbb, 0x1b, 0xdb, 0xc7, 0x71, 0xee, 0xe9, 0xd9, 0xc1, 0x48, 0xbf, 0xc7, 0xcc, 0x00, 0x82, 0x7f, 0x69, 0x52, 0xa7, 0xe1, 0x12, 0xec, 0xf1, 0x93, 0xa8, 0x55,
0x5b, 0x33, 0xd3, 0x35, 0x11, 0x5d, 0xf8, 0x3d, 0x5b, 0x94, 0xc9, 0x67, 0xae, 0xba, 0xc0, 0x4a, 0x8b, 0x25, 0x8d, 0xbf, 0xd4, 0xcc, 0x24, 0xb7, 0x3d, 0x0f,
0x1a, 0x57, 0x20, 0x5c, 0x64, 0x62, 0xf7, 0x3c, 0xff, 0xaf, 0x6b, 0xf2, 0xf3, 0xca, 0xd1, 0xcb, 0x7b, 0x9f, 0xc1, 0x31, 0x25, 0x01, 0xd1, 0x18, 0x78, 0x81,
0xf8, 0xae, 0x61, 0x4b, 0x59, 0xa1, 0xbe, 0x4a, 0x94, 0x12, 0xa3, 0x05, 0x4a, 0x26, 0x85, 0xbd, 0x5e, 0x59, 0xb2, 0xc2, 0x24, 0xec, 0xd6, 0x94, 0x6e, 0xc5,
0x7a, 0xdf, 0x21, 0x21, 0xe4, 0x06, 0x67, 0x89, 0xe0, 0x76, 0x85, 0xa9, 0x00, 0x43, 0xfe, 0x72, 0x8c, 0x10, 0xe4, 0x96, 0x63, 0x1a, 0xe8, 0x84, 0xe1, 0x86,
0xa2, 0xa5, 0x67, 0x31, 0x67, 0x44, 0xca, 0xec, 0xe8, 0xa1, 0x3e, 0x5f, 0x4e, 0x71, 0x5d, 0xd4, 0x34, 0xa9, 0x3d, 0xfa, 0x6a, 0xdb, 0xfb, 0x28, 0x2b, 0x70,
0xcc, 0xf1, 0x3c, 0x7c, 0xf5, 0x39, 0xb5, 0xd0, 0xa2, 0x56, 0x22, 0x96, 0x7e, 0xc5, 0x0e, 0x66, 0x2d, 0xcd, 0x5c, 0x33, 0x43, 0x1c, 0xca, 0x17, 0x77, 0x46,
0xb2, 0x41, 0x06, 0x8a, 0x7c, 0x7c, 0x66, 0x06, 0x18, 0x33, 0x21, 0x16, 0x8f, 0x5a, 0xb7, 0xdd, 0x10, 0xa1, 0xab, 0xe9, 0x66, 0xf7, 0x90, 0x22, 0x2c, 0xbe,
0xdd, 0xad, 0xe1, 0x40, 0xe9, 0x21, 0x53, 0x97, 0x07, 0x97, 0x6b, 0xd6, 0x91, 0x11, 0x44, 0x4e, 0x9d, 0x1f, 0x57, 0x07, 0xed, 0xa2, 0xac, 0x77, 0xc0, 0x84,
0xb7, 0xc5, 0x2b, 0xaa, 0x17, 0xd2, 0xdb, 0x2a, 0x15, 0x47, 0x2b, 0x69, 0xf1, 0xb4, 0xb5, 0x8f, 0x98, 0xcf, 0x26, 0x03, 0xf0, 0x4b, 0x1a, 0xba, 0x94, 0xc4,
0x12, 0xe3, 0xd1, 0x38, 0x0c, 0x2e, 0x87, 0x33, 0x0f, 0xe1, 0xa6, 0xba, 0x75, 0xd0, 0xa4, 0x94, 0x80, 0x49, 0x67, 0xa8, 0x90, 0x31, 0x19, 0xaa, 0xf9, 0x78,
0x0d, 0xdd, 0x64, 0xe3, 0xc7, 0x0e, 0x81, 0xa7, 0x6b, 0x44, 0x0c, 0xb5, 0xa0, 0x25, 0x8a, 0xa2, 0xdc, 0x5e, 0xbc, 0xcd, 0xb4, 0x87, 0x1b, 0x6c, 0x08, 0x38,
0x63, 0xa8, 0xc1, 0xde, 0xe2, 0xa1, 0xa4, 0x19, 0x1e, 0x3c, 0x67, 0x3b, 0xf7, 0x7f, 0x67, 0xfb, 0x50, 0x9a, 0x06, 0x5c, 0xdd, 0xf2, 0x26, 0x2c, 0xb9, 0xd2,
0xbd, 0x80, 0xd5, 0xfc, 0xc5, 0x54, 0x6c, 0xc1, 0xea, 0x76, 0x3e, 0xd4, 0xbb, 0x57, 0x65, 0x6a, 0xf8, 0x8e, 0x3e, 0x93, 0xe5, 0x03, 0xfc, 0xce, 0xf1, 0x1c,
0xf3, 0x10, 0xae, 0x87, 0x78, 0x46, 0x02, 0x63, 0xc5, 0xc0, 0x41, 0xbd, 0xae, 0x46, 0x68, 0x0c, 0x92, 0x22, 0xa4, 0xc0, 0xce, 0xf3, 0xc4, 0xf7, 0x83, 0xa9,
0x22, 0x78, 0x74, 0x7f, 0x2e, 0xc1, 0xc6, 0x3b, 0x72, 0x26, 0x4b, 0x45, 0xbd, 0x1b, 0x9f, 0x66, 0x61, 0x46, 0xbb, 0x0f, 0xf3, 0xc5, 0x65, 0x95, 0xbc, 0xae,
0x8f, 0x37, 0xfd, 0xa3, 0x20, 0xb6, 0xe4, 0xa8, 0xff, 0x45, 0xa1, 0x01, 0xa1, 0x76, 0xb3, 0xad, 0x16, 0x07, 0x39, 0x58, 0x3b, 0x34, 0xe9, 0xe6, 0xc0, 0xee,
0x7f, 0x65, 0x6f, 0x68, 0xf4, 0x45, 0xa4, 0x85, 0xa7, 0x50, 0x63, 0xce, 0x0b, 0x0d, 0xbd, 0xd1, 0x20, 0xc8, 0x41, 0x37, 0x05, 0x1f, 0x81, 0xf3, 0x7c, 0xe7,
0x67, 0x15, 0xce, 0xad, 0x76, 0x95, 0x1a, 0x93, 0x4a, 0xab, 0xc4, 0xea, 0x30, 0x44, 0x13, 0x47, 0xec, 0x79, 0xa2, 0x41, 0x0c, 0xdd, 0x42, 0xdf, 0xbf, 0x02,
0xef, 0x9e, 0x67, 0x7e, 0x1e, 0xb0, 0x2a, 0x7f, 0x97, 0xf3, 0x5a, 0xbc, 0x21, 0x8d, 0xf9, 0xc3, 0x30, 0x45, 0xfe, 0x72, 0x74, 0x04, 0x53, 0x99, 0xe7, 0xd1,
0x2b, 0xb6, 0x3a, 0x9c, 0x84, 0x0e, 0x15, 0x5e, 0x75, 0x3b, 0xc9, 0x0e, 0x94, 0xe6, 0x48, 0x0e, 0x37, 0x07, 0xf8, 0xd9, 0x59, 0x4b, 0x04, 0x50};
TEST(PACKET_INJECT, ETH_IP6_IP4_TCP_SSH)
{
struct ip6_hdr *hdr = (struct ip6_hdr *)(data2 + 14);
EXPECT_TRUE(packet_inject_ipv6(&hdr->ip6_dst, (const char *)(data2 + 14), sizeof(data2) - 14) == 0);
}
/******************************************************************************
* Pcap file: 4-ETH_IP4_IP6_TCP.pcap
* [Protocols in frame: eth:ethertype:ip:ipv6:tcp]
******************************************************************************
*
* Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits)
* Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00)
* Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00)
* Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29)
* Type: IPv4 (0x0800)
* Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* Total Length: 92
* Identification: 0x0b4d (2893)
* 000. .... = Flags: 0x0
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 59
* Protocol: IPv6 (41)
* Header Checksum: 0x09c8 [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 210.77.88.163
* Destination Address: 59.66.4.50
* Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058
* 0110 .... = Version: 6
* .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
* .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
* Payload Length: 32
* Next Header: TCP (6)
* Hop Limit: 64
* Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3
* Destination Address: 2600:140e:6::1702:1058
* [Source ISATAP IPv4: 210.77.88.163]
* Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0
* Source Port: 52556
* Destination Port: 80
* [Stream index: 0]
* [Conversation completeness: Complete, WITH_DATA (31)]
* [TCP Segment Len: 0]
* Sequence Number: 0 (relative sequence number)
* Sequence Number (raw): 2172673142
* [Next Sequence Number: 1 (relative sequence number)]
* Acknowledgment Number: 0
* Acknowledgment number (raw): 0
* 1000 .... = Header Length: 32 bytes (8)
* Flags: 0x002 (SYN)
* Window: 8192
* [Calculated window size: 8192]
* Checksum: 0xf757 [unverified]
* [Checksum Status: Unverified]
* Urgent Pointer: 0
* Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted
* [Timestamps]
*/
unsigned char data4[] = {
0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8,
0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00,
0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50,
0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01,
0x04, 0x02};
TEST(PACKET_INJECT, ETH_IP4_IP6_TCP)
{
struct ip *hdr = (struct ip *)(data4 + 14);
EXPECT_TRUE(packet_inject_ipv4(&hdr->ip_dst, (const char *)(data4 + 14), sizeof(data4) - 14) == 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.