[BUGFIX]fix maat_compile_state_free null pointer

This commit is contained in:
liuwentan
2023-05-23 17:50:53 +08:00
parent 464dc43cc4
commit d70e56ec4f
9 changed files with 219 additions and 229 deletions

View File

@@ -55,16 +55,16 @@ bool operator!=(const uint128_t& lhs, const uint128_t& rhs)
return !(lhs==rhs); return !(lhs==rhs);
} }
//ִ<><D6B4>a-b<><62>aΪlhs<68><73>bΪrhs //ִ<><D6B4>a-b<><62>aΪlhs<68><73>bΪrhs
uint128_t operator-(const uint128_t& lhs, const uint128_t& rhs) uint128_t operator-(const uint128_t& lhs, const uint128_t& rhs)
{ {
uint128_t l = rhs; uint128_t l = rhs;
uint128_t h = lhs; uint128_t h = lhs;
unsigned long long I[2] = {0}; unsigned long long I[2] = {0};
if(h.I[0] < l.I[0])//<2F><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>λ if(h.I[0] < l.I[0])//<2F><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>λ
{ {
I[0] = ULONG_MAX - (l.I[0] - h.I[0]); I[0] = ULONG_MAX - (l.I[0] - h.I[0]);
h.I[1]--;//<2F><><EFBFBD><EFBFBD>λ<EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD>λ<EFBFBD><CEBB>Ҫ<EFBFBD><D2AA>1 h.I[1]--;//<2F><><EFBFBD><EFBFBD>λ<EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD>λ<EFBFBD><CEBB>Ҫ<EFBFBD><D2AA>1
} }
else else
{ {
@@ -131,24 +131,21 @@ CInt128IntervalIndex::~CInt128IntervalIndex()
long long CInt128IntervalIndex::PreProcessing(const vector<uint128_t>& a, const vector<uint128_t>& b) long long CInt128IntervalIndex::PreProcessing(const vector<uint128_t>& a, const vector<uint128_t>& b)
{ {
if(a.size()==0) return -1; if (a.size() == 0) {
return -1;
}
m_is_single = true; m_is_single = true;
for(unsigned int i=0; i<a.size(); i++) for (size_t i = 0; i < a.size(); i++) {
{ if (a[i] != b[i]) {
if(a[i]!=b[i])
{
m_is_single = false; m_is_single = false;
break; break;
} }
} }
if(m_is_single) if (m_is_single) {
{
return process_single(a); return process_single(a);
} } else {
else
{
return process_interval(a, b); return process_interval(a, b);
} }
} }
@@ -163,8 +160,7 @@ long long CInt128IntervalIndex::process_single(const vector<uint128_t>& a)
mem_bytes += (2 * sizeof(unsigned int) + sizeof(uint128_t)) * num; mem_bytes += (2 * sizeof(unsigned int) + sizeof(uint128_t)) * num;
for(unsigned int i=0; i<num; i++) for (unsigned int i = 0; i < num; i++) {
{
keys[i] = ipv6_hash(&a[i]); keys[i] = ipv6_hash(&a[i]);
values[i] = i; values[i] = i;
m_array[i] = a[i]; m_array[i] = a[i];
@@ -175,6 +171,7 @@ long long CInt128IntervalIndex::process_single(const vector<uint128_t>& a)
delete [] values; delete [] values;
if(ret<0) return -1; if(ret<0) return -1;
mem_bytes += ret; mem_bytes += ret;
return mem_bytes; return mem_bytes;
} }
@@ -186,26 +183,24 @@ long long CInt128IntervalIndex::process_interval(const vector<uint128_t>& a, con
set<uint128_t> s; set<uint128_t> s;
vector<unsigned int> IndexForMaxInt; vector<unsigned int> IndexForMaxInt;
vector<unsigned int> IndexForWholeInterval; vector<unsigned int> IndexForWholeInterval;
for(int i=0, n=(int)A.size(); i<n; i++)
{ for (int i = 0, n = (int)A.size(); i<n; i++) {
if (A[i] > B[i]) continue; if (A[i] > B[i]) continue;
if(B[i].is_all_ones()) if (B[i].is_all_ones()) {
{
IndexForMaxInt.push_back(i); IndexForMaxInt.push_back(i);
--B[i]; --B[i];
} }
++B[i]; // now A[i], B[i] is half closed interval. ++B[i]; // now A[i], B[i] is half closed interval.
if (A[i] >= B[i]) continue; if (A[i] >= B[i]) continue;
if(A[i].is_all_zeros() && B[i].is_all_ones()) if (A[i].is_all_zeros() && B[i].is_all_ones()) {
{
IndexForWholeInterval.push_back(i); IndexForWholeInterval.push_back(i);
continue; continue;
} }
s.insert(A[i]); s.insert(A[i]);
s.insert(B[i]); s.insert(B[i]);
} }
m_IndexForWholeInterval=new unsigned int[IndexForWholeInterval.size()+1]; m_IndexForWholeInterval=new unsigned int[IndexForWholeInterval.size()+1];
@@ -288,12 +283,9 @@ long long CInt128IntervalIndex::process_interval(const vector<uint128_t>& a, con
int CInt128IntervalIndex::Find(const uint128_t *key, unsigned int *result, unsigned int size) int CInt128IntervalIndex::Find(const uint128_t *key, unsigned int *result, unsigned int size)
{ {
if(m_is_single) if (m_is_single) {
{
return Find_single(key, result, size); return Find_single(key, result, size);
} } else {
else
{
return Find_interval(key, result, size); return Find_interval(key, result, size);
} }
} }
@@ -303,28 +295,25 @@ int CInt128IntervalIndex::Find_single(const uint128_t * key, unsigned int * resu
unsigned int h = ipv6_hash(key); unsigned int h = ipv6_hash(key);
int ret = m_ip_hash.find(h, result, size); int ret = m_ip_hash.find(h, result, size);
int j=0; int j=0;
for(int i=0; i<ret; i++)
{ for (int i = 0; i < ret; i++) {
if(*key == m_array[result[i]]) result[j++] = result[i]; if(*key == m_array[result[i]]) result[j++] = result[i];
} }
return j; return j;
} }
int CInt128IntervalIndex::Find_interval(const uint128_t *key, unsigned int *result, unsigned int size) int CInt128IntervalIndex::Find_interval(const uint128_t *key, unsigned int *result, unsigned int size)
{ {
if(key->is_all_ones()) if (key->is_all_ones()) {
{
unsigned int s = m_IndexForMaxInt[0]; unsigned int s = m_IndexForMaxInt[0];
if (s > size) s = size; if (s > size) s = size;
for(unsigned int i = 1; i <= s; i++) *result++=m_IndexForMaxInt[i]; for(unsigned int i = 1; i <= s; i++) *result++=m_IndexForMaxInt[i];
return s; return s;
} } else {
else
{
unsigned int s = m_IndexForWholeInterval[0]; unsigned int s = m_IndexForWholeInterval[0];
if (s > size) s = size; if (s > size) s = size;
for(unsigned int i=1; i<=s; i++) for (unsigned int i = 1; i <= s; i++) {
{
*result++=m_IndexForWholeInterval[i]; *result++=m_IndexForWholeInterval[i];
} }
size-=s; size-=s;
@@ -332,15 +321,17 @@ int CInt128IntervalIndex::Find_interval(const uint128_t * key, unsigned int * re
unsigned int k = t.I[0]&0xffff; unsigned int k = t.I[0]&0xffff;
long long l=m_L[k], h=m_L[k+1]; long long l=m_L[k], h=m_L[k+1];
long long m=0; long long m=0;
while(l<=h && m<m_iEndPointsNum)
{ while (l <= h && m < m_iEndPointsNum) {
m = (l+h)>>1; m = (l+h)>>1;
if(*key>=m_pEndPoints[m]) l=m+1; if (*key >= m_pEndPoints[m]) {
else h=m-1; l = m+1;
} else {
h = m-1;
}
} }
if(h>=m_L[k] && h<m_iEndPointsNum) if (h >= m_L[k] && h < m_iEndPointsNum) {
{
long long n = m_pIDPtr[h+1] - m_pIDPtr[h]; long long n = m_pIDPtr[h+1] - m_pIDPtr[h];
if (n > size) n = size; if (n > size) n = size;
unsigned int *id_list = m_pIDList + m_pIDPtr[h]; unsigned int *id_list = m_pIDList + m_pIDPtr[h];

View File

@@ -24,12 +24,10 @@ using namespace std;
struct uint128_t struct uint128_t
{ {
unsigned long long I[2];//<2F><>λ-><3E><>λ<EFBFBD><CEBB>I[1]I[0] unsigned long long I[2];//<2F><>λ-><3E><>λ<EFBFBD><CEBB>I[1]I[0]
uint128_t(const unsigned int * a=NULL) uint128_t(const unsigned int *a = NULL) {
{ if (a != NULL) {
if(a!=NULL)
{
I[0] = a[2]; I[0] = a[2];
I[0] = (I[0]<<32)|a[3]; I[0] = (I[0]<<32)|a[3];
I[1] = a[0]; I[1] = a[0];
@@ -37,28 +35,27 @@ struct uint128_t
} }
} }
uint128_t& operator=(const uint128_t& rhs) uint128_t& operator=(const uint128_t& rhs) {
{ for (int i = 0; i < 2; i++) {
for(int i=0; i<2; i++) I[i]=rhs.I[i]; I[i]=rhs.I[i];
}
return *this; return *this;
} }
uint128_t& operator--() uint128_t& operator--() {
{
if(I[0] == 0) I[1]--; if(I[0] == 0) I[1]--;
I[0]--; I[0]--;
return *this; return *this;
} }
uint128_t& operator++() uint128_t& operator++() {
{
I[0]++; I[0]++;
if (I[0] == 0) I[1]++; if (I[0] == 0) I[1]++;
return *this; return *this;
} }
uint128_t operator<<(int n) const uint128_t operator<<(int n) const {
{
uint128_t t = *this; uint128_t t = *this;
int k=n>>6; int k=n>>6;
n&=63; n&=63;
@@ -71,8 +68,7 @@ struct uint128_t
return t; return t;
} }
uint128_t operator>>(int n) const uint128_t operator>>(int n) const {
{
uint128_t t = *this; uint128_t t = *this;
int k=n>>6; int k=n>>6;
n&=63; n&=63;
@@ -86,8 +82,7 @@ struct uint128_t
} }
void ornot(unsigned int * mask) void ornot(unsigned int * mask) {
{
unsigned long long m = mask[1]; unsigned long long m = mask[1];
m = (m<<32)|mask[0]; m = (m<<32)|mask[0];
unsigned long long n = mask[3]; unsigned long long n = mask[3];
@@ -96,13 +91,11 @@ struct uint128_t
I[1] |= ~n; I[1] |= ~n;
} }
bool is_all_zeros() const bool is_all_zeros() const {
{
return (I[0] == 0)&&(I[1] == 0); return (I[0] == 0)&&(I[1] == 0);
} }
bool is_all_ones() const bool is_all_ones() const {
{
return ((~I[0])==0)&&((~I[1])==0); return ((~I[0])==0)&&((~I[1])==0);
} }
}; };

View File

@@ -31,16 +31,11 @@ struct ip_matcher
CRuleMatch *new_rule_matcher(enum IP_TYPE type) CRuleMatch *new_rule_matcher(enum IP_TYPE type)
{ {
if(type==IPv4) if (type == IPv4) {
{
return new CIPv4Match(); return new CIPv4Match();
} } else if(type == IPv6) {
else if(type==IPv6)
{
return new CIPv6Match(); return new CIPv6Match();
} } else {
else
{
return NULL; return NULL;
} }
} }
@@ -48,8 +43,7 @@ CRuleMatch * new_rule_matcher(enum IP_TYPE type)
struct ip_matcher *ip_matcher_new(struct ip_rule *rules, size_t rule_num, struct ip_matcher *ip_matcher_new(struct ip_rule *rules, size_t rule_num,
size_t *mem_use) size_t *mem_use)
{ {
if(rules == NULL || rule_num == 0) if (rules == NULL || rule_num == 0) {
{
return NULL; return NULL;
} }
@@ -62,8 +56,7 @@ struct ip_matcher * ip_matcher_new(struct ip_rule * rules, size_t rule_num,
map<long long, struct ip_rule> ipv4_rules; map<long long, struct ip_rule> ipv4_rules;
map<long long, struct ip_rule> ipv6_rules; map<long long, struct ip_rule> ipv6_rules;
for(size_t i = 0; i < rule_num; i++) for (size_t i = 0; i < rule_num; i++) {
{
long long id = rules[i].rule_id; long long id = rules[i].rule_id;
if(rules[i].type == IPv4) if(rules[i].type == IPv4)
ipv4_rules[id] = rules[i]; ipv4_rules[id] = rules[i];
@@ -72,12 +65,10 @@ struct ip_matcher * ip_matcher_new(struct ip_rule * rules, size_t rule_num,
} }
//<2F><><EFBFBD><EFBFBD>ipv4ɨ<34><C9A8><EFBFBD><EFBFBD> //<2F><><EFBFBD><EFBFBD>ipv4ɨ<34><C9A8><EFBFBD><EFBFBD>
if(ipv4_rules.size() != 0) if (ipv4_rules.size() != 0) {
{
CRuleMatch *v4_matcher = new CIPv4Match; CRuleMatch *v4_matcher = new CIPv4Match;
long long ret = v4_matcher->initialize(ipv4_rules); long long ret = v4_matcher->initialize(ipv4_rules);
if(ret<0) if (ret < 0) {
{
delete v4_matcher; delete v4_matcher;
v4_matcher = NULL; v4_matcher = NULL;
return NULL; return NULL;

View File

@@ -77,7 +77,8 @@ extern "C"
* @param rule_num[input]: the number of ip rules * @param rule_num[input]: the number of ip rules
* @param mem_use[output]: memory used by ip_matcher * @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); struct ip_matcher *ip_matcher_new(struct ip_rule *rules, size_t rule_num,
size_t *mem_use);
/** /**
* @brief scan ip_data to find out if has matched rules in ip_matcher * @brief scan ip_data to find out if has matched rules in ip_matcher

View File

@@ -25,7 +25,7 @@ using namespace std;
//#define DEBUG_IPV6_MATCH //#define DEBUG_IPV6_MATCH
bool cmp(ipv6_rule_t a, ipv6_rule_t b) bool cmp_ipv6_rule(ipv6_rule_t a, ipv6_rule_t b)
{ {
uint128_t l_a(a.rule.start_ip); uint128_t l_a(a.rule.start_ip);
@@ -33,7 +33,6 @@ bool cmp(ipv6_rule_t a, ipv6_rule_t b)
uint128_t l_b(b.rule.start_ip); uint128_t l_b(b.rule.start_ip);
uint128_t h_b(b.rule.end_ip); uint128_t h_b(b.rule.end_ip);
//<2F>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ipv6<76><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ
uint128_t interval_a = h_a - l_a; uint128_t interval_a = h_a - l_a;
uint128_t interval_b = h_b - l_b; uint128_t interval_b = h_b - l_b;
@@ -63,29 +62,27 @@ CIPv6Match::~CIPv6Match()
long long CIPv6Match::initialize(const map<long long, struct ip_rule>& rules) long long CIPv6Match::initialize(const map<long long, struct ip_rule>& rules)
{ {
m_rnum = rules.size(); m_rnum = rules.size();
if(m_rnum==0) return 0; if (m_rnum == 0) {
return 0;
}
long long mem_bytes = 0; long long mem_bytes = 0;
m_rules = new ipv6_rule_t[m_rnum]; m_rules = new ipv6_rule_t[m_rnum];
mem_bytes += (sizeof(struct ipv6_range) + sizeof(unsigned int) + sizeof(void *)) * m_rnum; mem_bytes += (sizeof(struct ipv6_range) + sizeof(unsigned int) + sizeof(void *)) * m_rnum;
unsigned int i = 0; unsigned int i = 0;
for(map<long long, struct ip_rule>::const_iterator it=rules.begin(); it!=rules.end(); ++it) for (map<long long, struct ip_rule>::const_iterator it = rules.begin(); it != rules.end(); ++it) {
{
struct ipv6_range arule = it->second.ipv6_rule;; struct ipv6_range arule = it->second.ipv6_rule;;
m_rules[i].rule = arule; m_rules[i].rule = arule;
m_rules[i].rule_id = it->first; m_rules[i].rule_id = it->first;
m_rules[i++].tag = it->second.user_tag; m_rules[i++].tag = it->second.user_tag;
} }
//<2F><><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD>ip<69>ķ<EFBFBD>Χ<EFBFBD><CEA7>С<EFBFBD><D0A1><EFBFBD><EFBFBD> sort(&m_rules[0], &m_rules[m_rnum], cmp_ipv6_rule);
sort(&m_rules[0], &m_rules[m_rnum],cmp);
vector<uint128_t> A, B; vector<uint128_t> A, B;
for(i = 0; i < m_rnum; i++) for (i = 0; i < m_rnum; i++) {
{
uint128_t a(m_rules[i].rule.start_ip); uint128_t a(m_rules[i].rule.start_ip);
uint128_t b(m_rules[i].rule.end_ip); uint128_t b(m_rules[i].rule.end_ip);
A.push_back(a); A.push_back(a);
@@ -94,10 +91,13 @@ long long CIPv6Match::initialize(const map<long long, struct ip_rule>& rules)
m_ipv6Indexer = new CInt128IntervalIndex; m_ipv6Indexer = new CInt128IntervalIndex;
mem_bytes += sizeof(CInt128IntervalIndex); mem_bytes += sizeof(CInt128IntervalIndex);
long long ret = m_ipv6Indexer->PreProcessing(A, B);
if(ret<0) return -1;
mem_bytes+=ret;
long long ret = m_ipv6Indexer->PreProcessing(A, B);
if (ret < 0) {
return -1;
}
mem_bytes += ret;
return mem_bytes; return mem_bytes;
} }

View File

@@ -388,6 +388,7 @@ void maat_free(struct maat *maat_instance)
while (0 == maat_instance->is_running) { while (0 == maat_instance->is_running) {
usleep(500 * 1000); usleep(500 * 1000);
} }
maat_instance->is_running = 0; maat_instance->is_running = 0;
pthread_join(maat_instance->cfg_mon_thread, &ret); pthread_join(maat_instance->cfg_mon_thread, &ret);
} }
@@ -443,6 +444,14 @@ int maat_table_callback_register(struct maat *maat_instance, int table_id,
pthread_mutex_lock(&(maat_instance->background_update_mutex)); pthread_mutex_lock(&(maat_instance->background_update_mutex));
void *schema = table_manager_get_schema(maat_instance->tbl_mgr, table_id); void *schema = table_manager_get_schema(maat_instance->tbl_mgr, table_id);
if (NULL == schema) {
pthread_mutex_unlock(&(maat_instance->background_update_mutex));
log_error(maat_instance->logger, MODULE_MAAT_API,
"[%s:%d] table(table_id:%d) schema is NULL, register callback failed",
__FUNCTION__, __LINE__, table_id);
return -1;
}
ret = plugin_table_add_callback(schema, table_id, start, update, finish, ret = plugin_table_add_callback(schema, table_id, start, update, finish,
u_para, maat_instance->logger); u_para, maat_instance->logger);
if (ret < 0) { if (ret < 0) {
@@ -456,10 +465,16 @@ int maat_table_callback_register(struct maat *maat_instance, int table_id,
} }
void *runtime = table_manager_get_runtime(maat_instance->tbl_mgr, table_id); void *runtime = table_manager_get_runtime(maat_instance->tbl_mgr, table_id);
enum table_type table_type = table_manager_get_table_type(maat_instance->tbl_mgr, table_id);
assert(table_type == TABLE_TYPE_PLUGIN);
size_t row_cnt = plugin_runtime_cached_row_count(runtime);
enum table_type table_type = table_manager_get_table_type(maat_instance->tbl_mgr, table_id);
if (table_type != TABLE_TYPE_PLUGIN) {
pthread_mutex_unlock(&(maat_instance->background_update_mutex));
log_error(maat_instance->logger, MODULE_MAAT_API,
"[%s:%d] table type:%d illegal", __FUNCTION__, __LINE__, table_type);
return -1;
}
size_t row_cnt = plugin_runtime_cached_row_count(runtime);
if (row_cnt > 0) { if (row_cnt > 0) {
if (start != NULL) { if (start != NULL) {
start(MAAT_UPDATE_TYPE_FULL, u_para); start(MAAT_UPDATE_TYPE_FULL, u_para);
@@ -1679,11 +1694,13 @@ void maat_state_free(struct maat_state *state)
return; return;
} }
assert(state->compile_state != NULL); if (state->compile_state != NULL) {
maat_compile_state_free(state->compile_state); maat_compile_state_free(state->compile_state);
state->compile_state = NULL; state->compile_state = NULL;
}
state->maat_instance = NULL; state->maat_instance = NULL;
free(state); FREE(state);
} }
int maat_state_set_scan_district(struct maat_state *state, int vtable_id, int maat_state_set_scan_district(struct maat_state *state, int vtable_id,

View File

@@ -1414,7 +1414,6 @@ int maat_remove_group_from_compile(struct rcu_hash_table *hash_tbl,
if (0 == copy_compile->actual_clause_num && NULL == copy_compile->user_data) { if (0 == copy_compile->actual_clause_num && NULL == copy_compile->user_data) {
maat_compile_free(copy_compile); maat_compile_free(copy_compile);
copy_compile = NULL;
} else { } else {
rcu_hash_add(hash_tbl, (char *)&compile_id, sizeof(long long), copy_compile); rcu_hash_add(hash_tbl, (char *)&compile_id, sizeof(long long), copy_compile);
} }
@@ -1706,7 +1705,6 @@ int compile_runtime_add_compile(struct compile_runtime *compile_rt, struct compi
struct compile_rule *compile_rule = compile_rule_new(compile_item, schema, table_name, line); struct compile_rule *compile_rule = compile_rule_new(compile_item, schema, table_name, line);
compile_item_free(compile_item); compile_item_free(compile_item);
compile_item = NULL;
int updating_flag = rcu_hash_is_updating(compile_rt->cfg_hash_tbl); int updating_flag = rcu_hash_is_updating(compile_rt->cfg_hash_tbl);
if (1 == updating_flag) { if (1 == updating_flag) {
@@ -1815,7 +1813,6 @@ void compile_runtime_del_compile(struct compile_runtime *compile_rt, long long c
if (0 == copy_compile->actual_clause_num) { if (0 == copy_compile->actual_clause_num) {
maat_compile_free(copy_compile); maat_compile_free(copy_compile);
copy_compile = NULL;
} else { } else {
rcu_hash_add(compile_rt->cfg_hash_tbl, (char *)&compile_id, rcu_hash_add(compile_rt->cfg_hash_tbl, (char *)&compile_id,
sizeof(long long), copy_compile); sizeof(long long), copy_compile);

View File

@@ -168,7 +168,7 @@ void fqdn_rule_free(struct FQDN_rule *fqdn_rule)
FREE(fqdn_rule->FQDN); FREE(fqdn_rule->FQDN);
} }
free(fqdn_rule); FREE(fqdn_rule);
} }
void *fqdn_plugin_runtime_new(void *fqdn_plugin_schema, size_t max_thread_num, void *fqdn_plugin_runtime_new(void *fqdn_plugin_schema, size_t max_thread_num,

View File

@@ -109,9 +109,9 @@ TEST(ipv6_matcher_match, OneSingleIPv6Rule) {
} }
TEST(ipv6_matcher_match, MultiSingleIPv6Rule) { TEST(ipv6_matcher_match, MultiSingleIPv6Rule) {
const char *ip1_str = "1001:da8:205:1::101"; const char *ip1_str = "2607:5d00:2:2::56:22";
const char *ip2_str = "1001:da8:205:1::102"; const char *ip2_str = "2607:5d00:2:2::50:25";
const char *ip3_str = "1001:da8:205:1::103"; const char *ip3_str = "2607:5d00:2:2::64:203";
struct ip_rule rule[3]; struct ip_rule rule[3];
rule[0].rule_id = 100; rule[0].rule_id = 100;
rule[0].type = IPv6; rule[0].type = IPv6;