feature: add debug_plugin for development debugging
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
add_subdirectory(log)
|
add_subdirectory(log)
|
||||||
add_subdirectory(times)
|
add_subdirectory(times)
|
||||||
add_subdirectory(tuple)
|
add_subdirectory(tuple)
|
||||||
|
add_subdirectory(hexdump)
|
||||||
add_subdirectory(packet)
|
add_subdirectory(packet)
|
||||||
add_subdirectory(packet_io)
|
add_subdirectory(packet_io)
|
||||||
add_subdirectory(id_generator)
|
add_subdirectory(id_generator)
|
||||||
|
|||||||
3
src/hexdump/CMakeLists.txt
Normal file
3
src/hexdump/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
add_library(hexdump hexdump.cpp)
|
||||||
|
target_include_directories(hexdump PUBLIC ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
target_link_libraries(hexdump)
|
||||||
37
src/hexdump/hexdump.cpp
Normal file
37
src/hexdump/hexdump.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include "hexdump.h"
|
||||||
|
|
||||||
|
void hexdump_to_fd(int fd, const char *data, uint16_t len)
|
||||||
|
{
|
||||||
|
uint16_t i = 0;
|
||||||
|
uint16_t used = 0;
|
||||||
|
uint16_t offset = 0;
|
||||||
|
|
||||||
|
#define LINE_LEN 80
|
||||||
|
char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */
|
||||||
|
|
||||||
|
dprintf(fd, "dump data at [%p], len=%u\n", data, len);
|
||||||
|
while (offset < len)
|
||||||
|
{
|
||||||
|
/* format the line in the buffer, then use printf to usedput to screen */
|
||||||
|
used = snprintf(line, LINE_LEN, "%08X:", offset);
|
||||||
|
for (i = 0; ((offset + i) < len) && (i < 16); i++)
|
||||||
|
{
|
||||||
|
used += snprintf(line + used, LINE_LEN - used, " %02X", (data[offset + i] & 0xff));
|
||||||
|
}
|
||||||
|
for (; i <= 16; i++)
|
||||||
|
{
|
||||||
|
used += snprintf(line + used, LINE_LEN - used, " | ");
|
||||||
|
}
|
||||||
|
for (i = 0; (offset < len) && (i < 16); i++, offset++)
|
||||||
|
{
|
||||||
|
unsigned char c = data[offset];
|
||||||
|
if ((c < ' ') || (c > '~'))
|
||||||
|
{
|
||||||
|
c = '.';
|
||||||
|
}
|
||||||
|
used += snprintf(line + used, LINE_LEN - used, "%c", c);
|
||||||
|
}
|
||||||
|
dprintf(fd, "%s\n", line);
|
||||||
|
}
|
||||||
|
dprintf(fd, "\n");
|
||||||
|
}
|
||||||
15
src/hexdump/hexdump.h
Normal file
15
src/hexdump/hexdump.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void hexdump_to_fd(int fd, const char *data, uint16_t len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -2,6 +2,6 @@ add_library(packet packet_parse.cpp packet_craft.cpp packet_dump.cpp packet_util
|
|||||||
target_include_directories(packet PUBLIC ${CMAKE_CURRENT_LIST_DIR})
|
target_include_directories(packet PUBLIC ${CMAKE_CURRENT_LIST_DIR})
|
||||||
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash)
|
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash)
|
||||||
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(packet tuple log)
|
target_link_libraries(packet hexdump tuple log)
|
||||||
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "hexdump.h"
|
||||||
#include "packet_dump.h"
|
#include "packet_dump.h"
|
||||||
#include "packet_utils.h"
|
#include "packet_utils.h"
|
||||||
|
|
||||||
@@ -78,16 +79,8 @@ int packet_dump_pcap(const struct packet *pkt, const char *file)
|
|||||||
|
|
||||||
void packet_dump_hex(const struct packet *pkt, int fd)
|
void packet_dump_hex(const struct packet *pkt, int fd)
|
||||||
{
|
{
|
||||||
const char *data = packet_get_raw_data(pkt);
|
|
||||||
uint16_t len = packet_get_raw_len(pkt);
|
uint16_t len = packet_get_raw_len(pkt);
|
||||||
|
const char *data = packet_get_raw_data(pkt);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
hexdump_to_fd(fd, data, len);
|
||||||
{
|
|
||||||
if (i % 16 == 0)
|
|
||||||
{
|
|
||||||
dprintf(fd, "\n");
|
|
||||||
}
|
|
||||||
dprintf(fd, "%02x ", (unsigned char)data[i]);
|
|
||||||
}
|
|
||||||
dprintf(fd, "\n");
|
|
||||||
}
|
}
|
||||||
@@ -986,79 +986,87 @@ const char *packet_parse(struct packet *pkt, const char *data, uint16_t len)
|
|||||||
return parse_ether(pkt, data, len);
|
return parse_ether(pkt, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet_print(const struct packet *pkt)
|
int packet_to_str(const struct packet *pkt, char *buff, int size)
|
||||||
{
|
{
|
||||||
if (pkt == NULL)
|
if (pkt == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[2048] = {0};
|
int used = 0;
|
||||||
printf("packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
|
memset(buff, 0, size);
|
||||||
|
used += snprintf(buff + used, size - used, "packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
|
||||||
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
|
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
|
||||||
pkt->layers_used, pkt->layers_size);
|
pkt->layers_used, pkt->layers_size);
|
||||||
for (uint8_t i = 0; i < pkt->layers_used; i++)
|
for (uint8_t i = 0; i < pkt->layers_used; i++)
|
||||||
{
|
{
|
||||||
int used = 0;
|
|
||||||
const struct raw_layer *layer = &pkt->layers[i];
|
const struct raw_layer *layer = &pkt->layers[i];
|
||||||
printf(" layer[%u]: %p, proto: %s, header: {offset: %u, ptr: %p, len: %u}, payload: {ptr: %p, len: %u}\n",
|
used += snprintf(buff + used, size - used, "=> layer[%u]: %p, proto: %s, header: {offset: %u, ptr: %p, len: %u}, payload: {ptr: %p, len: %u}\n",
|
||||||
i, layer, layer_proto_to_str(layer->proto), layer->hdr_offset,
|
i, layer, layer_proto_to_str(layer->proto), layer->hdr_offset,
|
||||||
layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len);
|
layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len);
|
||||||
switch (layer->proto)
|
switch (layer->proto)
|
||||||
{
|
{
|
||||||
case LAYER_PROTO_ETHER:
|
case LAYER_PROTO_ETHER:
|
||||||
used = eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_PWETH:
|
case LAYER_PROTO_PWETH:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_PPP:
|
case LAYER_PROTO_PPP:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_L2TP:
|
case LAYER_PROTO_L2TP:
|
||||||
used = l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_VLAN:
|
case LAYER_PROTO_VLAN:
|
||||||
used = vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_PPPOE:
|
case LAYER_PROTO_PPPOE:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_MPLS:
|
case LAYER_PROTO_MPLS:
|
||||||
used = mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buff + used, size - used);
|
||||||
break;
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_IPV4:
|
case LAYER_PROTO_IPV4:
|
||||||
used = ip4_hdr_to_str((const struct ip *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += ip4_hdr_to_str((const struct ip *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_IPV6:
|
case LAYER_PROTO_IPV6:
|
||||||
used = ip6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += ip6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_IPAH:
|
case LAYER_PROTO_IPAH:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_GRE:
|
case LAYER_PROTO_GRE:
|
||||||
used = gre_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buffer, sizeof(buffer));
|
used += gre_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_UDP:
|
case LAYER_PROTO_UDP:
|
||||||
used = udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_TCP:
|
case LAYER_PROTO_TCP:
|
||||||
used = tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_ICMP:
|
case LAYER_PROTO_ICMP:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_ICMP6:
|
case LAYER_PROTO_ICMP6:
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_VXLAN:
|
case LAYER_PROTO_VXLAN:
|
||||||
used = vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
|
used += vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
case LAYER_PROTO_GTP_C:
|
case LAYER_PROTO_GTP_C:
|
||||||
case LAYER_PROTO_GTP_U:
|
case LAYER_PROTO_GTP_U:
|
||||||
used = gtp_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buffer, sizeof(buffer));
|
used += gtp_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used);
|
||||||
|
used += snprintf(buff + used, size - used, "\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (used)
|
|
||||||
{
|
|
||||||
printf(" %s\n", buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return used;
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,20 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len);
|
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len);
|
||||||
void packet_print(const struct packet *pkt);
|
|
||||||
|
// bref : 1, output packet bref info
|
||||||
|
// bref : 0, output packet detail info
|
||||||
|
int packet_to_str(const struct packet *pkt, char *buff, int size);
|
||||||
|
|
||||||
|
static inline void packet_print(const struct packet *pkt)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
packet_to_str(pkt, buff, sizeof(buff));
|
||||||
|
printf("%s\n", buff);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "packet_layer.h"
|
#include "packet_layer.h"
|
||||||
#include "packet_parse.h"
|
#include "packet_parse.h"
|
||||||
#include "packet_craft.h"
|
#include "packet_craft.h"
|
||||||
|
#include "packet_utils.h"
|
||||||
|
|
||||||
#define PRINT_GREEN(fmt, ...) printf("\033[0;32m" fmt "\033[0m\n", ##__VA_ARGS__)
|
#define PRINT_GREEN(fmt, ...) printf("\033[0;32m" fmt "\033[0m\n", ##__VA_ARGS__)
|
||||||
#define PRINT_RED(fmt, ...) printf("\033[0;31m" fmt "\033[0m\n", ##__VA_ARGS__)
|
#define PRINT_RED(fmt, ...) printf("\033[0;31m" fmt "\033[0m\n", ##__VA_ARGS__)
|
||||||
@@ -191,6 +192,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_TCP)
|
|||||||
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
||||||
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -336,6 +339,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_IP6_TCP)
|
|||||||
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
||||||
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -574,6 +579,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
|
|||||||
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
||||||
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -780,6 +787,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_GRE_IP6_TCP)
|
|||||||
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
||||||
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1011,6 +1020,8 @@ TEST(PACKET_CRAFT_UDP, ETH_VLAN_IPv6_IPv4_GRE_PPP_IPv4_UDP_DNS)
|
|||||||
printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
|
||||||
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet_free(new_pkt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -494,12 +494,25 @@ static void tcp_flags_to_str(uint8_t flags, char *buffer, size_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int session_to_json(struct session *sess, char *buff, int size)
|
int session_to_str(const struct session *sess, int bref, char *buff, int size)
|
||||||
{
|
{
|
||||||
memset(buff, 0, size);
|
memset(buff, 0, size);
|
||||||
char flags[64] = {0};
|
char flags[64] = {0};
|
||||||
int used = 0;
|
int used = 0;
|
||||||
|
|
||||||
|
if (bref)
|
||||||
|
{
|
||||||
|
used += snprintf(buff + used, size - used, "session id: %lu, addr: %s, type: %s, state: %s, dir: %s, c2s_rx_pkts: %lu, s2c_rx_pkts: %lu",
|
||||||
|
session_get_id(sess),
|
||||||
|
session_get0_readable_addr(sess),
|
||||||
|
session_type_to_str(session_get_type(sess)),
|
||||||
|
session_state_to_str(session_get_current_state(sess)),
|
||||||
|
flow_direction_to_str(session_get_current_flow_direction(sess)),
|
||||||
|
session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED),
|
||||||
|
session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
used += snprintf(buff + used, size - used, "{");
|
used += snprintf(buff + used, size - used, "{");
|
||||||
used += snprintf(buff + used, size - used, "\"id\":%" PRIu64 ",", session_get_id(sess));
|
used += snprintf(buff + used, size - used, "\"id\":%" PRIu64 ",", session_get_id(sess));
|
||||||
used += snprintf(buff + used, size - used, "\"start_timestamp\":%" PRIu64 ",", session_get_timestamp(sess, SESSION_TIMESTAMP_START));
|
used += snprintf(buff + used, size - used, "\"start_timestamp\":%" PRIu64 ",", session_get_timestamp(sess, SESSION_TIMESTAMP_START));
|
||||||
@@ -587,13 +600,7 @@ int session_to_json(struct session *sess, char *buff, int size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
used += snprintf(buff + used, size - used, "}");
|
used += snprintf(buff + used, size - used, "}");
|
||||||
|
}
|
||||||
|
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_print(struct session *sess)
|
|
||||||
{
|
|
||||||
char buff[4096];
|
|
||||||
session_to_json(sess, buff, sizeof(buff));
|
|
||||||
printf("%s\n", buff);
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "stellar/session.h"
|
#include "stellar/session.h"
|
||||||
|
|
||||||
@@ -131,8 +132,16 @@ const char *session_state_to_str(enum session_state state);
|
|||||||
const char *session_type_to_str(enum session_type type);
|
const char *session_type_to_str(enum session_type type);
|
||||||
const char *flow_direction_to_str(enum flow_direction dir);
|
const char *flow_direction_to_str(enum flow_direction dir);
|
||||||
|
|
||||||
int session_to_json(struct session *sess, char *buff, int size);
|
// bref : 1, output session bref info
|
||||||
void session_print(struct session *sess);
|
// bref : 0, output session detail info
|
||||||
|
int session_to_str(const struct session *sess, int bref, char *buff, int size);
|
||||||
|
|
||||||
|
static inline void session_print(const struct session *sess)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
session_to_str(sess, 0, buff, sizeof(buff));
|
||||||
|
printf("%s\n", buff);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
add_subdirectory(packet_inject)
|
add_subdirectory(packet_inject)
|
||||||
add_subdirectory(packet_tool)
|
add_subdirectory(packet_tool)
|
||||||
|
add_subdirectory(debug_plugin)
|
||||||
8
test/debug_plugin/CMakeLists.txt
Normal file
8
test/debug_plugin/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# build libdebug_plugin.so
|
||||||
|
add_library(debug_plugin SHARED debug_plugin.cpp)
|
||||||
|
# Note: The debug plugin here uses stellar_core instead of stellar_devel, in order to output more session/packet information for development debugging.
|
||||||
|
target_link_libraries(debug_plugin stellar_core toml)
|
||||||
|
target_include_directories(debug_plugin PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||||
|
set_target_properties(debug_plugin PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/version.map")
|
||||||
|
|
||||||
|
file(COPY ./conf/ DESTINATION ./conf/)
|
||||||
4
test/debug_plugin/conf/spec.toml
Normal file
4
test/debug_plugin/conf/spec.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[[plugin]]
|
||||||
|
path = "./plugin/libdebug_plugin.so"
|
||||||
|
init = "debug_plugin_init"
|
||||||
|
exit = "debug_plugin_exit"
|
||||||
196
test/debug_plugin/debug_plugin.cpp
Normal file
196
test/debug_plugin/debug_plugin.cpp
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "hexdump.h"
|
||||||
|
#include "session_utils.h"
|
||||||
|
#include "tcp_reassembly.h"
|
||||||
|
#include "packet_dump.h"
|
||||||
|
#include "packet_parse.h"
|
||||||
|
#include "packet_utils.h"
|
||||||
|
#include "stellar/session_mq.h"
|
||||||
|
|
||||||
|
// NOTE: packet hexdump or tcp segment hexdump may be too long, so we need direct output to fd, instead of using log_print
|
||||||
|
static void log_print(int fd, const char *module, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||||
|
static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
|
||||||
|
int nwrite;
|
||||||
|
char buf[4096 * 2] = {0};
|
||||||
|
char *p = buf;
|
||||||
|
char *end = buf + sizeof(buf);
|
||||||
|
va_list args;
|
||||||
|
struct tm local;
|
||||||
|
|
||||||
|
time_t t;
|
||||||
|
time(&t);
|
||||||
|
localtime_r(&t, &local);
|
||||||
|
|
||||||
|
// add time
|
||||||
|
p += snprintf(p, end - p, "%s %s %d %02d:%02d:%02d %d ",
|
||||||
|
weekday_str[local.tm_wday], month_str[local.tm_mon], local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec, local.tm_year + 1900);
|
||||||
|
// add tid
|
||||||
|
p += snprintf(p, end - p, "%lu ", pthread_self());
|
||||||
|
// add module
|
||||||
|
p += snprintf(p, end - p, "(%s), ", module);
|
||||||
|
// add content
|
||||||
|
va_start(args, fmt);
|
||||||
|
p += vsnprintf(p, end - p, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
// add end of line
|
||||||
|
p += snprintf(p, end - p, "\n");
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nwrite = write(fd, buf, p - buf);
|
||||||
|
} while (nwrite == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct plugin_ctx
|
||||||
|
{
|
||||||
|
struct stellar *st;
|
||||||
|
int sess_plug_id;
|
||||||
|
int tcp_topic_id;
|
||||||
|
int udp_topic_id;
|
||||||
|
int tcp_stream_topic_id;
|
||||||
|
int fd;
|
||||||
|
pthread_spinlock_t lock; // for hexdump thread safe
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *on_sess_new(struct session *sess, void *plugin_ctx)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
session_to_str(sess, 1, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "sess new: %s", buff);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_sess_free(struct session *sess, void *sess_ctx, void *plugin_ctx)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
session_to_str(sess, 0, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "sess free: %s", buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_sess_udp_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
struct packet *pkt = (struct packet *)msg;
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
session_to_str(sess, 1, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "on UDP msg: %s", buff);
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
packet_to_str(pkt, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "rx UDP packet: \n%s", buff);
|
||||||
|
|
||||||
|
pthread_spin_lock(&ctx->lock);
|
||||||
|
packet_dump_hex(pkt, ctx->fd);
|
||||||
|
pthread_spin_unlock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_sess_tcp_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
struct packet *pkt = (struct packet *)msg;
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
session_to_str(sess, 1, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "on TCP msg: %s", buff);
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
packet_to_str(pkt, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "rx TCP packet: \n%s", buff);
|
||||||
|
|
||||||
|
pthread_spin_lock(&ctx->lock);
|
||||||
|
packet_dump_hex(pkt, ctx->fd);
|
||||||
|
pthread_spin_unlock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_sess_tcp_stream_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
|
||||||
|
{
|
||||||
|
char buff[4096];
|
||||||
|
struct tcp_segment *seg = (struct tcp_segment *)msg;
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
session_to_str(sess, 1, buff, sizeof(buff) - 1);
|
||||||
|
log_print(ctx->fd, "debug plugin", "on TCP stream msg: %s", buff);
|
||||||
|
|
||||||
|
log_print(ctx->fd, "debug plugin", "rx TCP segment: len: %d, data: %p\n", seg->len, seg->data);
|
||||||
|
|
||||||
|
pthread_spin_lock(&ctx->lock);
|
||||||
|
hexdump_to_fd(ctx->fd, (const char *)seg->data, seg->len);
|
||||||
|
pthread_spin_unlock(&ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Plugin API
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
void *debug_plugin_init(struct stellar *st)
|
||||||
|
{
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)calloc(1, sizeof(struct plugin_ctx));
|
||||||
|
if (ctx == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->fd = open("./log/debug_plugin.log", O_WRONLY | O_APPEND | O_CREAT, 0644);
|
||||||
|
if (ctx->fd == -1)
|
||||||
|
{
|
||||||
|
ctx->fd = STDOUT_FILENO;
|
||||||
|
}
|
||||||
|
pthread_spin_init(&ctx->lock, PTHREAD_PROCESS_PRIVATE);
|
||||||
|
|
||||||
|
ctx->st = st;
|
||||||
|
ctx->sess_plug_id = stellar_session_plugin_register(st, on_sess_new, on_sess_free, ctx);
|
||||||
|
ctx->udp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_UDP);
|
||||||
|
ctx->tcp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP);
|
||||||
|
ctx->tcp_stream_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP_STREAM);
|
||||||
|
|
||||||
|
stellar_session_mq_subscribe(st, ctx->udp_topic_id, on_sess_udp_msg, ctx->sess_plug_id);
|
||||||
|
stellar_session_mq_subscribe(st, ctx->tcp_topic_id, on_sess_tcp_msg, ctx->sess_plug_id);
|
||||||
|
stellar_session_mq_subscribe(st, ctx->tcp_stream_topic_id, on_sess_tcp_stream_msg, ctx->sess_plug_id);
|
||||||
|
|
||||||
|
log_print(ctx->fd, "debug plugin", "init");
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_plugin_exit(void *plugin_ctx)
|
||||||
|
{
|
||||||
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
log_print(ctx->fd, "debug plugin", "exit");
|
||||||
|
if (ctx->fd > 0)
|
||||||
|
{
|
||||||
|
close(ctx->fd);
|
||||||
|
}
|
||||||
|
pthread_spin_destroy(&ctx->lock);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
test/debug_plugin/version.map
Normal file
7
test/debug_plugin/version.map
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
DEBUG_PLUGIN {
|
||||||
|
global:
|
||||||
|
debug_plugin_init;
|
||||||
|
debug_plugin_exit;
|
||||||
|
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user