diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index 124c9ad..ca557f3 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -293,14 +293,27 @@ typedef void Maat_plugin_EX_free_func_t(int table_id, MAAT_PLUGIN_EX_DATA* ad, l typedef void Maat_plugin_EX_dup_func_t(int table_id, MAAT_PLUGIN_EX_DATA *to, MAAT_PLUGIN_EX_DATA *from, long argl, void *argp); typedef int Maat_plugin_EX_key2index_func_t(const char* key); +//For IP plugin, key2index_func MUST be NULL. int Maat_plugin_EX_register(Maat_feather_t feather, int table_id, Maat_plugin_EX_new_func_t* new_func, Maat_plugin_EX_free_func_t* free_func, Maat_plugin_EX_dup_func_t* dup_func, Maat_plugin_EX_key2index_func_t* key2index_func, long argl, void *argp); -//Data is duplicated by dup_func of Maat_plugin_EX_register, caller is responsible to free the data. +//Data is duplicated by dup_func of Maat_plugin_EX_register, caller is responsible to FREE the data. MAAT_PLUGIN_EX_DATA Maat_plugin_get_EX_data(Maat_feather_t feather, int table_id, const char* key); +struct ip_address +{ + int ip_type; //4: IPv4, 6: IPv6 + union + { + unsigned int ipv4; //network order + unsigned int ipv6[4]; + }; +}; + +MAAT_PLUGIN_EX_DATA Maat_IP_plugin_get_EX_data(Maat_feather_t feather, int table_id, const struct ip_address* ip); + enum MAAT_RULE_OPT { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f19b34e..db42f65 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,7 @@ target_include_directories(maat_frame_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} #target_include_directories(maat_frame_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc_internal/hiredis) target_link_libraries(maat_frame_static hiredis-vip-static) target_link_libraries(maat_frame_static igraph-static) +target_link_libraries(maat_frame_static ipmatcher-static) # Shared Library Output add_library(maat_frame_shared SHARED ${MAAT_SRC}) @@ -34,6 +35,7 @@ target_include_directories(maat_frame_shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} target_include_directories(maat_frame_shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/inc_internal/hiredis) target_link_libraries(maat_frame_shared hiredis-vip-static ${MAAT_DEPEND_DYN_LIB}) target_link_libraries(maat_frame_shared igraph-static ${MAAT_DEPEND_DYN_LIB}) +target_link_libraries(maat_frame_shared ipmatcher-static) install(FILES ${PROJECT_SOURCE_DIR}/inc/Maat_rule.h DESTINATION /opt/MESA/include/MESA/ COMPONENT HEADER) install(FILES ${PROJECT_SOURCE_DIR}/inc/Maat_command.h DESTINATION /opt/MESA/include/MESA/ COMPONENT HEADER) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index c8122a6..cd031a2 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1380,6 +1380,27 @@ MAAT_PLUGIN_EX_DATA Maat_plugin_get_EX_data(Maat_feather_t feather, int table_id exdata=Maat_table_runtime_plugin_get_ex_data(table_rt, table_desc, key); return exdata; } +int Maat_IP_plugin_get_EX_data(Maat_feather_t feather, int table_id, const struct ip_address* ip, MAAT_PLUGIN_EX_DATA* ex_data_array, size_t n_ex_data) +{ + struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; + struct Maat_table_schema *table_desc=NULL; + struct Maat_table_runtime *table_rt=NULL; + int n_get=0; + if(_feather->scanner==NULL) + { + return 0; + } + table_desc=Maat_table_get_scan_by_id(_feather->table_mgr, table_id, TABLE_TYPE_PLUGIN, NULL); + table_rt=Maat_table_runtime_get(_feather->scanner->table_rt_mgr, table_id); + if(table_rt->table_type!=TABLE_TYPE_IP_PLUGIN) + { + return -1; + } + + n_get=Maat_table_runtime_ip_plugin_get_N_ex_data(table_rt, table_desc, ip, ex_data_array, n_ex_data); + return n_get; + +} int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id ,enum MAAT_CHARSET charset,const char* data,int data_len diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index b6aaca5..34c2eed 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -2410,142 +2410,7 @@ error_out: free(maat_str_rule); maat_str_rule=NULL; } -enum MAAT_IP_FORMAT -{ - FORMAT_RANGE, - FORMAT_MASK, - FORMAT_CIDR, - FORMAT_UNKNOWN -}; -enum MAAT_IP_FORMAT ip_format_str2int(const char* format) -{ - if(0==strcasecmp(format, "range")) - { - return FORMAT_RANGE; - } - else if(0==strcasecmp(format, "mask")) - { - return FORMAT_MASK; - } - else if(0==strcasecmp(format, "CIDR")) - { - return FORMAT_CIDR; - } - else - { - assert(0); - } - return FORMAT_UNKNOWN; -} -int ip_format2range(int ip_type, enum MAAT_IP_FORMAT format, const char* ip1, const char* ip2, unsigned int range_begin[], unsigned int range_end[]) -{ - unsigned int ipv4_addr=0, ipv4_mask=0, ipv4_range_end=0; - unsigned int ipv6_addr[4]={0}, ipv6_mask[4]={0}, ipv6_range_end[4]={0}; - int cidr=0, bit32=0; - int ret=0, i=0; - if(ip_type!=4 && ip_type!=6) - { - assert(0); - return -1; - } - if(ip_type==4) - { - ret=inet_pton(AF_INET, ip1, &ipv4_addr); - if(ret<=0) - { - return -1; - } - ipv4_addr=ntohl(ipv4_addr); - switch (format) - { - case FORMAT_RANGE: - range_begin[0]=ipv4_addr; - ret=inet_pton(AF_INET, ip2, &ipv4_range_end); - if(ret<=0) - { - return -1; - } - ipv4_range_end=ntohl(ipv4_range_end); - range_end[0]=ipv4_range_end; - break; - case FORMAT_MASK: - ret=inet_pton(AF_INET, ip2, &ipv4_mask); - if(ret<=0) - { - return -1; - } - ipv4_mask=ntohl(ipv4_mask); - range_begin[0]=ipv4_addr&ipv4_mask; - range_end[0]=ipv4_addr|~ipv4_mask; - break; - case FORMAT_CIDR: - cidr=atoi(ip2); - if(cidr>32||cidr<0) - { - return -1; - } - ipv4_mask = (0xFFFFFFFFUL << (32 - cidr)) & 0xFFFFFFFFUL; - range_begin[0]=ipv4_addr&ipv4_mask; - range_end[0]=ipv4_addr|~ipv4_mask; - break; - default: - assert(0); - } - } - else //ipv6 - { - ret=inet_pton(AF_INET6, ip1, ipv6_addr); - if(ret<=0) - { - return -1; - } - ipv6_ntoh(ipv6_addr); - switch(format) - { - case FORMAT_RANGE: - ret=inet_pton(AF_INET6, ip2, ipv6_range_end); - if(ret<=0) - { - return -1; - } - ipv6_ntoh(ipv6_range_end); - memcpy(range_begin, ipv6_addr, sizeof(ipv6_addr)); - memcpy(range_end, ipv6_range_end, sizeof(ipv6_range_end)); - break; - case FORMAT_MASK: - ret=inet_pton(AF_INET6, ip2, ipv6_mask); - if(ret<=0) - { - return -1; - } - ipv6_ntoh(ipv6_mask); - for(i=0; i<4; i++) - { - range_begin[i]=ipv6_addr[i]&ipv6_mask[i]; - range_end[i] = ipv6_addr[i]|~ipv6_mask[i]; - } - break; - case FORMAT_CIDR: - cidr=atoi(ip2); - if(cidr>128||cidr<0) - { - return -1; - } - for(i=0; i<4; i++) - { - bit32=128-cidr-32*(3-i); - if(bit32<0) bit32=0; - ipv6_mask[i]=(0xFFFFFFFFUL << bit32) & 0xFFFFFFFFUL; - range_begin[i]=ipv6_addr[i]&ipv6_mask[i]; - range_end[i] = ipv6_addr[i]|~ipv6_mask[i]; - } - break; - default: - assert(0); - } - } - return 0; -} + void update_ip_rule(struct Maat_table_schema* table, const char* table_line, struct Maat_scanner *scanner, void* logger) { struct db_ip_rule_t* ip_rule=(struct db_ip_rule_t*)calloc(sizeof(struct db_ip_rule_t),1); @@ -3032,12 +2897,12 @@ void garbage_bagging_with_timeout(enum maat_garbage_type type,void *p, int timeo MESA_lqueue_join_tail(garbage_q,&bag,sizeof(void*)); return; } -void garbage_bagging(enum maat_garbage_type type,void *p,MESA_lqueue_head garbage_q) +void garbage_bagging(enum maat_garbage_type type, void *p, MESA_lqueue_head garbage_q) { garbage_bagging_with_timeout(type, p, -1, garbage_q); return; } -void garbage_bury(MESA_lqueue_head garbage_q,int timeout,void *logger) +void garbage_bury(MESA_lqueue_head garbage_q, int timeout, void *logger) { UNUSED MESA_queue_errno_t q_ret=MESA_QUEUE_RET_OK; _maat_garbage_t* bag=NULL; @@ -3117,6 +2982,10 @@ void garbage_bury(MESA_lqueue_head garbage_q,int timeout,void *logger) free(bag->filename); bag->filename=NULL; break; + case GARBAGE_IP_MATCHER: + ip_matcher_free(bag->a_ip_matcher); + bag->a_ip_matcher=NULL; + break; default: assert(0); } @@ -3131,7 +3000,7 @@ void garbage_bury(MESA_lqueue_head garbage_q,int timeout,void *logger) q_cnt,bury_cnt); } } -void update_plugin_table(struct Maat_table_schema* table,const char* table_line,Maat_scanner* scanner, const struct rule_tag* tags, int n_tags, void* logger) +void update_plugin_table(struct Maat_table_schema* table, const char* table_line, Maat_scanner* scanner, const struct rule_tag* tags, int n_tags, void* logger) { int i=0, ret=1, matched_tag=1; unsigned int len=strlen(table_line)+1; @@ -3193,14 +3062,14 @@ void update_plugin_table(struct Maat_table_schema* table,const char* table_line, } else { - plugin_EX_data_free(table, table_line, table_rt->plugin.key2ex_hash, logger); + plugin_EX_data_free(table_line, plugin_desc->key_column, table_rt->plugin.key2ex_hash, logger); } } if(plugin_desc->cb_plug_cnt>0) { for(i=0;icb_plug_cnt;i++) { - plugin_desc->cb_plug[i].update(table->table_id,table_line,plugin_desc->cb_plug[i].u_para); + plugin_desc->cb_plug[i].update(table->table_id, table_line, plugin_desc->cb_plug[i].u_para); } } @@ -3210,10 +3079,77 @@ void update_plugin_table(struct Maat_table_schema* table,const char* table_line, p=ALLOC(char, len); memcpy(p,table_line,len); table_rt->plugin.cache_size+=len; - dynamic_array_write(table_rt->plugin.cache_lines,table_rt->plugin.cache_line_num,p); + dynamic_array_write(table_rt->plugin.cache_lines, table_rt->plugin.cache_line_num, p); table_rt->plugin.cache_line_num++; } } +void update_ip_plugin_table(struct Maat_table_schema* table,const char* table_line,Maat_scanner* scanner, const struct rule_tag* tags, int n_tags, void* logger) +{ + int ret=1, matched_tag=1; + struct ip_plugin_table_schema* ip_plugin_schema=&(table->ip_plugin); + struct Maat_table_runtime* table_rt=Maat_table_runtime_get(scanner->table_rt_mgr, table->table_id); + struct ip_plugin_runtime* ip_plugin_rt=&(table_rt->ip_plugin); + char* copy=NULL; + size_t is_valid_offset=0, valid_len=0; + size_t accept_tag_offset=0, accept_tag_len=0; + if(ip_plugin_schema->rule_tag_column>0&&n_tags>0) + { + ret=Maat_helper_read_column(table_line, ip_plugin_schema->rule_tag_column, &accept_tag_offset, &accept_tag_len); + if(ret<0) + { + MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , + "update error, could not locate tag in column %d of plugin table %s:%s", + ip_plugin_schema->rule_tag_column, + table->table_name[table->updating_name], + table_line); + table->udpate_err_cnt++; + return; + } + if(accept_tag_len>2) + { + copy=ALLOC(char, accept_tag_len+1); + memcpy(copy, table_line+accept_tag_offset, accept_tag_len); + matched_tag=compare_accept_tag(copy, tags, n_tags); + if(matched_tag<0) + { + MESA_handle_runtime_log(logger, RLOG_LV_FATAL, maat_module, + "update error, invalid tag format of ip_plugin table %s:%s", + table->table_name[table->updating_name], table_line); + table->udpate_err_cnt++; + } + if(matched_tag==0) + { + table->unmatch_tag_cnt++; + } + free(copy); + copy=NULL; + } + if(!matched_tag) + { + return; + } + } + ret=Maat_helper_read_column(table_line, ip_plugin_schema->valid_flag_column, &is_valid_offset, &valid_len); + //thread safe is protected by background_update_mutex + if(atoi(table_line+is_valid_offset)==1) + { + ret=plugin_EX_data_new(table, table_line, ip_plugin_rt->rowid2ex_hash, logger); + if(ret==0) + { + ip_plugin_rt->row_num++; + } + } + else + { + ret=plugin_EX_data_free(table_line, ip_plugin_schema->row_id_column, ip_plugin_rt->rowid2ex_hash, logger); + if(ret==0) + { + ip_plugin_rt->row_num--; + } + + } +} + void vector_print(igraph_vector_t *v) { long int i; for (i=0; igroup_graph), &is_dag); @@ -3355,7 +3292,10 @@ void do_scanner_update(struct Maat_scanner* scanner, MESA_lqueue_head garbage_q, "GIE_update error."); } break; - case TABLE_TYPE_PLUGIN: + case TABLE_TYPE_IP_PLUGIN: + Maat_table_runtime_rebuild_ip_matcher(table_rt); + old_ip_matcher=Maat_table_runtime_dettach_old_ip_matcher(table_rt); + garbage_bagging(GARBAGE_IP_MATCHER, old_ip_matcher, garbage_q); break; default: break; @@ -3513,6 +3453,10 @@ int maat_update_cb(const char* table_name,const char* line,void *u_para) break; case TABLE_TYPE_PLUGIN: update_plugin_table(p_table, line, scanner, feather->accept_tags, feather->n_tags, feather->logger); + break; + case TABLE_TYPE_IP_PLUGIN: + update_ip_plugin_table(p_table, line, scanner, feather->accept_tags, feather->n_tags, feather->logger); + break; default: break; diff --git a/src/entry/Maat_table.cpp b/src/entry/Maat_table.cpp index 65ea347..3771bef 100644 --- a/src/entry/Maat_table.cpp +++ b/src/entry/Maat_table.cpp @@ -74,7 +74,7 @@ int read_expr_table_info(const char* line, struct Maat_table_schema* table, MESA } return 0; } -int read_virtual_table_info(const char* line, struct Maat_table_schema* table, MESA_htable_handle string2int_map) +int read_virtual_table_schema(const char* line, struct Maat_table_schema* table, MESA_htable_handle string2int_map) { int ret=0; char table_type[16]; @@ -117,8 +117,11 @@ int _read_integer_arrary(char* string, int *array, int size) } return i; } -#define COLUMN_PLUGIN_DESCR_JSON 4 -int read_plugin_table_description(const char* line, struct Maat_table_schema* p) +#define COLUMN_PLUGIN_SCHEMA_JSON 4 +#define COLUMN_IP_PLUGIN_SCHEMA_JSON 4 +#define COLUMN_COMPOSITION_SCHEMA_JSON 4 + +int read_plugin_table_schema(const char* line, struct Maat_table_schema* p) { int i=0,ret=0; size_t offset=0, len=0; @@ -126,7 +129,7 @@ int read_plugin_table_description(const char* line, struct Maat_table_schema* p) char* copy_line=NULL, *plug_info=NULL; struct plugin_table_schema* plugin_desc=&(p->plugin); copy_line=_maat_strdup(line); - ret=get_column_pos(copy_line, COLUMN_PLUGIN_DESCR_JSON, &offset, &len); + ret=get_column_pos(copy_line, COLUMN_PLUGIN_SCHEMA_JSON, &offset, &len); if(ret<0) { goto error_out; @@ -202,7 +205,97 @@ error_out: free(copy_line); return -1; } -#define COLUMN_COMPOSITION_SCHEMA_JSON 4 +int read_ip_plugin_table_schema(const char* line, struct Maat_table_schema* p) +{ + int ret=0, read_cnt=0; + size_t offset=0, len=0; + cJSON* json=NULL, *tmp=NULL; + char* copy_line=NULL, *ip_plugin_info=NULL; + struct ip_plugin_table_schema* ip_plugin_schema=&(p->ip_plugin); + copy_line=_maat_strdup(line); + ret=get_column_pos(copy_line, COLUMN_IP_PLUGIN_SCHEMA_JSON, &offset, &len); + if(ret<0) + { + goto error_out; + } + if(offset+lentype==cJSON_Number) + { + ip_plugin_schema->row_id_column=tmp->valueint; + read_cnt++; + } + + tmp=cJSON_GetObjectItem(json, "ip_type"); + if(tmp!=NULL && tmp->type==cJSON_Number) + { + ip_plugin_schema->ip_type_column=tmp->valueint; + read_cnt++; + } + tmp=cJSON_GetObjectItem(json, "start_ip"); + if(tmp!=NULL && tmp->type==cJSON_Number) + { + ip_plugin_schema->start_ip_column=tmp->valueint; + read_cnt++; + } + tmp=cJSON_GetObjectItem(json, "end_ip"); + if(tmp!=NULL && tmp->type==cJSON_Number) + { + ip_plugin_schema->end_ip_column=tmp->valueint; + read_cnt++; + } + + tmp=cJSON_GetObjectItem(json, "valid"); + if(tmp!=NULL) + { + assert(tmp->type==cJSON_Number); + ip_plugin_schema->valid_flag_column=tmp->valueint; + read_cnt++; + } + ip_plugin_schema->rule_tag_column=-1; + tmp=cJSON_GetObjectItem(json, "tag"); + if(tmp!=NULL) + { + assert(tmp->type==cJSON_Number); + ip_plugin_schema->rule_tag_column=tmp->valueint; + //read_cnt++; Tag is optional, so NOT ++ intentionally. + } + + ip_plugin_schema->estimate_size=4096; + tmp=cJSON_GetObjectItem(json, "estimate_size"); + if(tmp!=NULL) + { + assert(tmp->type==cJSON_Number); + ip_plugin_schema->estimate_size=tmp->valueint; + //read_cnt++; estimate_size is optional, so NOT ++ intentionally. + } + + cJSON_Delete(json); + + free(copy_line); + if(read_cnt<5) + { + return 0; + } + else + { + return -1; + } +error_out: + free(copy_line); + return -1; + +} int read_composition_table_schema(const char* line, struct Maat_table_schema* p, MESA_htable_handle string2int_map) { @@ -397,6 +490,7 @@ struct Maat_table_manager* Maat_table_manager_create(const char* table_info_path map_register(string2int_map,"ip_plus", TABLE_TYPE_IP_PLUS); map_register(string2int_map,"compile", TABLE_TYPE_COMPILE); map_register(string2int_map,"plugin", TABLE_TYPE_PLUGIN); + map_register(string2int_map,"ip_plugin", TABLE_TYPE_IP_PLUGIN); map_register(string2int_map,"intval", TABLE_TYPE_INTERVAL); map_register(string2int_map,"digest", TABLE_TYPE_DIGEST); map_register(string2int_map,"expr_plus", TABLE_TYPE_EXPR_PLUS); @@ -468,7 +562,7 @@ struct Maat_table_manager* Maat_table_manager_create(const char* table_info_path } break; case TABLE_TYPE_PLUGIN: - ret=read_plugin_table_description(line, p); + ret=read_plugin_table_schema(line, p); if(ret<0) { fprintf(stderr,"Maat read table info %s line %d error:illegal plugin info.\n", table_info_path,i); @@ -477,6 +571,16 @@ struct Maat_table_manager* Maat_table_manager_create(const char* table_info_path goto invalid_table; } break; + case TABLE_TYPE_IP_PLUGIN: + ret=read_ip_plugin_table_schema(line, p); + if(ret<0) + { + fprintf(stderr,"Maat read table info %s line %d error:illegal ip_plugin info.\n", table_info_path,i); + MESA_handle_runtime_log(logger, RLOG_LV_FATAL,maat_module, + "Maat read table info %s line %d error:illegal ip_plugin info.", table_info_path,i); + goto invalid_table; + } + break; case TABLE_TYPE_COMPOSITION: ret=read_composition_table_schema(line, p, string2int_map); if(ret<0) @@ -488,7 +592,7 @@ struct Maat_table_manager* Maat_table_manager_create(const char* table_info_path } break; case TABLE_TYPE_VIRTUAL: - ret=read_virtual_table_info(line, p, string2int_map); + ret=read_virtual_table_schema(line, p, string2int_map); if(ret<0) { fprintf(stderr,"Maat read table info %s line %d error:illegal virtual info.\n", table_info_path,i); diff --git a/src/entry/Maat_table_runtime.cpp b/src/entry/Maat_table_runtime.cpp index d145e31..ede0861 100644 --- a/src/entry/Maat_table_runtime.cpp +++ b/src/entry/Maat_table_runtime.cpp @@ -5,18 +5,22 @@ #include #include #include +#include struct wrap_plugin_EX_data { MAAT_RULE_EX_DATA exdata; - const struct Maat_table_schema* ref_plugin_table; + int table_id; + const struct plugin_table_ex_data_schema* ex_desc; + struct ip_rule range_rule;//for ip_plugin + TAILQ_ENTRY(wrap_plugin_EX_data) entries; }; void wrap_plugin_EX_data_free(void *data) { struct wrap_plugin_EX_data* wrap_data=(struct wrap_plugin_EX_data*)data; - const struct plugin_table_ex_data_schema* ex_desc= &(wrap_data->ref_plugin_table->plugin.ex_desc); - ex_desc->free_func(wrap_data->ref_plugin_table->table_id, &(wrap_data->exdata), ex_desc->argl, ex_desc->argp); - wrap_data->ref_plugin_table=NULL; + wrap_data->ex_desc->free_func(wrap_data->table_id, &(wrap_data->exdata), wrap_data->ex_desc->argl, wrap_data->ex_desc->argp); + wrap_data->ex_desc=NULL; + wrap_data->table_id=-1; free(wrap_data); return; } @@ -51,66 +55,130 @@ MESA_htable_handle wrap_plugin_EX_hash_new(long long estimate_size, Maat_plugin_ return key2ex_hash; } -int plugin_EX_data_free(const struct Maat_table_schema* plugin_table, const char* line, +int plugin_EX_data_free(const char* line, int key_column, MESA_htable_handle key2ex_hash, void *logger) { size_t key_offset=0, key_len=0; - const struct plugin_table_schema* plugin_desc= &(plugin_table->plugin); int ret=0; - ret=get_column_pos(line, plugin_desc->key_column, &key_offset, &key_len); + ret=get_column_pos(line, key_column, &key_offset, &key_len); if(ret<0) { MESA_handle_runtime_log(logger, RLOG_LV_FATAL, maat_module, - "Plugin EX data del error: cannot find column %d of %s", - plugin_desc->key_column, line); + "plugin/ip_plugin EX data del error: cannot find column %d of %s", + key_column, line); return -1; } ret=MESA_htable_del(key2ex_hash, (const unsigned char*)line+key_offset, key_len, NULL); if(ret<0) { MESA_handle_runtime_log(logger, RLOG_LV_FATAL, maat_module, - "Plugin EX data del error: no such key %.*s of %s", + "plugin/ip_plugin EX data del error: no such key %.*s of %s", key_len, line+key_offset, line); return -1; } return 0; } +int ip_plugin_line_read(const struct ip_plugin_table_schema* schema, const char* line, struct ip_rule* range_rule) +{ + int ret[4]={0}; + size_t column_offset=0, column_len=0; + char start_ip[128]={0}, end_ip[128]={0}; + ret[0]=get_column_pos(line, schema->row_id_column, &column_offset, &column_len); + range_rule->rule_id=atoi(line+column_offset); + + ret[1]=get_column_pos(line, schema->ip_type_column, &column_offset, &column_len); + int ip_type=atoi(line+column_offset); -int plugin_EX_data_new(const struct Maat_table_schema* plugin_table, const char* line, + ret[2]=get_column_pos(line, schema->start_ip_column, &column_offset, &column_len); + strncpy(start_ip, line+column_offset, MIN(column_len, sizeof(start_ip))); + + ret[3]=get_column_pos(line, schema->end_ip_column, &column_offset, &column_len); + strncpy(end_ip, line+column_offset, MIN(column_len, sizeof(end_ip))); + if(ret[0]<0||ret[1]<0||ret[2]<0||ret[3]<0) + { + return -1; + } + + if(ip_type==4) + { + ret[0]=ip_format2range(ip_type, FORMAT_RANGE, start_ip, end_ip, &(range_rule->ipv4_rule.start_ip), &(range_rule->ipv4_rule.end_ip)); + range_rule->type=IPv4; + } + else if(ip_type==6) + { + ret[0]=ip_format2range(ip_type, FORMAT_RANGE, start_ip, end_ip, range_rule->ipv6_rule.start_ip, range_rule->ipv6_rule.end_ip); + range_rule->type=IPv6; + } + else + { + return -1; + } + if(ret[0]<0) + { + return -1; + } + range_rule->rule_id=(unsigned int)atoi(line+column_offset); + range_rule->user_tag=NULL; + return 0; +} +int plugin_EX_data_new(const struct Maat_table_schema* table_schema, + const char* line, MESA_htable_handle key2ex_hash, void *logger) { char* key=NULL; size_t key_offset=0, key_len=0; MAAT_RULE_EX_DATA exdata=NULL; - struct wrap_plugin_EX_data* wrap_data=NULL; - const struct plugin_table_schema* plugin_desc= &(plugin_table->plugin); + const struct plugin_table_ex_data_schema* ex_desc=NULL; + int key_column=-1; + struct wrap_plugin_EX_data* wrap_data=ALLOC(struct wrap_plugin_EX_data, 1); + switch(table_schema->table_type) + { + case TABLE_TYPE_PLUGIN: + ex_desc=&(table_schema->plugin.ex_desc); + key_column=table_schema->plugin.key_column; + break; + case TABLE_TYPE_IP_PLUGIN: + ex_desc=&(table_schema->ip_plugin.ex_desc); + key_column=table_schema->ip_plugin.row_id_column; + ip_plugin_line_read(&table_schema->ip_plugin, line, &(wrap_data->range_rule)); + wrap_data->range_rule.user_tag=wrap_data; + break; + default: + assert(0); + break; + } + int ret=0; - ret=get_column_pos(line, plugin_desc->key_column, &key_offset, &key_len); + ret=get_column_pos(line, key_column, &key_offset, &key_len); if(ret<0) { MESA_handle_runtime_log(logger, RLOG_LV_FATAL, maat_module, - "Plugin EX data add error: cannot find column %d of %s", - plugin_desc->key_column, line); - return -1; + "plugin/ip_plugin EX data add error: cannot find column %d of %s", + key_column, line); + goto error_out; } key=ALLOC(char, key_len+1); memcpy(key, line+key_offset, key_len); - plugin_desc->ex_desc.new_func(plugin_table->table_id, key, line, &exdata, - plugin_desc->ex_desc.argl, plugin_desc->ex_desc.argp); - wrap_data=ALLOC(struct wrap_plugin_EX_data, 1); + ex_desc->new_func(table_schema->table_id, key, line, &exdata, + ex_desc->argl, ex_desc->argp); wrap_data->exdata=exdata; - wrap_data->ref_plugin_table=plugin_table; + wrap_data->ex_desc=ex_desc; + wrap_data->table_id=table_schema->table_id; ret=MESA_htable_add(key2ex_hash, (const unsigned char*)line+key_offset, key_len, wrap_data); free(key); if(ret<0) { MESA_handle_runtime_log(logger, RLOG_LV_FATAL, maat_module, - "Plugin EX data add error: duplicated key %.*s of %s", + "plugin/ip_plugin EX data add error: duplicated key %.*s of %s", key_len, line+key_offset, line); wrap_plugin_EX_data_free(wrap_data); return -1; } return 0; +error_out: + free(wrap_data); + free(key); + return -1; } struct Maat_table_runtime_manager @@ -168,6 +236,10 @@ static struct Maat_table_runtime* table_runtime_new(const struct Maat_table_sche table_desc->plugin.ex_desc.key2index_func); } break; + case TABLE_TYPE_IP_PLUGIN: + table_rt->ip_plugin.rowid2ex_hash=wrap_plugin_EX_hash_new(table_desc->ip_plugin.estimate_size, + NULL); + break; default: break; } @@ -218,6 +290,12 @@ static void table_runtime_free(struct Maat_table_runtime* p) { MESA_htable_destroy(p->plugin.key2ex_hash, NULL); } + break; + case TABLE_TYPE_IP_PLUGIN: + MESA_htable_destroy(p->ip_plugin.rowid2ex_hash, NULL); + ip_matcher_free(p->ip_plugin.ip_matcher); + p->ip_plugin.row_num=0; + break; default: break; } @@ -331,6 +409,22 @@ MAAT_PLUGIN_EX_DATA Maat_table_runtime_plugin_get_ex_data(struct Maat_table_runt return exdata; } +int Maat_table_runtime_ip_plugin_get_N_ex_data(struct Maat_table_runtime* table_rt, struct Maat_table_schema* table_schema, const struct ip_address* ip, MAAT_PLUGIN_EX_DATA* ex_data_array, size_t size) +{ + struct ip_plugin_table_schema* ip_plugin_desc=NULL; + struct scan_result results[size]; + int n_result=0, i=0; + + ip_plugin_desc=&(table_schema->ip_plugin); + n_result=ip_matcher_match(table_rt->ip_plugin.ip_matcher, (struct ip_data*)ip, results, size); + for(i=0; iex_desc.dup_func(table_schema->table_id, &(ex_data_array[i]), &(results[i].tag), + ip_plugin_desc->ex_desc.argl, ip_plugin_desc->ex_desc.argp); + } + return n_result; +} void Maat_table_runtime_digest_add(struct Maat_table_runtime* table_rt, int expr_id, const char* digest, short confidence_degree, void* tag) { @@ -424,4 +518,45 @@ int Maat_table_runtime_digest_batch_udpate(struct Maat_table_runtime* table_rt) return q_cnt; } +TAILQ_HEAD(ip_range_rule_q, wrap_plugin_EX_data); + +void walk_ip_plugin_hash(const uchar * key, uint size, void * data, void * user) +{ + struct wrap_plugin_EX_data* wrap_plugin_ex=(struct wrap_plugin_EX_data*)data; + struct ip_range_rule_q* queue=(struct ip_range_rule_q*)user; + TAILQ_INSERT_TAIL(queue, wrap_plugin_ex, entries); + return; +} + +int Maat_table_runtime_rebuild_ip_matcher(struct Maat_table_runtime* table_rt) +{ + struct ip_matcher* new_ip_matcher=NULL; + struct ip_range_rule_q queue;//This is for index, no need to free. + size_t rule_cnt=0; + size_t i=0, mem_use=0; + struct ip_rule *rules=NULL; + struct wrap_plugin_EX_data *p=NULL; + TAILQ_INIT(&queue); + MESA_htable_iterate(table_rt->ip_plugin.rowid2ex_hash, walk_ip_plugin_hash, &queue); + rule_cnt=(size_t)MESA_htable_get_elem_num(table_rt->ip_plugin.rowid2ex_hash); + rules=ALLOC(struct ip_rule, rule_cnt); + TAILQ_FOREACH(p, &queue, entries) + { + rules[i]=p->range_rule; + i++; + } + assert(i==rule_cnt); + new_ip_matcher=ip_matcher_new(rules, rule_cnt, &mem_use); + table_rt->ip_plugin.old_ip_matcher=table_rt->ip_plugin.ip_matcher; + table_rt->ip_plugin.ip_matcher=new_ip_matcher; + return 0; +} +struct ip_matcher* Maat_table_runtime_dettach_old_ip_matcher(struct Maat_table_runtime* table_rt) +{ + struct ip_matcher* old_one=table_rt->ip_plugin.old_ip_matcher; + assert(table_rt->table_type==TABLE_TYPE_IP_PLUGIN); + table_rt->ip_plugin.old_ip_matcher=NULL; + return old_one; +} + diff --git a/src/entry/Maat_utils.cpp b/src/entry/Maat_utils.cpp index 8462ba7..745952a 100644 --- a/src/entry/Maat_utils.cpp +++ b/src/entry/Maat_utils.cpp @@ -390,4 +390,133 @@ int decrypt_open(const char* file_name, const char* key, const char* algorithm, file_buff=NULL; return ret; } +enum MAAT_IP_FORMAT ip_format_str2int(const char* format) +{ + if(0==strcasecmp(format, "range")) + { + return FORMAT_RANGE; + } + else if(0==strcasecmp(format, "mask")) + { + return FORMAT_MASK; + } + else if(0==strcasecmp(format, "CIDR")) + { + return FORMAT_CIDR; + } + else + { + assert(0); + } + return FORMAT_UNKNOWN; +} +int ip_format2range(int ip_type, enum MAAT_IP_FORMAT format, const char* ip1, const char* ip2, unsigned int range_begin[], unsigned int range_end[]) +{ + unsigned int ipv4_addr=0, ipv4_mask=0, ipv4_range_end=0; + unsigned int ipv6_addr[4]={0}, ipv6_mask[4]={0}, ipv6_range_end[4]={0}; + int cidr=0, bit32=0; + int ret=0, i=0; + if(ip_type!=4 && ip_type!=6) + { + assert(0); + return -1; + } + if(ip_type==4) + { + ret=inet_pton(AF_INET, ip1, &ipv4_addr); + if(ret<=0) + { + return -1; + } + ipv4_addr=ntohl(ipv4_addr); + switch (format) + { + case FORMAT_RANGE: + range_begin[0]=ipv4_addr; + ret=inet_pton(AF_INET, ip2, &ipv4_range_end); + if(ret<=0) + { + return -1; + } + ipv4_range_end=ntohl(ipv4_range_end); + range_end[0]=ipv4_range_end; + break; + case FORMAT_MASK: + ret=inet_pton(AF_INET, ip2, &ipv4_mask); + if(ret<=0) + { + return -1; + } + ipv4_mask=ntohl(ipv4_mask); + range_begin[0]=ipv4_addr&ipv4_mask; + range_end[0]=ipv4_addr|~ipv4_mask; + break; + case FORMAT_CIDR: + cidr=atoi(ip2); + if(cidr>32||cidr<0) + { + return -1; + } + ipv4_mask = (0xFFFFFFFFUL << (32 - cidr)) & 0xFFFFFFFFUL; + range_begin[0]=ipv4_addr&ipv4_mask; + range_end[0]=ipv4_addr|~ipv4_mask; + break; + default: + assert(0); + } + } + else //ipv6 + { + ret=inet_pton(AF_INET6, ip1, ipv6_addr); + if(ret<=0) + { + return -1; + } + ipv6_ntoh(ipv6_addr); + switch(format) + { + case FORMAT_RANGE: + ret=inet_pton(AF_INET6, ip2, ipv6_range_end); + if(ret<=0) + { + return -1; + } + ipv6_ntoh(ipv6_range_end); + memcpy(range_begin, ipv6_addr, sizeof(ipv6_addr)); + memcpy(range_end, ipv6_range_end, sizeof(ipv6_range_end)); + break; + case FORMAT_MASK: + ret=inet_pton(AF_INET6, ip2, ipv6_mask); + if(ret<=0) + { + return -1; + } + ipv6_ntoh(ipv6_mask); + for(i=0; i<4; i++) + { + range_begin[i]=ipv6_addr[i]&ipv6_mask[i]; + range_end[i] = ipv6_addr[i]|~ipv6_mask[i]; + } + break; + case FORMAT_CIDR: + cidr=atoi(ip2); + if(cidr>128||cidr<0) + { + return -1; + } + for(i=0; i<4; i++) + { + bit32=128-cidr-32*(3-i); + if(bit32<0) bit32=0; + ipv6_mask[i]=(0xFFFFFFFFUL << bit32) & 0xFFFFFFFFUL; + range_begin[i]=ipv6_addr[i]&ipv6_mask[i]; + range_end[i] = ipv6_addr[i]|~ipv6_mask[i]; + } + break; + default: + assert(0); + } + } + return 0; +} diff --git a/src/inc_internal/Maat_rule_internal.h b/src/inc_internal/Maat_rule_internal.h index 57772e0..8746343 100644 --- a/src/inc_internal/Maat_rule_internal.h +++ b/src/inc_internal/Maat_rule_internal.h @@ -13,6 +13,7 @@ #include "dynamic_array.h" #include "bool_matcher.h" #include "hiredis.h" +#include "IPMatcher.h" #include "igraph/igraph.h" #include "stream_fuzzy_hash.h" #include "gram_index_engine.h" @@ -204,7 +205,8 @@ enum maat_garbage_type GARBAGE_COMPILE_GOURP_RELATION, GARBAGE_BOOL_MATCHER, GARBAGE_MAP_STR2INT, - GARBAGE_FOREIGN_FILE + GARBAGE_FOREIGN_FILE, + GARBAGE_IP_MATCHER }; struct iconv_handle_t { @@ -402,6 +404,7 @@ struct _maat_garbage_t struct Maat_compile_rule* compile_rule; struct Maat_compile_group_relation * compile_group_relation; struct bool_matcher* bool_matcher; + struct ip_matcher* a_ip_matcher; void * raw; MESA_htable_handle str2int_map; char* filename; @@ -456,7 +459,7 @@ MAAT_RULE_EX_DATA rule_ex_data_new(const struct Maat_rule_head * rule_head, cons void rule_ex_data_free(const struct Maat_rule_head * rule_head, const char* srv_def, MAAT_RULE_EX_DATA *ad, const struct compile_ex_data_idx* ex_desc); MESA_htable_handle wrap_plugin_EX_hash_new(long long estimate_size, Maat_plugin_EX_key2index_func_t * key2index); int plugin_EX_data_new(const struct Maat_table_schema* plugin_table, const char* line, MESA_htable_handle key2ex_hash, void *logger); -int plugin_EX_data_free(const struct Maat_table_schema* plugin_table, const char* line, MESA_htable_handle key2ex_hash, void *logger); +int plugin_EX_data_free(const char* line, int key_column, MESA_htable_handle key2ex_hash, void *logger); void set_serial_rule(struct serial_rule_t* rule,enum MAAT_OPERATION op,int rule_id,int label_id,const char* table_name,const char* line, long long timeout); diff --git a/src/inc_internal/Maat_table.h b/src/inc_internal/Maat_table.h index 3e14f98..8e0b75c 100644 --- a/src/inc_internal/Maat_table.h +++ b/src/inc_internal/Maat_table.h @@ -32,7 +32,8 @@ enum MAAT_TABLE_TYPE TABLE_TYPE_COMPOSITION, TABLE_TYPE_GROUP, TABLE_TYPE_COMPILE, - TABLE_TYPE_PLUGIN + TABLE_TYPE_PLUGIN, + TABLE_TYPE_IP_PLUGIN }; struct compile_ex_data_idx @@ -100,7 +101,17 @@ struct plugin_table_schema struct plugin_table_callback_schema cb_plug[MAX_PLUGIN_PER_TABLE]; struct plugin_table_ex_data_schema ex_desc; }; - +struct ip_plugin_table_schema +{ + int row_id_column; + int ip_type_column; + int start_ip_column; + int end_ip_column; + int valid_flag_column; + int rule_tag_column; + long long estimate_size; + struct plugin_table_ex_data_schema ex_desc; +}; struct Maat_table_schema { int table_id; @@ -113,9 +124,10 @@ struct Maat_table_schema struct compile_table_schema compile; struct expr_table_schema expr; struct plugin_table_schema plugin; + struct ip_plugin_table_schema ip_plugin; struct virtual_table_schema virtual_table; struct composition_table_schema composition; - void* others;//group, ip, interval and digest don't have sperate description info. + void* others;//group, ip, interval and digest don't have any special schema. }; //for stat>>>>>>>> unsigned long long udpate_err_cnt; diff --git a/src/inc_internal/Maat_table_runtime.h b/src/inc_internal/Maat_table_runtime.h index acd1a69..57c6e2e 100644 --- a/src/inc_internal/Maat_table_runtime.h +++ b/src/inc_internal/Maat_table_runtime.h @@ -1,4 +1,5 @@ #include "Maat_table.h" +#include "IPMatcher.h" #include "gram_index_engine.h" #include "alignment_int64.h" #include "dynamic_array.h" @@ -19,6 +20,13 @@ struct plugin_runtime long long cache_size; MESA_htable_handle key2ex_hash; }; +struct ip_plugin_runtime +{ + long long row_num; + MESA_htable_handle rowid2ex_hash; + struct ip_matcher* ip_matcher; + struct ip_matcher* old_ip_matcher; +}; struct expr_runtime { long long expr_rule_cnt; //expr_type=0,1,3 @@ -42,6 +50,7 @@ struct Maat_table_runtime { struct similar_runtime similar; //for digest and similarity struct plugin_runtime plugin; + struct ip_plugin_runtime ip_plugin; struct expr_runtime expr; struct ip_runtime ip; struct group_runtime group; @@ -65,5 +74,8 @@ MAAT_PLUGIN_EX_DATA Maat_table_runtime_plugin_get_ex_data(struct Maat_table_runt void Maat_table_runtime_digest_add(struct Maat_table_runtime* table_rt, int expr_id, const char* digest, short confidence_degree, void* tag); void Maat_table_runtime_digest_del(struct Maat_table_runtime* table_rt, int expr_id); int Maat_table_runtime_digest_batch_udpate(struct Maat_table_runtime* table_rt); +int Maat_table_runtime_ip_plugin_get_N_ex_data(struct Maat_table_runtime* table_rt, struct Maat_table_schema* table_schema, const struct ip_address* ip, MAAT_PLUGIN_EX_DATA* ex_data_array, size_t size); +int Maat_table_runtime_rebuild_ip_matcher(struct Maat_table_runtime* table_rt); +struct ip_matcher* Maat_table_runtime_dettach_old_ip_matcher(struct Maat_table_runtime* table_rt); diff --git a/src/inc_internal/Maat_utils.h b/src/inc_internal/Maat_utils.h index ac4054b..4d8b63c 100644 --- a/src/inc_internal/Maat_utils.h +++ b/src/inc_internal/Maat_utils.h @@ -82,5 +82,14 @@ int decrypt_open(const char* file_name, const char* key, const char* algorithm, int load_file_to_memory(const char* file_name, unsigned char**pp_out, size_t *out_sz); //do_encrypt: 1 for encryption, 0 for decryption. int crypt_memory(const unsigned char* inbuf, size_t inlen, unsigned char** pp_out, size_t *out_sz, const char* key, const char* algorithm, int do_encrypt, char* err_str, size_t err_str_sz); +enum MAAT_IP_FORMAT +{ + FORMAT_RANGE, + FORMAT_MASK, + FORMAT_CIDR, + FORMAT_UNKNOWN +}; +enum MAAT_IP_FORMAT ip_format_str2int(const char* format); +int ip_format2range(int ip_type, enum MAAT_IP_FORMAT format, const char* ip1, const char* ip2, unsigned int range_begin[], unsigned int range_end[]); diff --git a/src/inc_internal/view_only/IPMatcher.h b/src/inc_internal/view_only/IPMatcher.h new file mode 100644 index 0000000..0e387f3 --- /dev/null +++ b/src/inc_internal/view_only/IPMatcher.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2020 + * String Algorithms Research Group + * Institute of Information Engineering, Chinese Academy of Sciences (IIE-CAS) + * National Engineering Laboratory for Information Security Technologies (NELIST) + * All rights reserved + * + * Written by: LU YUHAI (luyuhai@iie.ac.cn) + * Last modification: 2020-04-20 + * + * This code is the exclusive and proprietary property of IIE-CAS and NELIST. + * Usage for direct or indirect commercial advantage is not allowed without + * written permission from the authors. + * + */ + +#ifndef H_IP_MATCHER_H +#define H_IP_MATCHER_H +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + enum IP_TYPE + { + IPv4, + IPv6 + }; + + /* 带掩码的单点IPv4规则 */ + struct ipv4_range + { + unsigned int start_ip; /* IP范围下界 */ + unsigned int end_ip; /* IP范围上界 */ + }; + + /* 带掩码的单点IPv6规则 */ + struct ipv6_range + { + unsigned int start_ip[4]; /* IP范围下界 */ + unsigned int end_ip[4]; /* IP范围上界 */ + }; + + /* 通用的ip规则类型 */ + struct ip_rule + { + enum IP_TYPE type; /* 规则类型,ipv4或ipv6 */ + unsigned int rule_id; /* 规则ID */ + void* user_tag; /* 用户自定义数据,命中时随匹配结果返回 */ + union + { + struct ipv4_range ipv4_rule; /*带掩码的单点IPv4规则*/ + struct ipv6_range ipv6_rule; /*带掩码的单点IPv6规则*/ + }; + }; + + /* 通用的待扫描数据类型 */ + struct ip_data + { + enum IP_TYPE type; /* 规则类型,ipv4或ipv6 */ + union /* 根据rule_type决定数据负载是ipv4还是ipv6 */ + { + unsigned int ipv4; /* ipv4数据*/ + unsigned int ipv6[4]; /* ipv6数据*/ + }; + }; + + + /* 布尔表达式的扫描结果类型 */ + struct scan_result + { + unsigned int rule_id; /* 规则的ID */ + void * tag; /* 用户自定义数据,命中时随匹配结果返回 */ + }; + + + 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); + + /* + 功能:调用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); + + /* + 功能:销毁一个ip扫描器 + 参数: + matcher[in]:待销毁的ip扫描器指针 + */ + void ip_matcher_free(struct ip_matcher* matcher); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(H_IP_MATCHER_H) */ diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index d57f53e..fb50be3 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -46,3 +46,18 @@ add_library(igraph-static STATIC IMPORTED GLOBAL) add_dependencies(igraph-static igraph) set_property(TARGET igraph-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libigraph.a) set_property(TARGET igraph-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) + +ExternalProject_Add(ipmatcher PREFIX ipmatcher + URL ${CMAKE_CURRENT_SOURCE_DIR}/IPMatcher-20200503.zip + CONFIGURE_COMMAND "" + BUILD_COMMAND make + INSTALL_COMMAND make DESTDIR= install + BUILD_IN_SOURCE 1) + +ExternalProject_Get_Property(ipmatcher INSTALL_DIR) +file(MAKE_DIRECTORY ${INSTALL_DIR}/include) + +add_library(ipmatcher-static STATIC IMPORTED GLOBAL) +add_dependencies(ipmatcher-static ipmatcher) +set_property(TARGET ipmatcher-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/ipmatcher.a) +set_property(TARGET ipmatcher-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) diff --git a/vendor/IPMatcher-20200503.zip b/vendor/IPMatcher-20200503.zip new file mode 100644 index 0000000..921f294 Binary files /dev/null and b/vendor/IPMatcher-20200503.zip differ