From b58ecc09e6a34e7e9399647e660e7bf55ca2320d Mon Sep 17 00:00:00 2001 From: liuwentan Date: Wed, 17 May 2023 17:03:50 +0800 Subject: [PATCH] [BUGFIX]fix ip_matcher single ipv6 rule coredump --- .../ip_matcher/IntervalIndex/SuccinctHash.cpp | 5 +- scanner/ip_matcher/ip_matcher.h | 117 +++++------- test/CMakeLists.txt | 3 + test/ip_matcher_gtest.cpp | 174 ++++++++++++++++++ 4 files changed, 229 insertions(+), 70 deletions(-) create mode 100644 test/ip_matcher_gtest.cpp diff --git a/scanner/ip_matcher/IntervalIndex/SuccinctHash.cpp b/scanner/ip_matcher/IntervalIndex/SuccinctHash.cpp index bfa8c78..7e1a69d 100644 --- a/scanner/ip_matcher/IntervalIndex/SuccinctHash.cpp +++ b/scanner/ip_matcher/IntervalIndex/SuccinctHash.cpp @@ -94,7 +94,8 @@ long long CSuccinctHash::init(unsigned int keys[], unsigned int values[], unsign } int tn=m_RT[(1U<<(m_hash_bits-8))].A; - m_kv_ptr=new unsigned int[tn+1]; + m_kv_ptr=new unsigned int[tn+2](); + FOR(i, tn+1) m_kv_ptr[i]=0; FOR(i, num) { @@ -103,7 +104,7 @@ long long CSuccinctHash::init(unsigned int keys[], unsigned int values[], unsign unsigned int idx=rank(h); m_kv_ptr[idx]++; } - FOR(i, tn) m_kv_ptr[i+1]+=m_kv_ptr[i]; + FOR(i, tn+1) m_kv_ptr[i+1]+=m_kv_ptr[i]; m_kv_array=new unsigned int[2*num]; FOR(i, num) diff --git a/scanner/ip_matcher/ip_matcher.h b/scanner/ip_matcher/ip_matcher.h index cc8287c..b542edd 100644 --- a/scanner/ip_matcher/ip_matcher.h +++ b/scanner/ip_matcher/ip_matcher.h @@ -27,92 +27,73 @@ extern "C" { #endif - enum IP_TYPE - { - IPv4=4, - IPv6=6 + enum IP_TYPE { + IPv4 = 4, + IPv6 = 6 }; - /* ������ĵ���IPv4���� */ - struct ipv4_range - { - unsigned int start_ip; /* IP��Χ�½� */ - unsigned int end_ip; /* IP��Χ�Ͻ� */ + struct ipv4_range { + unsigned int start_ip; /* lower boundary(network-order) */ + unsigned int end_ip; /* upper boundary(network-order) */ }; - /* ������ĵ���IPv6���� */ - struct ipv6_range - { - unsigned int start_ip[4]; /* IP��Χ�½磬�� Big-Endian ģʽ�洢 */ - unsigned int end_ip[4]; /* IP��Χ�Ͻ磬�� Big-Endian ģʽ�洢 */ + struct ipv6_range { + unsigned int start_ip[4]; /* lower boundary(network-order) */ + unsigned int end_ip[4]; /* upper boundary(network-order) */ }; - /* ͨ�õ�ip�������� */ - struct ip_rule - { - enum IP_TYPE type; /* �������ͣ�ipv4��ipv6 */ - long long rule_id; /* ����ID */ - void* user_tag; /* �û��Զ������ݣ�����ʱ��ƥ�������� */ - union - { - struct ipv4_range ipv4_rule; /*������ĵ���IPv4����*/ - struct ipv6_range ipv6_rule; /*������ĵ���IPv6����*/ + /* common type for ip rule */ + struct ip_rule { + enum IP_TYPE type; /* IPv4 or IPv6 */ + long long rule_id; /* rule id */ + void *user_tag; /* point to user-defined data which will return with hit results */ + union { + struct ipv4_range ipv4_rule; + struct ipv6_range ipv6_rule; }; }; - /* ͨ�õĴ�ɨ���������� */ - struct ip_data - { - enum IP_TYPE type; /* �������ͣ�ipv4��ipv6 */ - union /* ����rule_type�������ݸ�����ipv4����ipv6 */ - { - unsigned int ipv4; /* ipv4����*/ - unsigned int ipv6[4]; /* ipv6���ݣ��� Big-Endian ģʽ�洢*/ + /* common type for scan data */ + struct ip_data { + enum IP_TYPE type; /* IPv4 or IPv6 */ + union { + unsigned int ipv4; /* network order */ + unsigned int ipv6[4]; /* network order */ }; }; - - /* ��������ʽ��ɨ�������� */ - struct scan_result - { - long long rule_id; /* �����ID */ - void * tag; /* �û��Զ������ݣ�����ʱ��ƥ�������� */ + /* data type for scan result */ + struct scan_result { + long long rule_id; /* rule id */ + void *tag; /* point to the same address as user_tag in struct ip_rule which has same rule_id */ }; - struct ip_matcher; - /* - ���ܣ���������Ĺ�������É?���� - ������ - rules[in]��һ��ip���� - rule_num[in]������������ï¿? - mem_use[out]���ڴ������� - ����ֵ�� - ipɨ����,���ؿ�ָ������ɨ����ʧ�� - */ - struct ip_matcher* ip_matcher_new(struct ip_rule * rules, size_t rule_num, size_t * mem_use); + /** + * @brief create an ip_matcher instance + * + * @param rules[input]: a set of ip rules + * @param rule_num[input]: the number of ip rules + * @param mem_use[output]: memory used by ip_matcher + */ + struct ip_matcher *ip_matcher_new(struct ip_rule *rules, size_t rule_num, size_t *mem_use); - /* - ���ܣ�����ipɨ�����������ip���ݽ���ɨ�� - ������ - matcher[in]��ipɨ���� - data[in]������Ĵ�É?��ip���� - result[in]�����ؽ���æ´?���� - size[in]���������Ĵ�С - ����ֵ�� - �����������ï¿?<=size��������ֵΪ-1��ʾ������ - - */ - int ip_matcher_match(struct ip_matcher* matcher, struct ip_data * data, - struct scan_result* result, size_t size); + /** + * @brief scan ip_data to find out if has matched rules in ip_matcher + * + * @param matcher[intput]: ip_matcher which created by ip_matcher_new + * @param data[intput]: ip_data to be scanned + * @param result[input]: result array to store the rule_id and user_tag if there are matching rules + * @param size[input]: result array size + */ + int ip_matcher_match(struct ip_matcher *matcher, struct ip_data *data, + struct scan_result *result, size_t size); - /* - ���ܣ�����һ��ipɨ���� - ������ - matcher[in]�������ٵ�ipɨ����ָ�� - */ - void ip_matcher_free(struct ip_matcher* matcher); + /** + * @brief destroy ip_matcher instance + */ + void ip_matcher_free(struct ip_matcher *matcher); #ifdef __cplusplus } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9c459d4..20ef57f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,6 +21,9 @@ target_link_libraries(maat_framework_perf_gtest maat_frame_static gtest_static) add_executable(adapter_hs_gtest adapter_hs_gtest.cpp) target_link_libraries(adapter_hs_gtest maat_frame_static gtest_static) +add_executable(ip_matcher_gtest ip_matcher_gtest.cpp) +target_link_libraries(ip_matcher_gtest maat_frame_static gtest_static) + add_executable(maat_ex_data_gtest maat_ex_data_gtest.cpp) target_link_libraries(maat_ex_data_gtest maat_frame_static gtest_static) diff --git a/test/ip_matcher_gtest.cpp b/test/ip_matcher_gtest.cpp new file mode 100644 index 0000000..4fbf5de --- /dev/null +++ b/test/ip_matcher_gtest.cpp @@ -0,0 +1,174 @@ +#include + +#include "log/log.h" +#include "ip_matcher.h" +#include "maat_utils.h" +#include "cJSON/cJSON.h" + +#define MAX_ARRAY_SIZE 6 + +struct log_handle *g_logger = NULL; + +TEST(ipv4_matcher_match, OneSingleIPv4Rule) { + const char *ip1_str = "192.168.0.1"; + struct ip_rule rule; + rule.rule_id = 100; + rule.type = IPv4; + int ret = ip_format2range(4, IP_FORMAT_RANGE, ip1_str, ip1_str, + &rule.ipv4_rule.start_ip, &rule.ipv4_rule.end_ip); + size_t mem_size = 0; + struct ip_matcher *matcher = ip_matcher_new(&rule, 1, &mem_size); + ASSERT_TRUE(matcher != NULL); + + struct ip_data data; + data.type = IPv4; + inet_pton(AF_INET, ip1_str, &data.ipv4); + data.ipv4 = ntohl(data.ipv4); + + struct scan_result results[MAX_ARRAY_SIZE]; + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 100); +} + +TEST(ipv4_matcher_match, MultiSingleIPv4Rule) { + const char *ip1_str = "192.168.0.1"; + const char *ip2_str = "192.168.0.2"; + const char *ip3_str = "192.168.0.3"; + struct ip_rule rule[3]; + rule[0].rule_id = 100; + rule[0].type = IPv4; + int ret = ip_format2range(4, IP_FORMAT_RANGE, ip1_str, ip1_str, + &rule[0].ipv4_rule.start_ip, &rule[0].ipv4_rule.end_ip); + EXPECT_EQ(ret, 0); + + rule[1].rule_id = 200; + rule[1].type = IPv4; + ret = ip_format2range(4, IP_FORMAT_RANGE, ip2_str, ip2_str, + &rule[1].ipv4_rule.start_ip, &rule[1].ipv4_rule.end_ip); + EXPECT_EQ(ret, 0); + + rule[2].rule_id = 300; + rule[2].type = IPv4; + ret = ip_format2range(4, IP_FORMAT_RANGE, ip3_str, ip3_str, + &rule[2].ipv4_rule.start_ip, &rule[2].ipv4_rule.end_ip); + EXPECT_EQ(ret, 0); + + size_t mem_size = 0; + struct ip_matcher *matcher = ip_matcher_new(rule, 3, &mem_size); + ASSERT_TRUE(matcher != NULL); + + struct ip_data data; + data.type = IPv4; + inet_pton(AF_INET, ip1_str, &data.ipv4); + data.ipv4 = ntohl(data.ipv4); + + struct scan_result results[MAX_ARRAY_SIZE]; + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 100); + + inet_pton(AF_INET, ip2_str, &data.ipv4); + data.ipv4 = ntohl(data.ipv4); + memset(results, 0, sizeof(results)); + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 200); + + inet_pton(AF_INET, ip3_str, &data.ipv4); + data.ipv4 = ntohl(data.ipv4); + memset(results, 0, sizeof(results)); + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 300); +} + +TEST(ipv6_matcher_match, OneSingleIPv6Rule) { + const char *ip1_str = "1001:da8:205:1::101"; + const char *ip2_str = "1001:da8:205:1::101"; + struct ip_rule rule; + rule.rule_id = 100; + rule.type = IPv6; + int ret = ip_format2range(6, IP_FORMAT_RANGE, ip1_str, ip2_str, + rule.ipv6_rule.start_ip, rule.ipv6_rule.end_ip); + EXPECT_EQ(ret, 0); + + size_t mem_size = 0; + struct ip_matcher *matcher = ip_matcher_new(&rule, 1, &mem_size); + ASSERT_TRUE(matcher != NULL); + + struct ip_data data; + data.type = IPv6; + inet_pton(AF_INET6, ip1_str, data.ipv6); + ipv6_ntoh(data.ipv6); + + struct scan_result results[MAX_ARRAY_SIZE]; + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 100); +} + +TEST(ipv6_matcher_match, MultiSingleIPv6Rule) { + const char *ip1_str = "1001:da8:205:1::101"; + const char *ip2_str = "1001:da8:205:1::102"; + const char *ip3_str = "1001:da8:205:1::103"; + struct ip_rule rule[3]; + rule[0].rule_id = 100; + rule[0].type = IPv6; + int ret = ip_format2range(6, IP_FORMAT_RANGE, ip1_str, ip1_str, + rule[0].ipv6_rule.start_ip, rule[0].ipv6_rule.end_ip); + EXPECT_EQ(ret, 0); + + rule[1].rule_id = 200; + rule[1].type = IPv6; + ret = ip_format2range(6, IP_FORMAT_RANGE, ip2_str, ip2_str, + rule[1].ipv6_rule.start_ip, rule[1].ipv6_rule.end_ip); + EXPECT_EQ(ret, 0); + + rule[2].rule_id = 300; + rule[2].type = IPv6; + ret = ip_format2range(6, IP_FORMAT_RANGE, ip3_str, ip3_str, + rule[2].ipv6_rule.start_ip, rule[2].ipv6_rule.end_ip); + EXPECT_EQ(ret, 0); + + size_t mem_size = 0; + struct ip_matcher *matcher = ip_matcher_new(rule, 3, &mem_size); + ASSERT_TRUE(matcher != NULL); + + struct ip_data data; + data.type = IPv6; + inet_pton(AF_INET6, ip1_str, data.ipv6); + ipv6_ntoh(data.ipv6); + + struct scan_result results[MAX_ARRAY_SIZE]; + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 100); + + memset(results, 0, sizeof(results)); + inet_pton(AF_INET6, ip2_str, data.ipv6); + ipv6_ntoh(data.ipv6); + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 200); + + memset(results, 0, sizeof(results)); + inet_pton(AF_INET6, ip3_str, data.ipv6); + ipv6_ntoh(data.ipv6); + ret = ip_matcher_match(matcher, &data, results, MAX_ARRAY_SIZE); + EXPECT_EQ(ret, 1); + EXPECT_EQ(results[0].rule_id, 300); +} + +int main(int argc, char **argv) +{ + int ret = 0; + ::testing::InitGoogleTest(&argc, argv); + g_logger = log_handle_create("./ip_matcher_gtest.log", 0); + + ret = RUN_ALL_TESTS(); + + log_handle_destroy(g_logger); + + return ret; +} \ No newline at end of file