Optimize integration testing
- Add injection package plug-in - Add libstellar_dynamic.so to facilitate unit testing of upper-level plug-ins
This commit is contained in:
30
test/packet_inject/CMakeLists.txt
Normal file
30
test/packet_inject/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
# build packet_injector
|
||||
add_executable(packet_injector packet_inject_main.cpp packet_inject_plugin.cpp)
|
||||
target_link_libraries(packet_injector "-rdynamic")
|
||||
target_link_libraries(packet_injector stellar_devel)
|
||||
|
||||
# build libpacket_inject_plugin.so
|
||||
add_library(packet_inject_plugin SHARED packet_inject_plugin.cpp)
|
||||
target_include_directories(packet_inject_plugin PUBLIC ${CMAKE_SOURCE_DIR}/include/)
|
||||
set_target_properties(packet_inject_plugin PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/version.map")
|
||||
|
||||
# build gtest
|
||||
function(packet_inject_add_case EXEC_NAME)
|
||||
add_executable(${EXEC_NAME} ${EXEC_NAME}.cpp packet_inject_main.cpp packet_inject_plugin.cpp packet_inject_test.cpp)
|
||||
target_link_libraries(${EXEC_NAME} "-rdynamic")
|
||||
target_link_libraries(${EXEC_NAME} stellar_devel gtest)
|
||||
gtest_discover_tests(${EXEC_NAME})
|
||||
endfunction()
|
||||
|
||||
include(GoogleTest)
|
||||
packet_inject_add_case(gtest_inject_tcp_rst_after_recv_syn_ack)
|
||||
packet_inject_add_case(gtest_inject_tcp_rst_after_recv_sub_ack)
|
||||
packet_inject_add_case(gtest_inject_tcp_rst_after_recv_c2s_first_payload)
|
||||
packet_inject_add_case(gtest_inject_tcp_rst_after_recv_s2c_first_payload)
|
||||
packet_inject_add_case(gtest_inject_tcp_payload_after_recv_c2s_first_payload)
|
||||
packet_inject_add_case(gtest_inject_tcp_payload_after_recv_s2c_first_payload)
|
||||
packet_inject_add_case(gtest_inject_tcp_payload_fin_rst_after_recv_c2s_first_payload)
|
||||
|
||||
file(COPY ./conf/ DESTINATION ./conf/)
|
||||
file(COPY ./pcap/ DESTINATION ./pcap/)
|
||||
file(COPY ./stellar_plugin/ DESTINATION ./stellar_plugin/)
|
||||
44
test/packet_inject/README.md
Normal file
44
test/packet_inject/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Inject Packet
|
||||
|
||||
## 捕包
|
||||
|
||||
``` shell
|
||||
/opt/tsg/mrzcpd/bin/mrpdump -- --pdump "dev_name=nf_0_fw,queue=*" --bpf-rule="host 192.0.2.110 and port 80" --dumpfile-path=/home/admin/fw.pcap
|
||||
tcpdump -i virtio_dign_c host 192.0.2.110 and port 80 -n -v -w virtio_dign_c.pcap
|
||||
tcpdump -i virtio_dign_s host 192.0.2.110 and port 80 -n -v -w virtio_dign_s.pcap
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
``` shell
|
||||
./packet_injector -t tcp-rst -c c2s-packet -n 1 # After recv SYN
|
||||
./packet_injector -t tcp-rst -c s2c-packet -n 1 # After recv SYN-ACK
|
||||
./packet_injector -t tcp-rst -c c2s-packet -n 2 # After recv Sub-ACK
|
||||
./packet_injector -t tcp-rst -c c2s-packet -n 3 # After recv First-Payload
|
||||
```
|
||||
|
||||
``` shell
|
||||
./packet_injector -t tcp-fin -c c2s-packet -n 1 # After recv SYN
|
||||
./packet_injector -t tcp-fin -c s2c-packet -n 1 # After recv SYN-ACK
|
||||
./packet_injector -t tcp-fin -c c2s-packet -n 2 # After recv Sub-ACK
|
||||
./packet_injector -t tcp-fin -c c2s-packet -n 3 # After recv First-Payload
|
||||
```
|
||||
|
||||
## 拨测
|
||||
|
||||
``` shell
|
||||
kubectl -n tsg-os-system exec -it dign-client-9h8rm -c dign-client sh
|
||||
curl -v http://http.badssl.selftest.gdnt-cloud.website --resolve "http.badssl.selftest.gdnt-cloud.website:80:192.0.2.110"
|
||||
```
|
||||
|
||||
## 结果
|
||||
|
||||
| -t | -c | -n | Note | result |
|
||||
| ----------- | ----------- | ----------- | ---------------------------- | ----------- |
|
||||
| tcp-rst | c2s-packet | 1 | After recv SYN | Failed |
|
||||
| tcp-rst | s2c-packet | 1 | After recv SYN-ACK | Success |
|
||||
| tcp-rst | c2s-packet | 2 | After recv Sub-ACK | Success |
|
||||
| tcp-rst | c2s-packet | 3 | After recv C2S First-Payload | Success |
|
||||
| tcp-rst | s2c-packet | 3 | After recv S2C First-payload | Success |
|
||||
| tcp-payload | c2s-packet | 3 | After recv C2S First-Payload | Success |
|
||||
| tcp-payload | s2c-packet | 3 | After recv S2C First-payload | Success |
|
||||
4
test/packet_inject/conf/log.toml
Normal file
4
test/packet_inject/conf/log.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[log]
|
||||
output = stderr # stderr, file
|
||||
level = DEBUG # TRACE, DEBUG, INFO, WARN, ERROR, FATAL
|
||||
file = "log/stellar.log"
|
||||
56
test/packet_inject/conf/stellar.toml
Normal file
56
test/packet_inject/conf/stellar.toml
Normal file
@@ -0,0 +1,56 @@
|
||||
[device]
|
||||
base = 1 # [0, 31]
|
||||
offset = 2 # [0, 127]
|
||||
|
||||
[packet_io]
|
||||
mode = marsio # dumpfile, marsio
|
||||
app_symbol = stellar
|
||||
dev_symbol = nf_0_fw
|
||||
|
||||
dumpfile_dir = "/tmp/dumpfile/"
|
||||
nr_threads = 1 # [1, 256]
|
||||
cpu_mask = [5]
|
||||
|
||||
[ip_reassembly]
|
||||
enable = 1
|
||||
timeout = 10000 # range: [1, 60000] (ms)
|
||||
bucket_entries = 8 # range: [1, 256] (must be power of 2)
|
||||
bucket_num = 4096 # range: [1, 4294967295]
|
||||
|
||||
[session_manager]
|
||||
# max session number
|
||||
max_tcp_session_num = 50000
|
||||
max_udp_session_num = 50000
|
||||
|
||||
# session overload evict
|
||||
tcp_overload_evict_old_sess = 1 # 1: evict old session, 0: bypass new session
|
||||
udp_overload_evict_old_sess = 1 # 1: evict old session, 0: bypass new session
|
||||
|
||||
# TCP timeout
|
||||
tcp_init_timeout = 50 # range: [1, 60000] (ms)
|
||||
tcp_handshake_timeout = 50 # range: [1, 60000] (ms)
|
||||
tcp_data_timeout = 50 # range: [1, 15999999000] (ms)
|
||||
tcp_half_closed_timeout = 50 # range: [1, 604800000] (ms)
|
||||
tcp_time_wait_timeout = 50 # range: [1, 600000] (ms)
|
||||
tcp_discard_timeout = 50 # range: [1, 15999999000] (ms)
|
||||
tcp_unverified_rst_timeout = 50 # range: [1, 600000] (ms)
|
||||
# UDP timeout
|
||||
udp_data_timeout = 50 # range: [1, 15999999000] (ms)
|
||||
udp_discard_timeout = 50 # range: [1, 15999999000] (ms)
|
||||
|
||||
# duplicate packet filter
|
||||
duplicated_packet_filter_enable = 1
|
||||
duplicated_packet_filter_capacity = 1000000 # range: [1, 4294967295]
|
||||
duplicated_packet_filter_timeout = 100 # range: [1, 60000] (ms)
|
||||
duplicated_packet_filter_error_rate = 0.00001 # range: [0.0, 1.0]
|
||||
|
||||
# evicted session filter
|
||||
evicted_session_filter_enable = 1
|
||||
evicted_session_filter_capacity = 1000000 # range: [1, 4294967295]
|
||||
evicted_session_filter_timeout = 100 # range: [1, 60000] (ms)
|
||||
evicted_session_filter_error_rate = 0.00001 # range: [0.0, 1.0]
|
||||
|
||||
# TCP reassembly (Per direction)
|
||||
tcp_reassembly_enable = 1
|
||||
tcp_reassembly_max_timeout = 10000 # range: [1, 60000] (ms)
|
||||
tcp_reassembly_max_segments = 128 # range: [2, 512]
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_PAYLOAD, AFTER_RECV_C2S_FIRST_PAYLOAD)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_payload_after_recv_c2s_first_payload");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_payload_after_recv_c2s_first_payload/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP Payload after receiving C2S first payload packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.212:54146-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.212:54146-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.212:54146-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.212:54146-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.212:54146-3.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.212:54146-3.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.212:54146-192.0.2.110:80-4.pcap",
|
||||
.inject_pcap = "inject-192.0.2.212:54146-192.0.2.110:80-4.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-payload", "-c", "c2s-packet", "-n", "3"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_PAYLOAD, AFTER_RECV_S2C_FIRST_PAYLOAD)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_payload_after_recv_s2c_first_payload");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_payload_after_recv_s2c_first_payload/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP Payload after receiving S2C first payload packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:48322-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:48322-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:48322-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:48322-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:48322-3.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:48322-3.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.213:48322-192.0.2.110:80-4.pcap",
|
||||
.inject_pcap = "inject-192.0.2.213:48322-192.0.2.110:80-4.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-payload", "-c", "s2c-packet", "-n", "3"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_PAYLOAD_FIN_RST, AFTER_RECV_C2S_FIRST_PAYLOAD)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_payload_fin_rst_after_recv_c2s_first_payload");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_payload_fin_rst_after_recv_c2s_first_payload/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP Payload & FIN & RST after receiving C2S first payload packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:37296-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:37296-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:37296-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:37296-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:37296-3.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:37296-3.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.213:37296-4.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.213:37296-4.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.213:37296-192.0.2.110:80-5.pcap",
|
||||
.inject_pcap = "inject-192.0.2.213:37296-192.0.2.110:80-5.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.213:37296-192.0.2.110:80-6.pcap",
|
||||
.inject_pcap = "inject-192.0.2.213:37296-192.0.2.110:80-6.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-payload-fin-rst", "-c", "c2s-packet", "-n", "3"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_RST, AFTER_RECV_C2S_FIRST_PAYLOAD)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_rst_after_recv_c2s_first_payload");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_rst_after_recv_c2s_first_payload/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP RST after receiving C2S first payload packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.211:35116-192.0.2.110:80-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.211:35116-192.0.2.110:80-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.211:35116-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.211:35116-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-rst", "-c", "c2s-packet", "-n", "3"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_RST, AFTER_RECV_S2C_FIRST_PAYLOAD)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_rst_after_recv_s2c_first_payload");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_rst_after_recv_s2c_first_payload/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP RST after receiving S2C first payload packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.211:54408-192.0.2.110:80-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.211:54408-192.0.2.110:80-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.211:54408-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.211:54408-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-rst", "-c", "s2c-packet", "-n", "3"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_RST, AFTER_RECV_SUB_ACK)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_rst_after_recv_sub_ack");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_rst_after_recv_sub_ack/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP RST after receiving SUB-ACK packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.211:42242-192.0.2.110:80-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.211:42242-192.0.2.110:80-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.211:42242-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.211:42242-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-rst", "-c", "c2s-packet", "-n", "2"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
|
||||
TEST(INJECT_IPV4_BASED_TCP_RST, AFTER_RECV_SYN_ACK)
|
||||
{
|
||||
char current_dir[1024] = {0};
|
||||
char work_dir[2048] = {0};
|
||||
char input_dir[2048] = {0};
|
||||
getcwd(current_dir, sizeof(current_dir));
|
||||
snprintf(work_dir, sizeof(work_dir), "%s/%s", current_dir, "inject_ipv4_based_tcp_rst_after_recv_syn_ack");
|
||||
snprintf(input_dir, sizeof(input_dir), "%s/%s", current_dir, "pcap/inject_ipv4_based_tcp_rst_after_recv_syn_ack/test/");
|
||||
|
||||
struct packet_inject_case test = {
|
||||
// descriptor
|
||||
.finish_clean_work_dir = 0,
|
||||
.descriptor = "Inject IPv4 based TCP RST after receiving SYN-ACK packet.",
|
||||
.work_dir = work_dir,
|
||||
|
||||
// prefix
|
||||
.input_prefix = input_dir,
|
||||
|
||||
// input pcap
|
||||
.input_pcap = "input.pcap",
|
||||
|
||||
// compare
|
||||
.compares = {
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.211:59942-192.0.2.110:80-1.pcap",
|
||||
.inject_pcap = "inject-192.0.2.211:59942-192.0.2.110:80-1.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = "expect-192.0.2.110:80-192.0.2.211:59942-2.pcap",
|
||||
.inject_pcap = "inject-192.0.2.110:80-192.0.2.211:59942-2.pcap",
|
||||
},
|
||||
{
|
||||
.expect_pcap = NULL,
|
||||
.inject_pcap = NULL,
|
||||
},
|
||||
},
|
||||
|
||||
// packet injector command
|
||||
.packet_injector_cmd = {"./packet_injector", "-t", "tcp-rst", "-c", "s2c-packet", "-n", "1"},
|
||||
.diff_skip_pattern = "-I frame.time -I frame.time_epoch -I ip.id -I ip.ttl -I ip.checksum -I tcp.checksum -I tcp.window_size",
|
||||
};
|
||||
|
||||
packet_inject_test(&test);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
166
test/packet_inject/packet_inject_main.cpp
Normal file
166
test/packet_inject/packet_inject_main.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "stellar_priv.h"
|
||||
#include "packet_inject_main.h"
|
||||
|
||||
struct packet_inject_rule rule = {0};
|
||||
|
||||
static void usage(char *cmd)
|
||||
{
|
||||
printf("Usage: %s [options]\n\n", cmd);
|
||||
printf("Options:\n");
|
||||
printf(" -h <ip> Host IP address\n");
|
||||
printf(" -p <port> Port number\n");
|
||||
printf(" -t <type> Type of manipulation\n");
|
||||
printf(" Options: tcp-rst, tcp-fin, tcp-payload, tcp-payload-fin-rst, udp-payload, ctrl-msg\n");
|
||||
printf(" -c <condition> Condition for manipulation\n");
|
||||
printf(" Options: c2s-packet, s2c-packet\n");
|
||||
printf(" -n <number> Number of packets received before injecting action\n\n");
|
||||
printf("Example:\n");
|
||||
printf(" %s -h 192.168.1.100 -p 8080 -t tcp-payload -c c2s-packet -n 5\n", cmd);
|
||||
printf(" %s -h 2001:db8::1 -p 8080 -t tcp-rst -c s2c-packet -n 10\n", cmd);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int parse_cmd(int argc, char **argv)
|
||||
{
|
||||
int opt = 0;
|
||||
const char *host = NULL;
|
||||
const char *type = NULL;
|
||||
const char *condition = NULL;
|
||||
while ((opt = getopt(argc, argv, "h:p:t:c:n:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'h':
|
||||
host = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
rule.port = htons(atoi(optarg));
|
||||
break;
|
||||
case 't':
|
||||
type = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
condition = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
rule.number = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (host)
|
||||
{
|
||||
if (inet_pton(AF_INET, host, &rule.v4) != 1)
|
||||
{
|
||||
if (inet_pton(AF_INET6, host, &rule.v6) != 1)
|
||||
{
|
||||
printf("unable to convert host %s to IPv4 / IPv6\n", host);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rule.ip_type = 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rule.ip_type = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == NULL)
|
||||
{
|
||||
usage(argv[0]);
|
||||
printf("invalid type\n");
|
||||
return -1;
|
||||
}
|
||||
else if (strcmp(type, "tcp-rst") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_TCP_RST;
|
||||
}
|
||||
else if (strcmp(type, "tcp-fin") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_TCP_FIN;
|
||||
}
|
||||
else if (strcmp(type, "tcp-payload") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_TCP_PAYLOAD;
|
||||
}
|
||||
else if (strcmp(type, "tcp-payload-fin-rst") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_TCP_PAYLOAD_FIN_RST;
|
||||
}
|
||||
else if (strcmp(type, "udp-payload") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_UDP_PAYLOAD;
|
||||
}
|
||||
else if (strcmp(type, "ctrl-msg") == 0)
|
||||
{
|
||||
rule.inject_type = INJECT_TYPE_CTRL_MSG;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage(argv[0]);
|
||||
printf("invalid type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (condition == NULL)
|
||||
{
|
||||
usage(argv[0]);
|
||||
printf("invalid condition\n");
|
||||
return -1;
|
||||
}
|
||||
else if (strcmp(condition, "c2s-packet") == 0)
|
||||
{
|
||||
rule.direction = AFTER_RECV_C2S_N_PACKET;
|
||||
}
|
||||
else if (strcmp(condition, "s2c-packet") == 0)
|
||||
{
|
||||
rule.direction = AFTER_RECV_S2C_N_PACKET;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage(argv[0]);
|
||||
printf("invalid condition\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rule.number <= 0)
|
||||
{
|
||||
usage(argv[0]);
|
||||
printf("invalid count\n");
|
||||
return -1;
|
||||
}
|
||||
printf("%s load inject rule:\n", argv[0]);
|
||||
printf(" host : %s\n", host);
|
||||
printf(" port : %d\n", ntohs(rule.port));
|
||||
printf(" type : %s\n", type);
|
||||
printf(" condition : %s\n", condition);
|
||||
printf(" count : %lu\n\n", rule.number);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int packet_inject_main(int argc, char **argv)
|
||||
{
|
||||
if (parse_cmd(argc, argv) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stellar_main(argc, argv);
|
||||
}
|
||||
|
||||
int __attribute__((weak)) main(int argc, char **argv)
|
||||
{
|
||||
return packet_inject_main(argc, argv);
|
||||
}
|
||||
46
test/packet_inject/packet_inject_main.h
Normal file
46
test/packet_inject/packet_inject_main.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _PACKET_INJECT_MAIN_H
|
||||
#define _PACKET_INJECT_MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define AFTER_RECV_C2S_N_PACKET 1
|
||||
#define AFTER_RECV_S2C_N_PACKET 2
|
||||
|
||||
enum packet_inject_type
|
||||
{
|
||||
INJECT_TYPE_TCP_RST = 1,
|
||||
INJECT_TYPE_TCP_FIN = 2,
|
||||
INJECT_TYPE_TCP_PAYLOAD = 3,
|
||||
INJECT_TYPE_TCP_PAYLOAD_FIN_RST = 4,
|
||||
INJECT_TYPE_UDP_PAYLOAD = 5,
|
||||
INJECT_TYPE_CTRL_MSG = 6,
|
||||
};
|
||||
|
||||
struct packet_inject_rule
|
||||
{
|
||||
int ip_type;
|
||||
struct in_addr v4; /* network order */
|
||||
struct in6_addr v6; /* network order */
|
||||
int port; /* network order */
|
||||
|
||||
enum packet_inject_type inject_type;
|
||||
|
||||
// inject packet after (C2S/S2C) receiving n packets
|
||||
int direction; // AFTER_RECV_C2S_N_PACKET or AFTER_RECV_S2C_N_PACKET
|
||||
uint64_t number; // n packets received
|
||||
};
|
||||
|
||||
extern struct packet_inject_rule rule;
|
||||
|
||||
int packet_inject_main(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
146
test/packet_inject/packet_inject_plugin.cpp
Normal file
146
test/packet_inject/packet_inject_plugin.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stellar/tuple.h"
|
||||
#include "stellar/session_mq.h"
|
||||
#include "packet_inject_main.h"
|
||||
|
||||
struct packet_inject_plugin_ctx
|
||||
{
|
||||
struct stellar *st;
|
||||
int sess_plug_id;
|
||||
int tcp_topic_id;
|
||||
int udp_topic_id;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
static void *on_sess_new(struct session *sess, void *plugin_ctx)
|
||||
{
|
||||
struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx;
|
||||
printf("[%s] pluign handle session new: %s\n", ctx->name, session_get0_readable_addr(sess));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void on_sess_free(struct session *sess, void *sess_ctx, void *plugin_ctx)
|
||||
{
|
||||
struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx;
|
||||
printf("[%s] pluign handle session free: %s\n", ctx->name, session_get0_readable_addr(sess));
|
||||
}
|
||||
|
||||
static void on_sess_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
|
||||
{
|
||||
struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx;
|
||||
printf("[%s] pluign handle session msg: %s (C2S received packets: %lu, S2C received packets: %lu)\n",
|
||||
ctx->name, session_get0_readable_addr(sess),
|
||||
session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED),
|
||||
session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED));
|
||||
|
||||
char buffer[1024] = {0};
|
||||
// struct packet *pkt = (struct packet *)msg;
|
||||
const struct tuple6 *tuple = session_get_tuple6(sess);
|
||||
if (rule.ip_type == 4 &&
|
||||
memcmp(&tuple->src_addr.v4, &rule.v4, sizeof(struct in_addr)) &&
|
||||
memcmp(&tuple->dst_addr.v4, &rule.v4, sizeof(struct in_addr)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rule.ip_type == 6 &&
|
||||
memcmp(&tuple->src_addr.v6, &rule.v6, sizeof(struct in6_addr)) &&
|
||||
memcmp(&tuple->dst_addr.v6, &rule.v6, sizeof(struct in6_addr)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rule.port != 0 && tuple->src_port != rule.port && tuple->dst_port != rule.port)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_INJECTED_PACKETS_SUCCESS) > 0 ||
|
||||
session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_INJECTED_PACKETS_SUCCESS) > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rule.direction == AFTER_RECV_C2S_N_PACKET && session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED) != rule.number)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (rule.direction == AFTER_RECV_S2C_N_PACKET && session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED) != rule.number)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (rule.inject_type)
|
||||
{
|
||||
case INJECT_TYPE_TCP_RST:
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S);
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C);
|
||||
session_set_discard(sess);
|
||||
break;
|
||||
case INJECT_TYPE_TCP_FIN:
|
||||
stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_C2S);
|
||||
stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_S2C);
|
||||
session_set_discard(sess);
|
||||
break;
|
||||
case INJECT_TYPE_TCP_PAYLOAD:
|
||||
snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", 5 + 5 + 2, "Hello");
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_S2C, buffer, strlen(buffer)); // inject payload to client
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "World\r\n", 7); // inject payload to client
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C); // inject RST to client
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S); // inject RST to server
|
||||
session_set_discard(sess);
|
||||
break;
|
||||
case INJECT_TYPE_TCP_PAYLOAD_FIN_RST:
|
||||
snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", 5 + 5 + 2, "Hello");
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_S2C, buffer, strlen(buffer)); // inject payload to client
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "World\r\n", 7); // inject payload to client
|
||||
stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_S2C); // inject FIN to client
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C); // inject RST to client
|
||||
stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_C2S); // inject FIN to server
|
||||
stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S); // inject RST to server
|
||||
session_set_discard(sess);
|
||||
break;
|
||||
case INJECT_TYPE_UDP_PAYLOAD:
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_C2S, "Hello Server", 12);
|
||||
stellar_inject_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "Hello Client", 12);
|
||||
session_set_discard(sess);
|
||||
break;
|
||||
case INJECT_TYPE_CTRL_MSG:
|
||||
// TOOD
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void *packet_inject_plugin_init(struct stellar *st)
|
||||
{
|
||||
struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)calloc(1, sizeof(struct packet_inject_plugin_ctx));
|
||||
if (ctx == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ctx->st = st;
|
||||
ctx->sess_plug_id = stellar_session_plugin_register(st, on_sess_new, on_sess_free, ctx);
|
||||
ctx->tcp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP);
|
||||
ctx->udp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_UDP);
|
||||
snprintf(ctx->name, sizeof(ctx->name), "packet_inject");
|
||||
|
||||
stellar_session_mq_subscribe(st, ctx->tcp_topic_id, on_sess_msg, ctx->sess_plug_id);
|
||||
stellar_session_mq_subscribe(st, ctx->udp_topic_id, on_sess_msg, ctx->sess_plug_id);
|
||||
|
||||
printf("[%s] plugin init\n", ctx->name);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void packet_inject_plugin_exit(void *plugin_ctx)
|
||||
{
|
||||
struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx;
|
||||
if (ctx)
|
||||
{
|
||||
printf("[%s] plugin exit\n", ctx->name);
|
||||
free(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
181
test/packet_inject/packet_inject_test.cpp
Normal file
181
test/packet_inject/packet_inject_test.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packet_inject_test.h"
|
||||
#include "packet_inject_main.h"
|
||||
|
||||
static int args_len(const char **args)
|
||||
{
|
||||
int i = 0;
|
||||
while (args[i] != NULL)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void system_cmd(const char *cmd, ...)
|
||||
{
|
||||
char buf[1024] = {0};
|
||||
va_list args;
|
||||
|
||||
va_start(args, cmd);
|
||||
vsnprintf(buf, sizeof(buf), cmd, args);
|
||||
va_end(args);
|
||||
|
||||
system(buf);
|
||||
}
|
||||
|
||||
static int replace_file_string(const char *file, const char *old_str, const char *new_str)
|
||||
{
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
FILE *in_fp = fopen(file, "r");
|
||||
if (in_fp == NULL)
|
||||
{
|
||||
printf("Open file %s failed, %s\n", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *tmp_fp = tmpfile();
|
||||
if (tmp_fp == NULL)
|
||||
{
|
||||
printf("Create temporary file failed, %s\n", strerror(errno));
|
||||
fclose(in_fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t old_len = strlen(old_str);
|
||||
size_t new_len = strlen(new_str);
|
||||
char buff[BUFFER_SIZE];
|
||||
|
||||
while (fgets(buff, BUFFER_SIZE, in_fp))
|
||||
{
|
||||
char *pos = buff;
|
||||
if ((pos = strstr(pos, old_str)))
|
||||
{
|
||||
fwrite(buff, 1, pos - buff, tmp_fp); // Write characters before the old_str
|
||||
fwrite(new_str, 1, new_len, tmp_fp); // Write the new_str
|
||||
pos += old_len; // Move past the old_str
|
||||
fwrite(pos, 1, strlen(pos), tmp_fp); // Write characters after the old_str
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs(buff, tmp_fp); // Write the remaining part of the line
|
||||
}
|
||||
}
|
||||
|
||||
fclose(in_fp);
|
||||
fseek(tmp_fp, 0, SEEK_SET);
|
||||
|
||||
FILE *out_fp = fopen(file, "w");
|
||||
if (out_fp == NULL)
|
||||
{
|
||||
printf("Open file %s for writing failed, %s\n", file, strerror(errno));
|
||||
fclose(tmp_fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buff, BUFFER_SIZE, tmp_fp))
|
||||
{
|
||||
fputs(buff, out_fp); // Write the contents of the temporary file to the original file
|
||||
}
|
||||
|
||||
fclose(tmp_fp);
|
||||
fclose(out_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void expect_cmp_inject(const char *expect_pcap_file, const char *inject_pcap_file, const char *diff_skip_pattern, int idx)
|
||||
{
|
||||
struct stat s;
|
||||
char expect_pcap_json[1024] = {0};
|
||||
char inject_pcap_json[1024] = {0};
|
||||
char diff_json_txt[1024] = {0};
|
||||
|
||||
snprintf(expect_pcap_json, sizeof(expect_pcap_json), "expect_pcap_%d.json", idx);
|
||||
snprintf(inject_pcap_json, sizeof(inject_pcap_json), "inject_pcap_%d.json", idx);
|
||||
snprintf(diff_json_txt, sizeof(diff_json_txt), "json_diff_%d.txt", idx);
|
||||
|
||||
stat(expect_pcap_file, &s);
|
||||
EXPECT_TRUE(s.st_size > 0);
|
||||
|
||||
stat(inject_pcap_file, &s);
|
||||
EXPECT_TRUE(s.st_size > 0);
|
||||
|
||||
printf("\033[32m tcpdump read expect pcap (%s) \033[0m\n", expect_pcap_file);
|
||||
system_cmd("tcpdump -r %s", expect_pcap_file);
|
||||
|
||||
printf("\033[32m tcpdump read inject pcap (%s) \033[0m\n", inject_pcap_file);
|
||||
system_cmd("tcpdump -r %s", inject_pcap_file);
|
||||
|
||||
system_cmd("tshark -r %s -T json | jq >> %s", expect_pcap_file, expect_pcap_json);
|
||||
system_cmd("tshark -r %s -T json | jq >> %s", inject_pcap_file, inject_pcap_json);
|
||||
|
||||
stat(expect_pcap_json, &s);
|
||||
EXPECT_TRUE(s.st_size > 0);
|
||||
|
||||
stat(inject_pcap_json, &s);
|
||||
EXPECT_TRUE(s.st_size > 0);
|
||||
|
||||
system_cmd("diff %s %s %s >> %s", diff_skip_pattern, expect_pcap_json, inject_pcap_json, diff_json_txt);
|
||||
|
||||
stat(diff_json_txt, &s);
|
||||
EXPECT_TRUE(s.st_size == 0);
|
||||
}
|
||||
|
||||
void packet_inject_test(struct packet_inject_case *test)
|
||||
{
|
||||
printf("\033[32m ============================================= \033[0m\n");
|
||||
printf("\033[32mTest: %s\033[0m\n", test->descriptor);
|
||||
printf("\033[32m ============================================= \033[0m\n");
|
||||
|
||||
// create directory
|
||||
char dumpfile_dir[1024] = {0};
|
||||
snprintf(dumpfile_dir, sizeof(dumpfile_dir), "%s/input/", test->work_dir);
|
||||
system_cmd("rm -rf %s", test->work_dir);
|
||||
system_cmd("mkdir -p %s", dumpfile_dir);
|
||||
system_cmd("mkdir -p %s/log/", test->work_dir);
|
||||
|
||||
// copy file to work directory
|
||||
for (int i = 0; i < MAX_COMPARISON; i++)
|
||||
{
|
||||
if (test->compares[i].expect_pcap)
|
||||
{
|
||||
system_cmd("cp %s/%s %s", test->input_prefix, test->compares[i].expect_pcap, test->work_dir);
|
||||
}
|
||||
}
|
||||
system_cmd("cp %s/%s %s", test->input_prefix, test->input_pcap, dumpfile_dir);
|
||||
system_cmd("cp -r conf %s/", test->work_dir);
|
||||
system_cmd("cp -r stellar_plugin %s/", test->work_dir);
|
||||
system_cmd("cp -r libpacket_inject_plugin.so %s/", test->work_dir);
|
||||
|
||||
// run packet injector
|
||||
char cwd[2048] = {0};
|
||||
char temp[2048] = {0};
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
chdir(test->work_dir);
|
||||
snprintf(temp, sizeof(temp), "dumpfile_dir = \"%s\"", dumpfile_dir);
|
||||
EXPECT_TRUE(replace_file_string("./conf/stellar.toml", "mode = marsio", "mode = dumpfile") == 0);
|
||||
EXPECT_TRUE(replace_file_string("./conf/stellar.toml", "dumpfile_dir = \"/tmp/dumpfile/\"", temp) == 0);
|
||||
packet_inject_main(args_len(test->packet_injector_cmd), (char **)test->packet_injector_cmd);
|
||||
|
||||
// compare pcap
|
||||
for (int i = 0; i < MAX_COMPARISON; i++)
|
||||
{
|
||||
if (test->compares[i].expect_pcap && test->compares[i].inject_pcap)
|
||||
{
|
||||
expect_cmp_inject(test->compares[i].expect_pcap, test->compares[i].inject_pcap, test->diff_skip_pattern, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// clean work directory
|
||||
if (test->finish_clean_work_dir)
|
||||
{
|
||||
system_cmd("rm -rf %s", test->work_dir);
|
||||
}
|
||||
chdir(cwd);
|
||||
}
|
||||
36
test/packet_inject/packet_inject_test.h
Normal file
36
test/packet_inject/packet_inject_test.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _PACKET_INJECT_TEST_H
|
||||
#define _PACKET_INJECT_TEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define MAX_COMPARISON 16
|
||||
|
||||
struct packet_inject_case
|
||||
{
|
||||
int finish_clean_work_dir;
|
||||
const char *descriptor;
|
||||
const char *work_dir;
|
||||
|
||||
const char *input_prefix;
|
||||
const char *input_pcap;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *expect_pcap;
|
||||
const char *inject_pcap;
|
||||
} compares[MAX_COMPARISON];
|
||||
|
||||
const char *packet_injector_cmd[16];
|
||||
const char *diff_skip_pattern;
|
||||
};
|
||||
|
||||
void packet_inject_test(struct packet_inject_case *test);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
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.
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.
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.
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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
test/packet_inject/stellar_plugin/spec.toml
Normal file
4
test/packet_inject/stellar_plugin/spec.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[[plugin]]
|
||||
path = "./libpacket_inject_plugin.so"
|
||||
init = "packet_inject_plugin_init"
|
||||
exit = "packet_inject_plugin_exit"
|
||||
7
test/packet_inject/version.map
Normal file
7
test/packet_inject/version.map
Normal file
@@ -0,0 +1,7 @@
|
||||
LIBPACKET_INJECT_PLUGIN {
|
||||
global:
|
||||
packet_inject_plugin_init;
|
||||
packet_inject_plugin_exit;
|
||||
|
||||
local: *;
|
||||
};
|
||||
Reference in New Issue
Block a user