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,7 +1,7 @@
variables:
GIT_STRATEGY: "clone"
BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/
INSTALL_PREFIX: "/opt/tsg/packetadapter"
INSTALL_PREFIX: "/opt/tsg/packet_adapter"
TESTING_VERSION_BUILD: 0
BUILD_IMAGE_CENTOS7: "git.mesalab.cn:7443/mesa_platform/build-env:master"
BUILD_IMAGE_CENTOS8: "git.mesalab.cn:7443/mesa_platform/build-env:rockylinux"
@@ -60,7 +60,7 @@ develop_build_debug_for_centos7:
PULP3_REPO_NAME: tsg-testing-x86_64.el7
PULP3_DIST_NAME: tsg-testing-x86_64.el7
artifacts:
name: "packetadapter-develop-$CI_COMMIT_REF_NAME-debug"
name: "packet_adapter-develop-$CI_COMMIT_REF_NAME-debug"
paths:
- build/*.rpm
only:
@@ -79,7 +79,7 @@ develop_build_release_for_centos7:
PULP3_REPO_NAME: tsg-testing-x86_64.el7
PULP3_DIST_NAME: tsg-testing-x86_64.el7
artifacts:
name: "packetadapter-develop-$CI_COMMIT_REF_NAME-release"
name: "packet_adapter-develop-$CI_COMMIT_REF_NAME-release"
paths:
- build/*.rpm
only:
@@ -96,7 +96,7 @@ release_build_debug_for_centos7:
PULP3_DIST_NAME: tsg-stable-x86_64.el7
extends: .build_by_travis_for_centos7
artifacts:
name: "packetadapter-install-$CI_COMMIT_REF_NAME-debug"
name: "packet_adapter-install-$CI_COMMIT_REF_NAME-debug"
paths:
- build/*.rpm
only:
@@ -112,7 +112,7 @@ release_build_release_for_centos7:
PULP3_DIST_NAME: tsg-stable-x86_64.el7
extends: .build_by_travis_for_centos7
artifacts:
name: "packetadapter-install-$CI_COMMIT_REF_NAME-release"
name: "packet_adapter-install-$CI_COMMIT_REF_NAME-release"
paths:
- build/*.rpm
only:
@@ -169,7 +169,7 @@ develop_build_debug_for_centos8:
PULP3_REPO_NAME: tsg-testing-x86_64.el8
PULP3_DIST_NAME: tsg-testing-x86_64.el8
artifacts:
name: "packetadapter-develop-$CI_COMMIT_REF_NAME-debug"
name: "packet_adapter-develop-$CI_COMMIT_REF_NAME-debug"
paths:
- build/*.rpm
only:
@@ -188,7 +188,7 @@ develop_build_release_for_centos8:
PULP3_REPO_NAME: tsg-testing-x86_64.el8
PULP3_DIST_NAME: tsg-testing-x86_64.el8
artifacts:
name: "packetadapter-develop-$CI_COMMIT_REF_NAME-release"
name: "packet_adapter-develop-$CI_COMMIT_REF_NAME-release"
paths:
- build/*.rpm
only:
@@ -205,7 +205,7 @@ release_build_debug_for_centos8:
PULP3_DIST_NAME: tsg-stable-x86_64.el8
extends: .build_by_travis_for_centos8
artifacts:
name: "packetadapter-install-$CI_COMMIT_REF_NAME-debug"
name: "packet_adapter-install-$CI_COMMIT_REF_NAME-debug"
paths:
- build/*.rpm
only:
@@ -221,7 +221,7 @@ release_build_release_for_centos8:
PULP3_DIST_NAME: tsg-stable-x86_64.el8
extends: .build_by_travis_for_centos8
artifacts:
name: "packetadapter-install-$CI_COMMIT_REF_NAME-release"
name: "packet_adapter-install-$CI_COMMIT_REF_NAME-release"
paths:
- build/*.rpm
only:

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5)
project(packetadapter)
project(packet_adapter)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(Version)
@@ -14,7 +14,7 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set (CMAKE_INSTALL_PREFIX "/opt/tsg/packetadapter" CACHE PATH "default install path" FORCE )
set (CMAKE_INSTALL_PREFIX "/opt/tsg/packet_adapter" CACHE PATH "default install path" FORCE )
endif()
# Global compile options
@@ -58,6 +58,10 @@ add_custom_target("install-program" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Pr
add_custom_target("install-profile" COMMAND ${CMAKE_COMMAND} ARGS -DCOMPONENT=Profile -P cmake_install.cmake)
enable_testing()
add_subdirectory(conf)
add_subdirectory(vendor)
add_subdirectory(common)
add_subdirectory(platform)
add_subdirectory(script)
install(DIRECTORY DESTINATION log)

View File

@@ -65,8 +65,8 @@ ip6tables -F -t raw
# /usr/sbin/ip6tables -A OUTPUT -o eno2 -j LOG
# 启动服务
systemctl enable packetadapter
systemctl start packetadapter
systemctl enable packet_adapter
systemctl start packet_adapter
```
## TODO

View File

@@ -34,6 +34,14 @@ env | sort
# Install dependency from YUM
#yum install -y libmnl-devel libnfnetlink-devel
yum install -y mrzcpd numactl-devel
yum install -y libMESA_field_stat2-devel
yum install -y libMESA_handle_logger-devel
yum install -y libMESA_prof_load-devel
yum install -y libbreakpad_mini-devel
yum install -y libasan
yum install -y numactl-libs # required by mrzcpd
yum install -y libibverbs # required by mrzcpd
if [ $ASAN_OPTION ];then
source /opt/rh/devtoolset-7/enable
@@ -57,7 +65,7 @@ if [ -n "${PACKAGE}" ]; then
fi
if [ -n "${UPLOAD_SYMBOL_FILES}" ]; then
rpm -i packetadapter*debuginfo*.rpm
cp /usr/lib/debug/opt/tsg/packetadapter/bin/packetadapter*debug /tmp/packetadapter.debuginfo.${CI_COMMIT_SHORT_SHA}
sentry-cli upload-dif -t elf /tmp/packetadapter.debuginfo.${CI_COMMIT_SHORT_SHA}
rpm -i packet_adapter*debuginfo*.rpm
cp /usr/lib/debug/opt/tsg/packet_adapter/bin/packet_adapter*debug /tmp/packet_adapter.debuginfo.${CI_COMMIT_SHORT_SHA}
sentry-cli upload-dif -t elf /tmp/packet_adapter.debuginfo.${CI_COMMIT_SHORT_SHA}
fi

View File

@@ -1,7 +1,7 @@
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CPACK_PACKAGE_NAME "packetadapter-debug")
set(CPACK_PACKAGE_NAME "packet_adapter-debug")
else()
set(CPACK_PACKAGE_NAME "packetadapter")
set(CPACK_PACKAGE_NAME "packet_adapter")
endif()
message(STATUS "Package: ${CPACK_PACKAGE_NAME}")
@@ -25,9 +25,9 @@ set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/cmake/PreUninstall.i
# Must uninstall the debug package before install release package
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CPACK_RPM_PACKAGE_CONFLICTS "packetadapter")
set(CPACK_RPM_PACKAGE_CONFLICTS "packet_adapter")
else()
set(CPACK_RPM_PACKAGE_CONFLICTS "packetadapter-debug")
set(CPACK_RPM_PACKAGE_CONFLICTS "packet_adapter-debug")
endif()
include(CPack)

View File

@@ -1,2 +1,2 @@
%systemd_post packetadapter.service
%systemd_post packet_adapter.service
/sbin/ldconfig

View File

@@ -1,2 +1,2 @@
%systemd_postun_with_restart packetadapter.service
%systemd_postun_with_restart packet_adapter.service
/sbin/ldconfig

View File

@@ -1 +1 @@
%systemd_preun packetadapter.service
%systemd_preun packet_adapter.service

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.

2
conf/CMakeLists.txt Normal file
View File

@@ -0,0 +1,2 @@
install(FILES packet_adapter.conf DESTINATION conf COMPONENT Profile)
install(FILES zlog.conf DESTINATION conf COMPONENT Profile)

18
conf/packet_adapter.conf Normal file
View File

@@ -0,0 +1,18 @@
[packet_io]
thread_num=8
cpu_mask=2,3,4-9
rx_burst_max=128
bypass_traffic=0
app_symbol=packet_adapter
app_device=eth_nf_packet_adapter
[stat]
output_file=log/packet_adapter.fs2
statsd_server=127.0.0.1
statsd_port=8100
# 1 : FS_OUTPUT_STATSD
# 2 : FS_OUTPUT_INFLUX_LINE
statsd_format=1
statsd_cycle=2
prometheus_listen_port=9001
prometheus_listen_url=/packet_adapter_prometheus

12
conf/zlog.conf Normal file
View File

@@ -0,0 +1,12 @@
# kill -s SIGHUP "pid"
[global]
default format = "%d(%c), %t, %V, %F, %U, %m%n"
[levels]
DEBUG=10
INFO=20
FATAL=30
[rules]
packet_adapter.fatal "./log/packet_adapter.log.%d(%F)";

View File

@@ -1,10 +1,16 @@
find_package(NFNETLINK REQUIRED)
add_executable(packetadapter src/inject_pkt.c src/system.c src/packet_adapter.c)
add_executable(packet_adapter
src/system.cpp
src/packet_stat.cpp
src/packet_handle.cpp
src/packet_adapter.cpp)
target_include_directories(packetadapter PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/)
target_include_directories(packet_adapter PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/)
target_link_libraries(packetadapter common)
target_link_libraries(packetadapter netfilter_queue)
target_link_libraries(packet_adapter common)
target_link_libraries(packet_adapter pthread)
target_link_libraries(packet_adapter MESA_field_stat)
install(TARGETS packetadapter RUNTIME DESTINATION bin COMPONENT Program)
install(TARGETS packet_adapter RUNTIME DESTINATION bin COMPONENT Program)
add_subdirectory(test)

View File

@@ -1,18 +0,0 @@
#ifndef _INJECT_PKT_H
#define _INJECT_PKT_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "public.h"
int inject_ipv4_pkt(char *ip4_addr, uint8_t *data, uint32_t len);
int inject_ipv6_pkt(char *ip6_addr, uint8_t *data, uint32_t len);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -0,0 +1,17 @@
#ifndef _PACKET_HANDLE_H
#define _PACKET_HANDLE_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include "utils.h"
void packet_handle(const char *data, int len, struct metrics *metrics);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -0,0 +1,20 @@
#ifndef _PACKET_STAT_H
#define _PACKET_STAT_H
#ifdef __cpluscplus
extern "C"
{
#endif
struct packet_stat;
struct packet_stat *packet_stat_create(const char *profile);
void packet_stat_destory(struct packet_stat *handle);
void packet_stat_output(struct packet_stat *handle, struct metrics *metrics);
int packet_stat_cycle(struct packet_stat *handle);
#ifdef __cpluscplus
}
#endif
#endif

View File

@@ -6,9 +6,7 @@ extern "C"
{
#endif
#include "public.h"
int run_daemon(void);
int run_daemon(void);
#ifdef __cpluscplus
}

View File

@@ -1,53 +0,0 @@
#include "inject_pkt.h"
int inject_ipv4_pkt(char *ip4_addr, uint8_t *data, uint32_t len)
{
int fd = 0;
struct sockaddr_in saddr4 = {0};
saddr4.sin_family = PF_INET;
saddr4.sin_addr.s_addr = inet_addr(ip4_addr);
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)
{
LOG_ERROR("Failed at send(), %d: %s", errno, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}
int inject_ipv6_pkt(char *ip6_addr, uint8_t *data, uint32_t len)
{
int fd = 0;
struct sockaddr_in6 saddr6 = {0};
saddr6.sin6_family = PF_INET6;
inet_pton(AF_INET6, ip6_addr, &saddr6.sin6_addr);
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)
{
LOG_ERROR("Failed at send(), %d: %s", errno, strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}

View File

@@ -1,506 +0,0 @@
#include "decode_ipv4.h"
#include "decode_ipv6.h"
#include "decode_tcp.h"
#include "decode_udp.h"
#include "decode_gtp.h"
#include "inject_pkt.h"
#include "system.h"
#include <linux/netfilter.h> // for NF_ACCEPT
#include <libnetfilter_queue/libnetfilter_queue.h>
#ifdef GIT_VERSION
static __attribute__((__used__)) const char *Packet_Adapter_Version = GIT_VERSION;
#else
static __attribute__((__used__)) const char *Packet_Adapter_Version = "Unknown";
#endif
typedef struct pkt_info_s
{
uint32_t id; // unique ID of packet in queue
uint16_t protocol; // hw protocol
uint8_t hook; // netfilter hook
u_int32_t mark;
u_int32_t indev;
u_int32_t outdev;
u_int32_t phys_indev;
u_int32_t phys_outdev;
uint8_t *payload;
uint32_t payload_len;
char src_addr[512];
} pkt_info_t;
typedef struct union_info_s
{
ipv4_info_t ipv4;
ipv6_info_t ipv6;
tcp_info_t tcp;
udp_info_t udp;
} union_info_t;
typedef struct pkt_paser_s
{
pkt_info_t raw;
union_info_t external;
gtp_info_t gtp;
union_info_t internal;
} pkt_paser_t;
static int is_dump_packet_info = 0;
static void dump_info(pkt_paser_t *parser)
{
char buff[4096] = {0};
size_t size = sizeof(buff);
size_t len = 0;
len += snprintf(buff + len, size - len, "{");
len += snprintf(buff + len, size - len,
"\"raw_info\":{\"id\":%u,\"protocol\":%u,\"hook\":%u,\"mark\":%u,\"indev\":%u,\"outdev\":%u,\"phys_indev\":%u,\"phys_outdev\":%u,\"src_addr\":\"%s\",\"data_len\":%u}",
parser->raw.id,
parser->raw.protocol,
parser->raw.hook,
parser->raw.mark,
parser->raw.indev,
parser->raw.outdev,
parser->raw.phys_indev,
parser->raw.phys_outdev,
parser->raw.src_addr,
parser->raw.payload_len);
// external
if (parser->external.ipv4.hdr)
{
len += snprintf(buff + len, size - len, ",\"external_ipv4\":");
len += dump_ipv4_info(&(parser->external.ipv4), buff + len, size - len);
}
if (parser->external.ipv6.hdr)
{
len += snprintf(buff + len, size - len, ",\"external_ipv6\":");
len += dump_ipv6_info(&(parser->external.ipv6), buff + len, size - len);
}
if (parser->external.udp.hdr)
{
len += snprintf(buff + len, size - len, ",\"external_udp\":");
len += dump_udp_info(&(parser->external.udp), buff + len, size - len);
}
if (parser->external.tcp.hdr)
{
len += snprintf(buff + len, size - len, ",\"external_tcp\":");
len += dump_tcp_info(&(parser->external.tcp), buff + len, size - len);
}
// gtp
if (parser->gtp.hdr)
{
len += snprintf(buff + len, size - len, ",\"gtp\":");
len += dump_gtp_info(&(parser->gtp), buff + len, size - len);
}
// internal
if (parser->internal.ipv4.hdr)
{
len += snprintf(buff + len, size - len, ",\"internal_ipv4\":");
len += dump_ipv4_info(&(parser->internal.ipv4), buff + len, size - len);
}
if (parser->internal.ipv6.hdr)
{
len += snprintf(buff + len, size - len, ",\"internal_ipv6\":");
len += dump_ipv6_info(&(parser->internal.ipv6), buff + len, size - len);
}
if (parser->internal.udp.hdr)
{
len += snprintf(buff + len, size - len, ",\"internal_udp\":");
len += dump_udp_info(&(parser->internal.udp), buff + len, size - len);
}
if (parser->internal.tcp.hdr)
{
len += snprintf(buff + len, size - len, ",\"internal_tcp\":");
len += dump_tcp_info(&(parser->internal.tcp), buff + len, size - len);
}
len += snprintf(buff + len, size - len, "}");
LOG_DEBUG("%s", buff);
}
static int decode_ip_tcp_udp(union_info_t *parser, const uint8_t *data, uint32_t len)
{
int next_protocol = 0;
uint8_t *payload = NULL;
uint32_t payload_len = 0;
if (len < IPV4_HEADER_LEN)
{
LOG_ERROR("Parser IP header: packet length too small %d", len);
return -1;
}
if (IP_GET_RAW_VER(data) == 4)
{
if (decode_ipv4(&(parser->ipv4), data, len) == -1)
{
return -1;
}
payload = parser->ipv4.payload;
payload_len = parser->ipv4.payload_len;
next_protocol = parser->ipv4.next_protocol;
}
else if (IP_GET_RAW_VER(data) == 6)
{
if (decode_ipv6(&(parser->ipv6), data, len) == -1)
{
return -1;
}
payload = parser->ipv6.payload;
payload_len = parser->ipv6.payload_len;
next_protocol = parser->ipv6.next_protocol;
}
else
{
LOG_ERROR("Unknown IP version %d", IP_GET_RAW_VER(data));
return -1;
}
if (next_protocol == IPPROTO_UDP)
{
if (decode_udp(&(parser->udp), payload, payload_len) == -1)
{
return -1;
}
return 0;
}
else if (next_protocol == IPPROTO_TCP)
{
if (decode_tcp(&(parser->tcp), payload, payload_len) == -1)
{
return -1;
}
return 0;
}
else
{
LOG_ERROR("Unknown Internal L4 next_protocol version %d", next_protocol);
return -1;
}
}
///////////////////////////////////////////////////////////////////////////////
// NFQ API
///////////////////////////////////////////////////////////////////////////////
static int decode_pkt(pkt_info_t *packet, struct nfgenmsg *nfmsg, struct nfq_data *nfa)
{
struct nfqnl_msg_packet_hdr *packet_hdr = NULL;
struct nfqnl_msg_packet_hw *packet_hw = NULL;
packet_hdr = nfq_get_msg_packet_hdr(nfa);
if (packet_hdr == NULL)
{
LOG_ERROR("Failed at nfq_get_msg_packet_hdr()");
return 0;
}
packet->id = ntohl(packet_hdr->packet_id);
packet->payload_len = nfq_get_payload(nfa, &packet->payload);
if (packet->payload_len <= 0)
{
LOG_ERROR("Failed at nfq_get_payload()");
return packet->id;
}
packet->protocol = ntohs(packet_hdr->hw_protocol);
packet->hook = packet_hdr->hook;
packet_hw = nfq_get_packet_hw(nfa);
if (packet_hw)
{
int i = 0;
int offset = 0;
int len = sizeof(packet->src_addr);
int hlen = ntohs(packet_hw->hw_addrlen);
for (i = 0; i < hlen - 1; i++)
{
offset += snprintf(packet->src_addr + offset, len - offset, "%02x:", packet_hw->hw_addr[i]);
}
snprintf(packet->src_addr + offset, len - offset, "%02x", packet_hw->hw_addr[hlen - 1]);
}
packet->mark = nfq_get_nfmark(nfa);
packet->indev = nfq_get_indev(nfa);
packet->outdev = nfq_get_outdev(nfa);
packet->phys_indev = nfq_get_physindev(nfa);
packet->phys_outdev = nfq_get_physoutdev(nfa);
return packet->id;
}
/*
* nfmsg : message objetc that contains the packet
* nfa : Netlink packet data handle
*/
static int packet_handler_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)
{
int offest = 0;
pkt_paser_t parser = {0};
int packet_id = decode_pkt(&(parser.raw), nfmsg, nfa);
// external
if (decode_ip_tcp_udp(&(parser.external), parser.raw.payload, parser.raw.payload_len) == -1)
{
goto end;
}
if (parser.external.udp.hdr == NULL)
{
LOG_ERROR("External L4 protocol not UDP");
goto end;
}
// decode GTP
if (decode_gtp(&(parser.gtp), parser.external.udp.payload, parser.external.udp.payload_len) == -1)
{
return -1;
}
// internal
if (decode_ip_tcp_udp(&(parser.internal), parser.gtp.payload, parser.gtp.payload_len) == -1)
{
goto end;
}
/*
* NF_DROP : discarded the packet
* NF_ACCEPT : the packet passes, continue iterations
* NF_QUEUE : inject the packet into a different queue (the target queue number is in the high 16 bits of the verdict)
* NF_REPEAT : iterate the same cycle once more
* NF_STOP : accept, but don't continue iterations
*/
// nfq_set_verdict()
// nfq_set_verdict2()
// nfq_set_verdict_batch()
// nfq_set_verdict_batch2()
// nfq_set_verdict_mark()
if (parser.external.ipv4.hdr)
{
offest += parser.external.ipv4.hdr_len;
}
if (parser.external.ipv6.hdr)
{
offest += parser.external.ipv6.hdr_len;
}
offest += parser.external.udp.hdr_len;
offest += parser.gtp.hdr_len;
if (is_dump_packet_info)
{
dump_info(&parser);
LOG_DEBUG("Offset : %d", offest);
}
uint8_t *inject_data = parser.raw.payload + offest;
uint32_t inject_data_len = parser.raw.payload_len - offest;
if (offest > 0)
{
if ((parser.external.ipv4.hdr && parser.internal.ipv4.hdr) || (parser.external.ipv6.hdr && parser.internal.ipv6.hdr))
{
return nfq_set_verdict(qh, packet_id, NF_ACCEPT, inject_data_len, inject_data);
}
if (parser.external.ipv4.hdr && parser.internal.ipv6.hdr)
{
if (inject_ipv6_pkt(parser.internal.ipv6.dst_addr, inject_data, inject_data_len) == -1)
{
goto end;
}
return nfq_set_verdict(qh, packet_id, NF_DROP, 0, NULL);
}
if (parser.external.ipv6.hdr && parser.internal.ipv4.hdr)
{
if (inject_ipv4_pkt(parser.internal.ipv4.dst_addr, inject_data, inject_data_len) == -1)
{
goto end;
}
return nfq_set_verdict(qh, packet_id, NF_DROP, 0, NULL);
}
}
end:
return nfq_set_verdict(qh, packet_id, NF_ACCEPT, 0, NULL);
}
static void sig_handler(int signo)
{
if (signo == SIGUSR1)
{
is_dump_packet_info = 1;
LOG_ERROR("received SIGUSR1, enable dump packet info");
}
if (signo == SIGUSR2)
{
is_dump_packet_info = 0;
LOG_ERROR("received SIGUSR2, disable dump packet info");
}
}
static void usage(char *cmd)
{
fprintf(stderr, "USAGE: %s [OPTIONS]\n", cmd);
fprintf(stderr, " -v -- show version\n");
fprintf(stderr, " -i id -- set queue id\n");
fprintf(stderr, " -d -- run daemon\n");
fprintf(stderr, " -p -- dump packet info\n");
fprintf(stderr, " -h -- show help\n");
fprintf(stderr, "Signal: \n");
fprintf(stderr, " kill -s SIGUSR1 `pidof %s` -- enable dump packet info\n", cmd);
fprintf(stderr, " kill -s SIGUSR2 `pidof %s` -- disable dump packet info\n", cmd);
}
/*
* doc : http://www.netfilter.org/projects/libnetfilter_queue/doxygen/html/
* Library setup : http://www.netfilter.org/projects/libnetfilter_queue/doxygen/html/group__LibrarySetup.html
* Queue handling : http://www.netfilter.org/projects/libnetfilter_queue/doxygen/html/group__Queue.html
* Message parsing : http://www.netfilter.org/projects/libnetfilter_queue/doxygen/html/group__Parsing.html
*/
int main(int argc, char **argv)
{
int fd;
int rv;
int opt;
uint16_t queue = 1;
struct nfq_handle *handle = NULL;
struct nfq_q_handle *q_handle = NULL;
char buf[65535] __attribute__((aligned));
is_dump_packet_info = 0;
while ((opt = getopt(argc, argv, "vi:dph")) != -1)
{
switch (opt)
{
case 'v':
fprintf(stderr, "Packet Adapter Version: %s\n", Packet_Adapter_Version);
return 0;
case 'i':
queue = atoi(optarg);
if (queue < 0 || queue > 65535)
{
fprintf(stderr, "Usage: %s queueid %d out of range [0, 65535]\n", argv[0], queue);
return 0;
}
break;
case 'd':
run_daemon();
break;
case 'p':
is_dump_packet_info = 1;
break;
case 'h': /* fall through */
default:
usage(argv[0]);
return 0;
}
}
LOG_DEBUG("Using queue: %d", queue);
if (signal(SIGUSR1, sig_handler) == SIG_ERR)
{
LOG_ERROR("Failed at signal(SIGUSR1), %d: %s", errno, strerror(errno));
goto error;
}
if (signal(SIGUSR2, sig_handler) == SIG_ERR)
{
LOG_ERROR("Failed at signal(SIGUSR2), %d: %s", errno, strerror(errno));
goto error;
}
handle = nfq_open();
if (handle == NULL)
{
LOG_ERROR("Failed at nfq_open(), %d: %s", errno, strerror(errno));
goto error;
}
if (nfq_unbind_pf(handle, AF_INET) < 0)
{
LOG_ERROR("Failed at nfq_unbind_pf(), %d: %s", errno, strerror(errno));
goto error;
}
if (nfq_bind_pf(handle, AF_INET) < 0)
{
LOG_ERROR("Failed at nfq_bind_pf(), %d: %s", errno, strerror(errno));
goto error;
}
q_handle = nfq_create_queue(handle, queue, &packet_handler_cb, NULL);
if (q_handle == NULL)
{
LOG_ERROR("Failed at nfq_create_queue(), %d: %s", errno, strerror(errno));
goto error;
}
/*
* NFQNL_COPY_NONE - noop, do not use it
* NFQNL_COPY_META - copy only packet metadata
* NFQNL_COPY_PACKET - copy entire packet
*/
if (nfq_set_mode(q_handle, NFQNL_COPY_PACKET, 0xffff) < 0)
{
LOG_ERROR("Failed at nfq_set_mode(NFQNL_COPY_PACKET), %d: %s", errno, strerror(errno));
goto error;
}
if (nfq_set_queue_maxlen(q_handle, 65535) < 0)
{
LOG_ERROR("Failed at nfq_set_queue_maxlen(65535), %d: %s", errno, strerror(errno));
goto error;
}
LOG_DEBUG("Waiting for packets...");
fd = nfq_fd(handle);
for (;;)
{
if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0)
{
nfq_handle_packet(handle, buf, rv);
continue;
}
/*
* if your application is too slow to digest the packets that
* are sent from kernel-space, the socket buffer that we use
* to enqueue packets may fill up returning ENOBUFS. Depending
* on your application, this error may be ignored. Please, see
* the doxygen documentation of this library on how to improve
* this situation.
*/
if (rv < 0 && errno == ENOBUFS)
{
LOG_ERROR("Losing packets !!!");
continue;
}
LOG_ERROR("Failed at recv(), %d: %s", errno, strerror(errno));
}
error:
if (q_handle)
{
nfq_destroy_queue(q_handle);
}
if (handle)
{
nfq_close(handle);
}
return 0;
}

View File

@@ -0,0 +1,240 @@
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
#include "log.h"
#include "system.h"
#include "packet_io.h"
#include "packet_stat.h"
#include "packet_handle.h"
#define LOG_MAIN "PacketAdapter"
#ifdef GIT_VERSION
static __attribute__((__used__)) const char *Packet_Adapter_Version = GIT_VERSION;
#else
static __attribute__((__used__)) const char *Packet_Adapter_Version = "Unknown";
#endif
/******************************************************************************
* Struct
******************************************************************************/
struct thread
{
int index;
pthread_t tid;
struct runtime_ctx *runtime;
};
struct runtime_ctx
{
int enable_debug;
int need_stop;
struct metrics metrics;
struct packet_io *handle;
struct packet_stat *stat;
struct thread threads[MAX_THREAD_NUM];
};
/******************************************************************************
* Static
******************************************************************************/
struct runtime_ctx static_runtime_ctx = {0};
struct runtime_ctx *runtime = &static_runtime_ctx;
/******************************************************************************
* API
******************************************************************************/
static enum action packet_handle_callback(const char *data, int len, void *args)
{
struct metrics *metrics = (struct metrics *)args;
packet_handle(data, len, metrics);
return ACTION_BYPASS;
}
static void *worker_thread_cycle(void *arg)
{
struct thread *thread = (struct thread *)arg;
struct runtime_ctx *runtime = thread->runtime;
struct packet_io *handle = runtime->handle;
char thread_name[16];
snprintf(thread_name, sizeof(thread_name), "pkt-adapter:%d", thread->index);
prctl(PR_SET_NAME, (unsigned long long)thread_name, NULL, NULL, NULL);
if (packet_io_thread_init(handle, thread->index) != 0)
{
goto error_out;
}
LOG_INFO("%s: worker thread %d is running", LOG_MAIN, thread->index);
while (!runtime->need_stop)
{
if (packet_io_thread_polling(handle, thread->index) == 0)
{
packet_io_thread_wait(handle, thread->index, -1);
}
}
error_out:
LOG_ERROR("%s: worker thread %d exiting", LOG_MAIN, thread->index);
return (void *)NULL;
}
static void signal_handler(int signo)
{
if (signo == SIGUSR1)
{
runtime->enable_debug = 1;
LOG_ERROR("%s: received SIGUSR1, enable debug", LOG_MAIN);
}
if (signo == SIGUSR2)
{
runtime->enable_debug = 0;
LOG_ERROR("%s: received SIGUSR2, disable debug", LOG_MAIN);
}
if (signo == SIGHUP)
{
LOG_RELOAD();
LOG_ERROR("%s: received SIGHUP, reload zlog.conf", LOG_MAIN);
}
if (signo == SIGINT)
{
runtime->need_stop = 1;
LOG_ERROR("%s: received SIGINT, exit !!!", LOG_MAIN);
}
if (signo == SIGQUIT)
{
runtime->need_stop = 1;
LOG_ERROR("%s: received SIGQUIT, exit !!!", LOG_MAIN);
}
if (signo == SIGTERM)
{
runtime->need_stop = 1;
LOG_ERROR("%s: received SIGTERM, exit !!!", LOG_MAIN);
}
}
static void usage(char *cmd)
{
fprintf(stderr, "USAGE: %s [OPTIONS]\n", cmd);
fprintf(stderr, " -v -- show version\n");
fprintf(stderr, " -d -- run daemon\n");
fprintf(stderr, " -h -- show help\n");
fprintf(stderr, "Signal: \n");
fprintf(stderr, " kill -s SIGUSR1 `pidof %s` -- enable debug\n", cmd);
fprintf(stderr, " kill -s SIGUSR2 `pidof %s` -- disable debug\n", cmd);
}
int main(int argc, char **argv)
{
int opt;
const char *profile = "./conf/packet_adapter.conf";
if (LOG_INIT("./conf/zlog.conf") == -1)
{
return -1;
}
while ((opt = getopt(argc, argv, "vdh")) != -1)
{
switch (opt)
{
case 'v':
fprintf(stderr, "Packet Adapter Version: %s\n", Packet_Adapter_Version);
return 0;
case 'd':
run_daemon();
break;
case 'h': /* fall through */
default:
usage(argv[0]);
return 0;
}
}
LOG_ERROR("%s: TSG Packet Adapter Engine, Version: %s Start ...", LOG_MAIN, Packet_Adapter_Version);
if (signal(SIGUSR1, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGUSR1), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
if (signal(SIGUSR2, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGUSR2), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
if (signal(SIGHUP, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGHUP), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
if (signal(SIGINT, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGINT), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
if (signal(SIGQUIT, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGQUIT), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
if (signal(SIGTERM, signal_handler) == SIG_ERR)
{
LOG_ERROR("%s: failed at signal(SIGTERM), %d: %s", LOG_MAIN, errno, strerror(errno));
goto error;
}
runtime->stat = packet_stat_create(profile);
if (runtime->stat == NULL)
{
goto error;
}
runtime->handle = packet_io_create(profile);
if (runtime->handle == NULL)
{
goto error;
}
packet_io_set_callback(runtime->handle, packet_handle_callback, &runtime->metrics);
for (int i = 0; i < packet_io_thread_number(runtime->handle); i++)
{
runtime->threads[i].tid = 0;
runtime->threads[i].index = i;
runtime->threads[i].runtime = runtime;
}
for (int i = 0; i < packet_io_thread_number(runtime->handle); i++)
{
struct thread *thread = &runtime->threads[i];
if (pthread_create(&thread->tid, NULL, worker_thread_cycle, (void *)thread) < 0)
{
LOG_ERROR("%s: unable to create worker thread %d, error %d: %s", LOG_MAIN, i, errno, strerror(errno));
runtime->need_stop = 1;
}
}
while (!runtime->need_stop)
{
packet_stat_output(runtime->stat, &runtime->metrics);
sleep(packet_stat_cycle(runtime->stat));
}
error:
packet_stat_destory(runtime->stat);
packet_io_destory(runtime->handle);
LOG_CLOSE();
return 0;
}

View File

@@ -0,0 +1,145 @@
#include <stddef.h>
#include "packet_parser.h"
#include "packet_inject.h"
#include "packet_handle.h"
static void packet_inject(int next_proto, const char *data, int len, struct metrics *metrics)
{
if (next_proto == 4)
{
struct ip *hdr = (struct ip *)data;
if (packet_inject_ipv4(&hdr->ip_dst, data, len) == 0)
{
ATOMIC_ADD(&metrics->succ_tx_v4_pkts, 1);
ATOMIC_ADD(&metrics->succ_tx_v4_bytes, len);
}
else
{
ATOMIC_ADD(&metrics->err_tx_v4_pkts, 1);
ATOMIC_ADD(&metrics->err_tx_v4_bytes, len);
}
}
if (next_proto == 6)
{
struct ip6_hdr *hdr = (struct ip6_hdr *)data;
if (packet_inject_ipv6(&hdr->ip6_dst, data, len) == 0)
{
ATOMIC_ADD(&metrics->succ_tx_v6_pkts, 1);
ATOMIC_ADD(&metrics->succ_tx_v6_bytes, len);
}
else
{
ATOMIC_ADD(&metrics->err_tx_v6_pkts, 1);
ATOMIC_ADD(&metrics->err_tx_v6_bytes, len);
}
}
}
static void packet_handle_error(struct metrics *metrics, int n_pkts, int n_bytes)
{
ATOMIC_ADD(&metrics->rx_err_pkts, n_pkts);
ATOMIC_ADD(&metrics->rx_err_bytes, n_bytes);
}
// return 1: is gtp
// return 0: not gtp
static int packet_handle_gtp(struct packet_parser *handler, struct metrics *metrics)
{
const struct layer_record *gtp_layer = packet_parser_get_most_outer(handler, LAYER_TYPE_GTPV1_U);
if (gtp_layer == NULL)
{
return 0;
}
if (gtp_layer->hdr_offset + gtp_layer->hdr_len >= handler->packet_len)
{
packet_handle_error(metrics, 1, handler->packet_len);
return 1;
}
const char *inject_data = (const char *)handler->packet_data + gtp_layer->hdr_offset + gtp_layer->hdr_len;
int inject_len = gtp_layer->pld_len;
uint8_t next_proto = gtp_next_proto((const char *)handler->packet_data + gtp_layer->hdr_offset);
if (next_proto != 4 && next_proto != 6)
{
packet_handle_error(metrics, 1, handler->packet_len);
return 1;
}
else
{
packet_inject(next_proto, inject_data, inject_len, metrics);
return 1;
}
}
// return 1: is l3
// return 0: not l3
static int packet_handle_l3(struct packet_parser *handler, struct metrics *metrics)
{
const struct layer_record *l3_layer = packet_parser_get_most_outer(handler, LAYER_TYPE_L3);
if (l3_layer == NULL)
{
return 0;
}
if (l3_layer->hdr_offset >= handler->packet_len)
{
packet_handle_error(metrics, 1, handler->packet_len);
return 1;
}
const char *inject_data = (const char *)handler->packet_data + l3_layer->hdr_offset;
int inject_len = l3_layer->hdr_len + l3_layer->pld_len;
uint8_t next_proto = 0;
if (l3_layer->type == LAYER_TYPE_IPV4)
{
next_proto = 4;
}
else if (l3_layer->type == LAYER_TYPE_IPV6)
{
next_proto = 6;
}
else
{
packet_handle_error(metrics, 1, handler->packet_len);
return 1;
}
packet_inject(next_proto, inject_data, inject_len, metrics);
return 1;
}
void packet_handle(const char *data, int len, struct metrics *metrics)
{
ATOMIC_ADD(&metrics->rx_pkts, 1);
ATOMIC_ADD(&metrics->rx_bytes, len);
if (data == NULL || len <= 0)
{
packet_handle_error(metrics, 1, len);
return;
}
struct packet_parser handler;
uint64_t packet_id = ATOMIC_READ(&metrics->rx_pkts);
packet_parser_init(&handler);
packet_parser_parse(&handler, data, len, packet_id);
// Handle GTP
if (packet_handle_gtp(&handler, metrics) == 1)
{
return;
}
// Handle L3
if (packet_handle_l3(&handler, metrics) == 1)
{
return;
}
packet_handle_error(metrics, 1, len);
}

View File

@@ -0,0 +1,181 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <MESA/field_stat2.h>
#include <MESA/MESA_prof_load.h>
#include "log.h"
#include "utils.h"
enum STAT_FIELD
{
STAT_RX_PKT,
STAT_RX_B,
STAT_RX_ERR_PKT,
STAT_RX_ERR_B,
STAT_SUCC_TX_V4_PKT,
STAT_SUCC_TX_V4_B,
STAT_SUCC_TX_V6_PKT,
STAT_SUCC_TX_V6_B,
STAT_ERR_TX_V4_PKT,
STAT_ERR_TX_V4_B,
STAT_ERR_TX_V6_PKT,
STAT_ERR_TX_V6_B,
STAT_MAX,
};
static const char *stat_map[] =
{
[STAT_RX_PKT] = "nf_rx_pkt",
[STAT_RX_B] = "nf_rx_B",
[STAT_RX_ERR_PKT] = "rx_err_pkt",
[STAT_RX_ERR_B] = "rx_err_B",
[STAT_SUCC_TX_V4_PKT] = "succ_tx_4_pkt",
[STAT_SUCC_TX_V4_B] = "succ_tx_4_B",
[STAT_SUCC_TX_V6_PKT] = "succ_tx_6_pkt",
[STAT_SUCC_TX_V6_B] = "succ_tx_6_B",
[STAT_ERR_TX_V4_PKT] = "err_tx_4_pkt",
[STAT_ERR_TX_V4_B] = "err_tx_4_B",
[STAT_ERR_TX_V6_PKT] = "err_tx_6_pkt",
[STAT_ERR_TX_V6_B] = "err_tx_6_B",
[STAT_MAX] = NULL};
struct stat_config
{
char output_file[256];
char statsd_server[32];
int statsd_port;
int statsd_format;
int statsd_cycle;
int prometheus_listen_port;
char prometheus_listen_url[256];
};
struct packet_stat
{
struct stat_config config;
screen_stat_handle_t fs_handle;
int fs_id[512];
};
static void packet_stat_config(const char *profile, struct stat_config *config)
{
MESA_load_profile_string_def(profile, "STAT", "output_file", config->output_file, sizeof(config->output_file), "log/packet_adapter.fs2");
MESA_load_profile_string_def(profile, "STAT", "statsd_server", config->statsd_server, sizeof(config->statsd_server), "127.0.0.1");
MESA_load_profile_int_def(profile, "STAT", "statsd_port", &(config->statsd_port), 8100);
MESA_load_profile_int_def(profile, "STAT", "statsd_format", &(config->statsd_format), 1); // FS_OUTPUT_STATSD=1, FS_OUTPUT_INFLUX_LINE=2
MESA_load_profile_int_def(profile, "STAT", "statsd_cycle", &(config->statsd_cycle), 1);
MESA_load_profile_int_def(profile, "STAT", "prometheus_listen_port", &(config->prometheus_listen_port), 9001);
MESA_load_profile_string_def(profile, "STAT", "prometheus_listen_url", config->prometheus_listen_url, sizeof(config->prometheus_listen_url), "/packet_prometheus");
if (config->statsd_format != 1 && config->statsd_format != 2)
{
config->statsd_format = 1;
}
LOG_DEBUG("STAT->output_file : %s", config->output_file);
LOG_DEBUG("STAT->statsd_server : %s", config->statsd_server);
LOG_DEBUG("STAT->statsd_port : %d", config->statsd_port);
LOG_DEBUG("STAT->statsd_format : %d", config->statsd_format);
LOG_DEBUG("STAT->statsd_cycle : %d", config->statsd_cycle);
LOG_DEBUG("STAT->prometheus_listen_port : %d", config->prometheus_listen_port);
LOG_DEBUG("STAT->prometheus_listen_url : %s", config->prometheus_listen_url);
}
struct packet_stat *packet_stat_create(const char *profile)
{
struct packet_stat *handle = (struct packet_stat *)calloc(1, sizeof(struct packet_stat));
assert(handle != NULL);
packet_stat_config(profile, &handle->config);
FS_library_set_prometheus_port(handle->config.prometheus_listen_port);
FS_library_set_prometheus_url_path(handle->config.prometheus_listen_url);
FS_library_init();
int value = 0;
handle->fs_handle = FS_create_handle(); // TODO memleak no free() API
FS_set_para(handle->fs_handle, APP_NAME, "packet_adapter", 13);
FS_set_para(handle->fs_handle, OUTPUT_DEVICE, handle->config.output_file, strlen(handle->config.output_file));
value = 1;
FS_set_para(handle->fs_handle, OUTPUT_PROMETHEUS, &value, sizeof(value));
value = 1;
FS_set_para(handle->fs_handle, PRINT_MODE, &value, sizeof(value));
value = 0;
FS_set_para(handle->fs_handle, CREATE_THREAD, &value, sizeof(value));
if (strlen(handle->config.statsd_server) > 0 && handle->config.statsd_port != 0)
{
FS_set_para(handle->fs_handle, STATS_SERVER_IP, handle->config.statsd_server, strlen(handle->config.statsd_server));
FS_set_para(handle->fs_handle, STATS_SERVER_PORT, &(handle->config.statsd_port), sizeof(handle->config.statsd_port));
FS_set_para(handle->fs_handle, STATS_FORMAT, &handle->config.statsd_format, sizeof(handle->config.statsd_format));
}
for (int i = 0; i < STAT_MAX; i++)
{
handle->fs_id[i] = FS_register(handle->fs_handle, FS_STYLE_FIELD, FS_CALC_CURRENT, stat_map[i]);
}
FS_start(handle->fs_handle);
return handle;
}
void packet_stat_destory(struct packet_stat *handle)
{
if (handle)
{
FS_library_destroy();
free(handle);
handle = NULL;
}
}
void packet_stat_output(struct packet_stat *handle, struct metrics *metrics)
{
FS_operate(handle->fs_handle, handle->fs_id[STAT_RX_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->rx_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_RX_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->rx_bytes)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_RX_ERR_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->rx_err_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_RX_ERR_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->rx_err_bytes)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_SUCC_TX_V4_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->succ_tx_v4_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_SUCC_TX_V4_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->succ_tx_v4_bytes)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_SUCC_TX_V6_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->succ_tx_v6_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_SUCC_TX_V6_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->succ_tx_v6_bytes)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_ERR_TX_V4_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->err_tx_v4_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_ERR_TX_V4_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->err_tx_v4_bytes)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_ERR_TX_V6_PKT], 0, FS_OP_SET, ATOMIC_READ(&(metrics->err_tx_v6_pkts)));
FS_operate(handle->fs_handle, handle->fs_id[STAT_ERR_TX_V6_B], 0, FS_OP_SET, ATOMIC_READ(&(metrics->err_tx_v6_bytes)));
FS_passive_output(handle->fs_handle);
}
int packet_stat_cycle(struct packet_stat *handle)
{
if (handle)
{
return handle->config.statsd_cycle;
}
else
{
return 0;
}
}

View File

@@ -1,4 +1,11 @@
#include "system.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "log.h"
int run_daemon(void)
{

View File

@@ -0,0 +1,15 @@
###############################################################################
# gtest_packet_handle
###############################################################################
add_executable(gtest_packet_handle gtest_packet_handle.cpp ${CMAKE_SOURCE_DIR}/platform/src/packet_handle.cpp)
target_include_directories(gtest_packet_handle PUBLIC ${CMAKE_SOURCE_DIR}/common/include)
target_include_directories(gtest_packet_handle PUBLIC ${CMAKE_SOURCE_DIR}/platform/include)
target_link_libraries(gtest_packet_handle common gtest)
###############################################################################
# gtest_discover_tests
###############################################################################
include(GoogleTest)
gtest_discover_tests(gtest_packet_handle)

View File

@@ -0,0 +1,570 @@
#include <gtest/gtest.h>
#include "utils.h"
#include "packet_handle.h"
#if 1
/******************************************************************************
* Pcap file: 1-ETH_VLAN_VLAN_IP4_IP4_UDP.pcap
* [Protocols in frame: eth:ethertype:vlan:ethertype:vlan:ethertype:ip:ip:udp:data]
******************************************************************************
*
* Frame 1: 170 bytes on wire (1360 bits), 170 bytes captured (1360 bits)
* Ethernet II, Src: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a), Dst: 00:00:00_00:00:04 (00:00:00:00:00:04)
* Destination: 00:00:00_00:00:04 (00:00:00:00:00:04)
* Source: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a)
* Type: 802.1Q Virtual LAN (0x8100)
* 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 1624
* 011. .... .... .... = Priority: Critical Applications (3)
* ...0 .... .... .... = DEI: Ineligible
* .... 0110 0101 1000 = ID: 1624
* Type: 802.1Q Virtual LAN (0x8100)
* 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 505
* 011. .... .... .... = Priority: Critical Applications (3)
* ...0 .... .... .... = DEI: Ineligible
* .... 0001 1111 1001 = ID: 505
* Type: IPv4 (0x0800)
* Internet Protocol Version 4, Src: 69.67.35.146, Dst: 41.202.46.110
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT)
* Total Length: 148
* Identification: 0xe858 (59480)
* 000. .... = Flags: 0x0
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 255
* Protocol: IPIP (4)
* Header Checksum: 0x1148 [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 69.67.35.146
* Destination Address: 41.202.46.110
* Internet Protocol Version 4, Src: 10.10.100.25, Dst: 10.10.101.2
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT)
* Total Length: 128
* Identification: 0x0001 (1)
* 000. .... = Flags: 0x0
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 254
* Protocol: UDP (17)
* Header Checksum: 0xde84 [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 10.10.100.25
* Destination Address: 10.10.101.2
* User Datagram Protocol, Src Port: 62367, Dst Port: 17000
* Source Port: 62367
* Destination Port: 17000
* Length: 108
* Checksum: 0x4b9a [unverified]
* [Checksum Status: Unverified]
* [Stream index: 0]
* [Timestamps]
* [Time since first frame: 0.000000000 seconds]
* [Time since previous frame: 0.000000000 seconds]
* UDP payload (100 bytes)
* Data (100 bytes)
*/
unsigned char data1[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa4, 0xc6, 0x4f, 0x3b, 0xb3, 0x9a, 0x81, 0x00, 0x66, 0x58, 0x81, 0x00, 0x61, 0xf9, 0x08, 0x00, 0x45, 0xb8, 0x00, 0x94,
0xe8, 0x58, 0x00, 0x00, 0xff, 0x04, 0x11, 0x48, 0x45, 0x43, 0x23, 0x92, 0x29, 0xca, 0x2e, 0x6e, 0x45, 0xb8, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x11,
0xde, 0x84, 0x0a, 0x0a, 0x64, 0x19, 0x0a, 0x0a, 0x65, 0x02, 0xf3, 0x9f, 0x42, 0x68, 0x00, 0x6c, 0x4b, 0x9a, 0x00, 0x02, 0x00, 0x00, 0x04, 0x73, 0x6c, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd};
TEST(PACKET_PARSER, ETH_VLAN_VLAN_IP4_IP4_UDP)
{
struct metrics metrics = {0};
packet_handle((const char *)data1, sizeof(data1), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 170);
EXPECT_TRUE(metrics.succ_tx_v4_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v4_bytes == 148); // 170 - 14 - 4 - 4
}
#endif
#if 1
/******************************************************************************
* 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_HANDLE, ETH_IP6_IP4_TCP_SSH)
{
struct metrics metrics = {0};
packet_handle((const char *)data2, sizeof(data2), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 726);
EXPECT_TRUE(metrics.succ_tx_v6_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v6_bytes == 712); // 726 - 14
}
#endif
#if 1
/******************************************************************************
* 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_HANDLE, ETH_IP4_IP6_TCP)
{
struct metrics metrics = {0};
packet_handle((const char *)data4, sizeof(data4), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 106);
EXPECT_TRUE(metrics.succ_tx_v4_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v4_bytes == 92); // 106 - 14
}
#endif
#if 1
/******************************************************************************
* Pcap file: 6-ETH_MPLS_IP4_TCP.pcap
* [Protocols in frame: eth:ethertype:mpls:ip:tcp]
******************************************************************************
*
* Frame 1: 70 bytes on wire (560 bits), 70 bytes captured (560 bits)
* Ethernet II, Src: Hangzhou_d9:28:cc (00:23:89:d9:28:cc), Dst: HuaweiTe_7f:eb:f7 (d4:6a:a8:7f:eb:f7)
* Destination: HuaweiTe_7f:eb:f7 (d4:6a:a8:7f:eb:f7)
* Source: Hangzhou_d9:28:cc (00:23:89:d9:28:cc)
* Type: MPLS label switched packet (0x8847)
* MultiProtocol Label Switching Header, Label: 18, Exp: 6, S: 1, TTL: 254
* 0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012)
* .... .... .... .... .... 110. .... .... = MPLS Experimental Bits: 6
* .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1
* .... .... .... .... .... .... 1111 1110 = MPLS TTL: 254
* Internet Protocol Version 4, Src: 119.40.37.65, Dst: 123.125.29.250
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* Total Length: 52
* Identification: 0x02a1 (673)
* 010. .... = Flags: 0x2, Don't fragment
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 126
* Protocol: TCP (6)
* Header Checksum: 0xc442 [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 119.40.37.65
* Destination Address: 123.125.29.250
* Transmission Control Protocol, Src Port: 61853, Dst Port: 80, Seq: 0, Len: 0
* Source Port: 61853
* 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): 1710561749
* [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: 0xa777 [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 data6[] = {
0xd4, 0x6a, 0xa8, 0x7f, 0xeb, 0xf7, 0x00, 0x23, 0x89, 0xd9, 0x28, 0xcc, 0x88, 0x47, 0x00, 0x01, 0x2d, 0xfe, 0x45, 0x00, 0x00, 0x34, 0x02, 0xa1, 0x40, 0x00,
0x7e, 0x06, 0xc4, 0x42, 0x77, 0x28, 0x25, 0x41, 0x7b, 0x7d, 0x1d, 0xfa, 0xf1, 0x9d, 0x00, 0x50, 0x65, 0xf5, 0x19, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02,
0x20, 0x00, 0xa7, 0x77, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02};
TEST(PACKET_PARSER, ETH_MPLS_IP4_TCP)
{
struct metrics metrics = {0};
packet_handle((const char *)data6, sizeof(data6), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 70);
EXPECT_TRUE(metrics.succ_tx_v4_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v4_bytes == 52); // 70 - 14 -4
}
#endif
#if 1
/******************************************************************************
* Pcap file: 7-ETH_MPLS_MPLS_IP4_TCP.pcap
* [Protocols in frame: eth:ethertype:mpls:ip:tcp]
******************************************************************************
*
* Frame 1: 66 bytes on wire (528 bits), 66 bytes captured (528 bits)
* Ethernet II, Src: Cisco_05:28:38 (00:30:96:05:28:38), Dst: Cisco_e6:fc:39 (00:30:96:e6:fc:39)
* Destination: Cisco_e6:fc:39 (00:30:96:e6:fc:39)
* Source: Cisco_05:28:38 (00:30:96:05:28:38)
* Type: MPLS label switched packet (0x8847)
* MultiProtocol Label Switching Header, Label: 18, Exp: 5, S: 0, TTL: 255
* 0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012)
* .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5
* .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0
* .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255
* MultiProtocol Label Switching Header, Label: 16, Exp: 5, S: 1, TTL: 255
* 0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010)
* .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5
* .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1
* .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255
* Internet Protocol Version 4, Src: 10.31.0.1, Dst: 10.34.0.1
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0xb0 (DSCP: Unknown, ECN: Not-ECT)
* Total Length: 44
* Identification: 0x0000 (0)
* 000. .... = Flags: 0x0
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 255
* Protocol: TCP (6)
* Header Checksum: 0xa6d9 [validation disabled]
* [Header checksum status: Unverified]
* Source Address: 10.31.0.1
* Destination Address: 10.34.0.1
* Transmission Control Protocol, Src Port: 11001, Dst Port: 23, Seq: 0, Len: 0
* Source Port: 11001
* Destination Port: 23
* [Stream index: 0]
* [Conversation completeness: Incomplete (29)]
* [TCP Segment Len: 0]
* Sequence Number: 0 (relative sequence number)
* Sequence Number (raw): 3481568569
* [Next Sequence Number: 1 (relative sequence number)]
* Acknowledgment Number: 0
* Acknowledgment number (raw): 0
* 0110 .... = Header Length: 24 bytes (6)
* Flags: 0x002 (SYN)
* Window: 4128
* [Calculated window size: 4128]
* Checksum: 0xf791 [unverified]
* [Checksum Status: Unverified]
* Urgent Pointer: 0
* Options: (4 bytes), Maximum segment size
* [Timestamps]
*/
unsigned char data7[] = {
0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39, 0x00, 0x30, 0x96, 0x05, 0x28, 0x38, 0x88, 0x47, 0x00, 0x01, 0x2a, 0xff, 0x00, 0x01, 0x0b, 0xff, 0x45, 0xb0, 0x00, 0x2c,
0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0xa6, 0xd9, 0x0a, 0x1f, 0x00, 0x01, 0x0a, 0x22, 0x00, 0x01, 0x2a, 0xf9, 0x00, 0x17, 0xcf, 0x84, 0x85, 0x39, 0x00, 0x00,
0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xf7, 0x91, 0x00, 0x00, 0x02, 0x04, 0x02, 0x18};
TEST(PACKET_PARSER, ETH_MPLS_MPLS_IP4_TCP)
{
struct metrics metrics = {0};
packet_handle((const char *)data7, sizeof(data7), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 66);
EXPECT_TRUE(metrics.succ_tx_v4_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v4_bytes == 44); // 66 - 14 - 4 - 4
}
#endif
#if 1
/******************************************************************************
* Pcap file: 9-ETH_IP6_UDP_GTP_IP6_TCP_TLS.pcap
* [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ipv6:tcp:ja3:tls]
******************************************************************************
*
* Frame 1: 1442 bytes on wire (11536 bits), 1442 bytes captured (11536 bits)
* Ethernet II, Src: zte_0e:f5:40 (74:4a:a4:0e:f5:40), Dst: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2)
* Destination: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2)
* Source: zte_0e:f5:40 (74:4a:a4:0e:f5:40)
* Type: IPv6 (0x86dd)
* Internet Protocol Version 6, Src: 2409:8034:4040:5300::105, Dst: 2409:8034:4025::60:61
* 0110 .... = Version: 6
* .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
* .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
* Payload Length: 1388
* Next Header: UDP (17)
* Hop Limit: 127
* Source Address: 2409:8034:4040:5300::105
* Destination Address: 2409:8034:4025::60:61
* User Datagram Protocol, Src Port: 2152, Dst Port: 2152
* Source Port: 2152
* Destination Port: 2152
* Length: 1388
* Checksum: 0xeb00 [unverified]
* [Checksum Status: Unverified]
* [Stream index: 0]
* [Timestamps]
* UDP payload (1380 bytes)
* GPRS Tunneling Protocol
* Flags: 0x30
* Message Type: T-PDU (0xff)
* Length: 1372
* TEID: 0x024c3cbd (38550717)
* Internet Protocol Version 6, Src: 2409:8c34:4400:700:0:4:0:3, Dst: 2409:8934:5082:2100:ecad:e0e4:530a:c269
* 0110 .... = Version: 6
* .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
* .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
* Payload Length: 1332
* Next Header: TCP (6)
* Hop Limit: 56
* Source Address: 2409:8c34:4400:700:0:4:0:3
* Destination Address: 2409:8934:5082:2100:ecad:e0e4:530a:c269
* Transmission Control Protocol, Src Port: 443, Dst Port: 46582, Seq: 1, Ack: 1, Len: 1312
* Source Port: 443
* Destination Port: 46582
* [Stream index: 0]
* [Conversation completeness: Incomplete (8)]
* [TCP Segment Len: 1312]
* Sequence Number: 1 (relative sequence number)
* Sequence Number (raw): 2198097831
* [Next Sequence Number: 1313 (relative sequence number)]
* Acknowledgment Number: 1 (relative ack number)
* Acknowledgment number (raw): 2264498872
* 0101 .... = Header Length: 20 bytes (5)
* Flags: 0x010 (ACK)
* Window: 529
* [Calculated window size: 529]
* [Window size scaling factor: -1 (unknown)]
* Checksum: 0x2c4b [unverified]
* [Checksum Status: Unverified]
* Urgent Pointer: 0
* [Timestamps]
* [SEQ/ACK analysis]
* TCP payload (1312 bytes)
* Transport Layer Security
*/
unsigned char data9[] = {
0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc2, 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x40, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x6c, 0x11, 0x7f, 0x24, 0x09, 0x80, 0x34,
0x40, 0x40, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x24, 0x09, 0x80, 0x34, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x00, 0x61, 0x08, 0x68, 0x08, 0x68, 0x05, 0x6c, 0xeb, 0x00, 0x30, 0xff, 0x05, 0x5c, 0x02, 0x4c, 0x3c, 0xbd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x34, 0x06, 0x38,
0x24, 0x09, 0x8c, 0x34, 0x44, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x24, 0x09, 0x89, 0x34, 0x50, 0x82, 0x21, 0x00, 0xec, 0xad,
0xe0, 0xe4, 0x53, 0x0a, 0xc2, 0x69, 0x01, 0xbb, 0xb5, 0xf6, 0x83, 0x04, 0x4f, 0xa7, 0x86, 0xf9, 0x82, 0xb8, 0x50, 0x10, 0x02, 0x11, 0x2c, 0x4b, 0x00, 0x00,
0x17, 0x03, 0x03, 0x3c, 0x8c, 0x87, 0xa0, 0x99, 0x23, 0x5b, 0x53, 0x4a, 0x12, 0x1b, 0xf8, 0xba, 0xe8, 0x83, 0xc2, 0x95, 0xda, 0xb8, 0xea, 0x5b, 0xdc, 0x84,
0x61, 0xa9, 0x86, 0x7e, 0x43, 0xc7, 0x31, 0x44, 0x6e, 0x11, 0xc1, 0x30, 0x21, 0x03, 0xb4, 0x21, 0x4a, 0xee, 0xc9, 0x2e, 0x14, 0xd2, 0x98, 0x63, 0x12, 0xfe,
0x79, 0x58, 0xb3, 0x18, 0xa6, 0x8d, 0x0c, 0x62, 0x67, 0x51, 0xef, 0x02, 0x5a, 0xa8, 0xb3, 0x82, 0x1f, 0xe4, 0x51, 0xba, 0xde, 0xee, 0x83, 0x9c, 0x4e, 0xac,
0x4d, 0xa2, 0xb7, 0x6a, 0x82, 0xe7, 0xbb, 0x00, 0xf7, 0x5a, 0xe7, 0x02, 0x71, 0x7e, 0x7d, 0x6f, 0xf2, 0xe5, 0x47, 0xd0, 0xba, 0x3c, 0x51, 0x09, 0x95, 0xcd,
0xf6, 0xc9, 0x8b, 0x6f, 0xb0, 0x39, 0x11, 0x0d, 0xe9, 0x0d, 0x4d, 0x29, 0xd4, 0xcb, 0x87, 0xba, 0x11, 0xfa, 0x0d, 0x0b, 0x82, 0x95, 0xa5, 0x84, 0x94, 0x48,
0xa2, 0xee, 0xa4, 0xb7, 0xb6, 0x76, 0x13, 0x4d, 0x18, 0x42, 0x91, 0x77, 0xad, 0x82, 0x38, 0xee, 0x34, 0x1c, 0xb7, 0xf6, 0x39, 0xdc, 0xa4, 0x23, 0xa1, 0x7c,
0xa5, 0x0b, 0x7e, 0x4c, 0x8b, 0x81, 0x31, 0x48, 0xea, 0xf4, 0x18, 0x37, 0x09, 0x0a, 0x53, 0x13, 0x05, 0x90, 0x26, 0x10, 0x69, 0xb2, 0xa3, 0x36, 0xbc, 0xa5,
0x83, 0xd8, 0x16, 0x77, 0x98, 0xc8, 0x21, 0x38, 0xd9, 0x88, 0x0c, 0xa7, 0x16, 0x97, 0x4e, 0x20, 0x6d, 0x68, 0xda, 0x1b, 0x3b, 0x4a, 0x62, 0xe0, 0x36, 0x0d,
0xbf, 0x30, 0x71, 0xb1, 0xe9, 0xbe, 0x47, 0x77, 0x99, 0xb9, 0xe6, 0x26, 0xab, 0x81, 0x2e, 0x46, 0xf1, 0x1b, 0x1e, 0xfb, 0xd7, 0x81, 0x60, 0x21, 0x4a, 0x71,
0x85, 0xf7, 0x9c, 0x9c, 0xd4, 0x1c, 0x52, 0xc4, 0x3d, 0x8d, 0x72, 0xf6, 0x7c, 0xd3, 0x58, 0x79, 0x0d, 0x78, 0xd7, 0x7c, 0x29, 0x2b, 0xc3, 0x96, 0x1d, 0xc7,
0x96, 0x50, 0x42, 0xd7, 0xda, 0xeb, 0x29, 0x8e, 0x2a, 0x72, 0x23, 0x57, 0x0f, 0x6f, 0x37, 0x35, 0xb2, 0x42, 0x76, 0x78, 0xbf, 0xbf, 0x8c, 0x3f, 0x31, 0xa2,
0x51, 0xec, 0x9e, 0x0d, 0xfd, 0xf2, 0xaf, 0x71, 0xa0, 0x4f, 0xa9, 0xf6, 0x19, 0xcf, 0x3e, 0x4b, 0xc8, 0xaa, 0x38, 0x06, 0xa1, 0x15, 0xde, 0xde, 0xef, 0x9b,
0x25, 0xa3, 0xcc, 0x47, 0xca, 0x29, 0x30, 0x65, 0x5f, 0xc1, 0x8b, 0x12, 0x63, 0x79, 0xcd, 0x57, 0x4d, 0x99, 0xc0, 0xcd, 0xbe, 0x62, 0xcb, 0xc3, 0xf2, 0x6b,
0x0b, 0x40, 0xc5, 0xee, 0x79, 0x0a, 0xa4, 0x75, 0x56, 0xe7, 0xe7, 0xf2, 0xfd, 0xe0, 0x72, 0x78, 0x04, 0xa2, 0x50, 0x31, 0x09, 0x8b, 0x57, 0xc3, 0x85, 0x4e,
0xc4, 0xae, 0xde, 0x8a, 0xfa, 0xf6, 0x31, 0x06, 0xd2, 0x07, 0x25, 0x40, 0xce, 0x0d, 0xfd, 0x26, 0x98, 0x41, 0xa3, 0xa9, 0xa2, 0x8d, 0x8b, 0x7f, 0x6d, 0x63,
0x87, 0x7e, 0x75, 0x2f, 0x78, 0xc9, 0xd5, 0x04, 0xb2, 0x4f, 0xc9, 0x94, 0xa7, 0x7f, 0xbc, 0x75, 0x7b, 0xb6, 0xfb, 0x2c, 0x46, 0xf6, 0xde, 0x36, 0x31, 0x2a,
0x32, 0x1d, 0x7f, 0x30, 0x9e, 0x4a, 0x84, 0x69, 0x66, 0xac, 0xef, 0xbe, 0xb3, 0x83, 0x8c, 0xb8, 0x30, 0xd2, 0x3f, 0xcf, 0xb5, 0xbb, 0x65, 0xaa, 0xe7, 0x6b,
0x74, 0x48, 0x2c, 0xb2, 0x72, 0x2b, 0x78, 0xaf, 0xd0, 0x71, 0x04, 0xa9, 0xb4, 0x65, 0xd9, 0xfc, 0x74, 0x23, 0xff, 0x89, 0xc1, 0x16, 0x23, 0xac, 0x59, 0x16,
0x89, 0x41, 0xc3, 0xdb, 0xdb, 0x5b, 0x9a, 0x3d, 0x08, 0xc4, 0x12, 0x28, 0xf8, 0x10, 0xa5, 0xad, 0xc6, 0x81, 0xc0, 0x61, 0x48, 0xba, 0x9d, 0xef, 0xc7, 0xf8,
0xad, 0x9a, 0xbd, 0x87, 0xfa, 0x7f, 0xa2, 0x4e, 0x4d, 0xe0, 0x19, 0xd5, 0x47, 0xc7, 0xd0, 0xfb, 0x00, 0x7b, 0xbf, 0x17, 0x80, 0xfe, 0xf5, 0x27, 0xec, 0x94,
0x44, 0x3d, 0x4a, 0x34, 0x49, 0x60, 0xb4, 0x8d, 0x71, 0x6d, 0x9c, 0xf4, 0x4c, 0x33, 0xa9, 0x49, 0x58, 0x58, 0x6f, 0xe1, 0xd1, 0x7d, 0x36, 0x51, 0xf4, 0xd8,
0x0d, 0x0b, 0xfc, 0xeb, 0xae, 0x58, 0x06, 0x08, 0xbf, 0x67, 0x07, 0x28, 0x7e, 0x68, 0x65, 0x79, 0x86, 0xfb, 0x43, 0x0f, 0x0a, 0xef, 0xd0, 0x97, 0x33, 0x10,
0x7a, 0x20, 0xe8, 0x22, 0xe5, 0xdc, 0x0c, 0xa2, 0xa5, 0x50, 0x1b, 0x08, 0x15, 0xc2, 0xec, 0xd2, 0x06, 0x25, 0xd0, 0x3b, 0xfd, 0xe3, 0xa2, 0x6f, 0x41, 0x15,
0x6d, 0x9f, 0x5f, 0xc4, 0x07, 0x5c, 0x99, 0x63, 0xd9, 0xd7, 0xdc, 0x90, 0xc9, 0x8f, 0x3a, 0x4b, 0x6a, 0x84, 0xe8, 0x3c, 0xc7, 0x71, 0x50, 0x71, 0x86, 0x71,
0x7d, 0x54, 0x84, 0x7b, 0xb7, 0xca, 0xd5, 0x42, 0xaf, 0x88, 0xa5, 0xae, 0xa4, 0x9c, 0xfd, 0x71, 0x71, 0x0f, 0x67, 0xaa, 0x1b, 0x61, 0xd7, 0xf4, 0x50, 0x21,
0x9d, 0x80, 0x6e, 0x54, 0xcd, 0xb6, 0xb9, 0x02, 0x3e, 0x59, 0x50, 0xff, 0xf2, 0xda, 0x21, 0x5c, 0x50, 0x6d, 0x64, 0x8c, 0x33, 0x75, 0x2a, 0xa4, 0x56, 0xb3,
0xa8, 0xdb, 0xba, 0xbe, 0x52, 0xd4, 0xe5, 0x29, 0x68, 0xe2, 0x6b, 0x94, 0x6b, 0xb3, 0x90, 0x63, 0x91, 0x1a, 0x95, 0xb5, 0xd7, 0x10, 0x1b, 0xd9, 0x93, 0x4f,
0x33, 0xb6, 0x6a, 0x4e, 0xcd, 0x40, 0x9d, 0x47, 0x76, 0x3e, 0x4b, 0xc7, 0x2f, 0x16, 0x96, 0x64, 0x9d, 0x4e, 0x8c, 0xfb, 0x0f, 0xd2, 0xec, 0x6c, 0xba, 0xf2,
0x9c, 0xca, 0xd2, 0x3e, 0x64, 0x37, 0x32, 0x20, 0xd7, 0x4c, 0xb0, 0xe7, 0xd3, 0x75, 0x51, 0x3a, 0x94, 0xc1, 0xdf, 0x1c, 0xb3, 0x10, 0xd5, 0x1e, 0xcf, 0x7c,
0xb7, 0xab, 0x4a, 0x93, 0xf0, 0x78, 0x58, 0x28, 0x63, 0x10, 0xee, 0xb0, 0xd6, 0x14, 0x81, 0x47, 0xeb, 0x2e, 0xc8, 0x6e, 0x33, 0x7e, 0xf3, 0x2d, 0xc8, 0xdb,
0x29, 0x0c, 0x80, 0xe4, 0x2f, 0x10, 0x07, 0x8e, 0x08, 0x86, 0x97, 0x1b, 0x39, 0x98, 0x39, 0x06, 0xb3, 0x85, 0x53, 0xb7, 0xbb, 0x65, 0x65, 0x85, 0x0e, 0x0a,
0x7d, 0x29, 0x3d, 0x3f, 0x52, 0xc2, 0x7b, 0x2b, 0x30, 0x94, 0x99, 0x6a, 0x4b, 0xad, 0xe9, 0xec, 0xcb, 0xcd, 0xae, 0x97, 0x45, 0x54, 0xd5, 0x00, 0x5e, 0xd8,
0xac, 0xeb, 0x99, 0xdc, 0x58, 0x0b, 0x01, 0xeb, 0x32, 0x22, 0xc4, 0xec, 0x4f, 0xd2, 0x15, 0x03, 0x30, 0x88, 0xc7, 0x28, 0xaf, 0x78, 0xf5, 0x38, 0x84, 0x3b,
0x3b, 0xe9, 0x29, 0x71, 0x50, 0xa3, 0x07, 0x49, 0x3b, 0xc6, 0x97, 0xc6, 0xf9, 0x53, 0x95, 0x51, 0x65, 0x7e, 0xd7, 0xd4, 0xe8, 0x76, 0x6a, 0x6d, 0x37, 0x6b,
0xa5, 0x59, 0xaa, 0x14, 0x18, 0x8c, 0x8d, 0x65, 0x78, 0x67, 0xfb, 0x60, 0x56, 0xab, 0x04, 0xa0, 0xc2, 0x93, 0x46, 0xf1, 0x2b, 0x0d, 0x3b, 0x38, 0x62, 0x62,
0x5e, 0xc8, 0x30, 0xf9, 0x45, 0x28, 0x6f, 0xa1, 0xb1, 0x88, 0xf1, 0x2b, 0x3b, 0xf8, 0xae, 0x91, 0x52, 0xc3, 0x72, 0x86, 0xe4, 0xec, 0xc3, 0x54, 0x86, 0xbf,
0x8f, 0x33, 0xb1, 0x0f, 0x42, 0xc5, 0x9c, 0xb8, 0xc2, 0x67, 0x8b, 0xac, 0x78, 0xd7, 0x63, 0xab, 0x05, 0xc6, 0x6c, 0x37, 0xa1, 0x28, 0xef, 0x95, 0xc9, 0xf5,
0x12, 0x38, 0x54, 0x34, 0x2e, 0x03, 0x6a, 0xaa, 0xa9, 0x97, 0x72, 0x22, 0x9f, 0x20, 0xec, 0x9e, 0x29, 0x09, 0xd8, 0x38, 0xd1, 0x86, 0x82, 0x99, 0xbd, 0x2a,
0x03, 0xe9, 0x3d, 0xbd, 0xea, 0xc5, 0x8b, 0xb0, 0x4c, 0x8b, 0x7e, 0x78, 0x08, 0xef, 0x39, 0xa8, 0xb4, 0x47, 0xce, 0x44, 0xc3, 0x3f, 0x52, 0xe4, 0xbd, 0x9e,
0xf6, 0xed, 0x6f, 0x6c, 0x05, 0x19, 0xa6, 0x0a, 0x1e, 0x48, 0xe3, 0x9b, 0x91, 0x61, 0xef, 0xf5, 0x91, 0x39, 0x70, 0x44, 0x1c, 0x08, 0x2e, 0x2c, 0x6c, 0x27,
0xb9, 0x0e, 0xcc, 0x74, 0x69, 0xa5, 0xf8, 0x19, 0xd6, 0xbf, 0x57, 0x6c, 0x9a, 0x91, 0x74, 0xfd, 0xc2, 0x31, 0x32, 0x12, 0x06, 0xa3, 0x69, 0x71, 0xda, 0x40,
0xa1, 0xf3, 0xb5, 0x9a, 0x43, 0xcc, 0xb4, 0x3c, 0x16, 0x40, 0x65, 0x2b, 0x02, 0xac, 0x5c, 0xae, 0xd6, 0x34, 0x34, 0xe3, 0x69, 0x76, 0x2c, 0xa8, 0xdd, 0x04,
0x92, 0xa6, 0x7a, 0xc0, 0x87, 0x70, 0x8b, 0x85, 0xba, 0x5d, 0xbb, 0x62, 0x70, 0xcc, 0x1f, 0x21, 0x2c, 0x7e, 0xc3, 0x77, 0xcf, 0x23, 0x22, 0xf4, 0x16, 0x8e,
0xf1, 0x3d, 0xdc, 0x33, 0x99, 0x5e, 0xaa, 0xa2, 0x50, 0x68, 0xde, 0x03, 0x44, 0xbb, 0xc7, 0x16, 0x2a, 0xf2, 0x08, 0xeb, 0x3d, 0x12, 0x6d, 0xcb, 0x2a, 0xaf,
0xb4, 0x79, 0xdb, 0x74, 0x5e, 0x54, 0x89, 0x73, 0x0c, 0x48, 0x9c, 0x03, 0x33, 0xd2, 0x92, 0x22, 0xdb, 0x3a, 0xa0, 0x8c, 0xe2, 0x30, 0x6f, 0x39, 0xe4, 0xa9,
0x24, 0x04, 0xbb, 0x85, 0x7d, 0x62, 0xc5, 0xa9, 0x98, 0x92, 0xef, 0xc6, 0xc8, 0xd1, 0x81, 0xad, 0x95, 0x40, 0x27, 0x09, 0xc7, 0x43, 0xcd, 0xb6, 0x94, 0xfc,
0x1c, 0x7d, 0x1c, 0xd3, 0x47, 0xfe, 0x62, 0x9c, 0xfa, 0xeb, 0xfc, 0x02, 0x2e, 0x48, 0x62, 0xcf, 0x63, 0xdb, 0x63, 0xd9, 0x21, 0x86, 0xe8, 0x96, 0x54, 0xeb,
0x6a, 0xa8, 0x78, 0x3c, 0x5b, 0xb6, 0xde, 0xa9, 0x04, 0x48, 0x63, 0xb2, 0x10, 0x02, 0x6a, 0x7f, 0x6d, 0xc8, 0x04, 0xdd, 0x99, 0x25, 0x08, 0xff, 0x80, 0x11,
0x53, 0xfb, 0x7a, 0x07, 0x39, 0xd9, 0x97, 0xca, 0xf0, 0xa7, 0x46, 0x9c, 0xc2, 0xae, 0x2e, 0x05, 0x62, 0xa0, 0xd5, 0x5d, 0x17, 0x0e, 0x5c, 0x7e, 0x9a, 0xb2,
0xb7, 0x9d, 0xd4, 0x4f, 0xe3, 0xac, 0x64, 0xdb, 0x6f, 0x1d, 0xdf, 0xd8, 0x41, 0xd7, 0xd9, 0x50, 0x55, 0x30, 0xeb, 0x4b, 0x19, 0xce, 0x78, 0x1f, 0xa8, 0x1e,
0x87, 0x9c, 0x8f, 0x93, 0x97, 0xd4, 0xa2, 0x28, 0x2c, 0x79, 0x22, 0xc8};
TEST(PACKET_PARSER, ETH_IP6_UDP_GTP_IP6_TCP_TLS)
{
struct metrics metrics = {0};
packet_handle((const char *)data9, sizeof(data9), &metrics);
metrics_dump(&metrics);
EXPECT_TRUE(metrics.rx_pkts == 1);
EXPECT_TRUE(metrics.rx_bytes == 1442);
EXPECT_TRUE(metrics.succ_tx_v6_pkts == 1);
EXPECT_TRUE(metrics.succ_tx_v6_bytes == 1372); // 1442 - 14 - 40 - 8 - 8
}
#endif
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -1 +1 @@
install(FILES service/packetadapter.service DESTINATION /usr/lib/systemd/system/ COMPONENT Program)
install(FILES service/packet_adapter.service DESTINATION /usr/lib/systemd/system/ COMPONENT Program)

View File

@@ -0,0 +1,10 @@
[Unit]
Description=Packet Adapter
After=network.target
[Service]
#ExecStartPre=/usr/sbin/iptables -A OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
#ExecStartPre=/usr/sbin/ip6tables -A OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
ExecStart=/opt/tsg/packet_adapter/bin/packet_adapter
#ExecStopPost=/usr/sbin/iptables -D OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
#ExecStopPost=/usr/sbin/ip6tables -D OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Packet Adapter
After=network.target
[Service]
ExecStartPre=/usr/sbin/iptables -A OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
ExecStartPre=/usr/sbin/ip6tables -A OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
ExecStart=/opt/tsg/packetadapter/bin/packetadapter
ExecStopPost=/usr/sbin/iptables -D OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1
ExecStopPost=/usr/sbin/ip6tables -D OUTPUT -o eno4 -p udp --dport 2152 -j NFQUEUE --queue-num 1

44
vendor/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,44 @@
include(ExternalProject)
# GoogleTest
ExternalProject_Add(googletest PREFIX googletest
URL ${CMAKE_CURRENT_SOURCE_DIR}/googletest-release-1.8.0.tar.gz
URL_MD5 16877098823401d1bf2ed7891d7dce36
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
ExternalProject_Get_Property(googletest INSTALL_DIR)
file(MAKE_DIRECTORY ${INSTALL_DIR}/include)
add_library(gtest STATIC IMPORTED GLOBAL)
add_dependencies(gtest googletest)
set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgtest.a)
set_property(TARGET gtest PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
set_property(TARGET gtest PROPERTY INTERFACE_LINK_LIBRARIES pthread)
add_library(gmock STATIC IMPORTED GLOBAL)
add_dependencies(gmock googletest)
set_property(TARGET gmock PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libgmock.a)
set_property(TARGET gmock PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include)
# MESA Framework
set(MESA_FRAMEWORK_LIB_DIR /opt/MESA/lib)
set(MESA_FRAMEWORK_INCLUDE_DIR /opt/MESA/include)
add_library(MESA_handle_logger SHARED IMPORTED GLOBAL)
set_property(TARGET MESA_handle_logger PROPERTY IMPORTED_LOCATION ${MESA_FRAMEWORK_LIB_DIR}/libMESA_handle_logger.so)
set_property(TARGET MESA_handle_logger PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MESA_FRAMEWORK_INCLUDE_DIR})
add_library(MESA_prof_load SHARED IMPORTED GLOBAL)
set_property(TARGET MESA_prof_load PROPERTY IMPORTED_LOCATION ${MESA_FRAMEWORK_LIB_DIR}/libMESA_prof_load.so)
set_property(TARGET MESA_prof_load PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MESA_FRAMEWORK_INCLUDE_DIR})
add_library(MESA_field_stat SHARED IMPORTED GLOBAL)
set_property(TARGET MESA_field_stat PROPERTY IMPORTED_LOCATION ${MESA_FRAMEWORK_LIB_DIR}/libMESA_field_stat2.so)
set_property(TARGET MESA_field_stat PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MESA_FRAMEWORK_INCLUDE_DIR})
set(MRZCPD_LIB_DIR /opt/mrzcpd/lib)
set(MRZCPD_INCLUDE_DIR /opt/mrzcpd/include)
add_library(mrzcpd SHARED IMPORTED GLOBAL)
set_property(TARGET mrzcpd PROPERTY IMPORTED_LOCATION ${MRZCPD_LIB_DIR}/libmarsio.so)
set_property(TARGET mrzcpd PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MRZCPD_INCLUDE_DIR})

BIN
vendor/googletest-release-1.8.0.tar.gz vendored Normal file

Binary file not shown.