From 9d0d5103486e4116ccde71b9139978cb78acd469 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Sun, 3 May 2020 17:19:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EIP=E5=9B=9E=E8=B0=83=E8=A1=A8?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=BF=9B=E8=A1=8CIPv4=E5=92=8CIPv6?= =?UTF-8?q?=E7=9A=84=E5=8C=BA=E9=97=B4=E5=8C=B9=E9=85=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/Maat_rule.h | 15 +- src/CMakeLists.txt | 2 + src/entry/Maat_api.cpp | 21 +++ src/entry/Maat_rule.cpp | 230 ++++++++++--------------- src/entry/Maat_table.cpp | 118 ++++++++++++- src/entry/Maat_table_runtime.cpp | 179 ++++++++++++++++--- src/entry/Maat_utils.cpp | 129 ++++++++++++++ src/inc_internal/Maat_rule_internal.h | 7 +- src/inc_internal/Maat_table.h | 18 +- src/inc_internal/Maat_table_runtime.h | 12 ++ src/inc_internal/Maat_utils.h | 9 + src/inc_internal/view_only/IPMatcher.h | 117 +++++++++++++ vendor/CMakeLists.txt | 15 ++ vendor/IPMatcher-20200503.zip | Bin 0 -> 86786 bytes 14 files changed, 694 insertions(+), 178 deletions(-) create mode 100644 src/inc_internal/view_only/IPMatcher.h create mode 100644 vendor/IPMatcher-20200503.zip 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 0000000000000000000000000000000000000000..921f29435de9a825ba39bee3a0bfe975ff3585bf GIT binary patch literal 86786 zcmbrl1#p|qvMp-1V`j!UF~rQwj+vR6*)gNc%*^bVnb|SM%y!Jo%p_Si`=0miIj8Es zr{1oos*&_b>aOmdu9;73tx=MNhCzh**P}$KSm}Si`G20U{=P~p$s4?7(PZ?CKWBhd9WLEbI|{ zy~88+Ba)F65mX)cdBVojNsp4QbkvcCR=!_*dm(wK7|pJ;>U8=@G_fE-!`73WOQ4m; zjJUOgpIYLKt|_{rcB}5<6d?%OSpax0L#I}f=Qm}5@k2z4i=as(Z?DM2$*&1cUKglO z_t1B3kGY2@p3UE5$+9h91N{o|ulWBtVWNMI-`c^{&dtpHza&l>R;(oBNHn_#0|D{# zuP>_q+3^1qkSUsd@$-=`f-fTvv zsfo&AI9|F2Tj#Lw3n!$W6wyXWJE9VKf<)wEC9OSnp-hGNyi&;)U)MRB-J0uHpSt5b z9+#_3zOE}2H+S?$3TO>ZCN0*l(z7R@Efw;4YQiK-jrgTaPD{RK$eG*y2wYRclZf&q zr>CwGc6N}ZB9V?v4Iuj@YvwveuK?$j=3BU%CEo}hc>(iQ){#~#z&jmGm3vX7fTx4r8n5gAU(pW z9Yi40uYIWbeA?@TKiISVpRlRAo^&_<(_{TiMggi<1k_?62+8SY}eu@m6FbBXD7GOjcsdsKND; zHTyAQ9ZDb`-K>C9>7MgB^5~xg+RV^Gxg-x!B|*um&}F=Qf{+NIm6!;q=;OJ_kb4c$ zl)*Pdje)|xUshJO@ty{x05C-rM|=bedIrk9p6L0Q5ebY2B_0# zpD%<=CofXFwofGy6PxHk$>6D&uF|+eKn}e8uIXqwedLqv>tLU9nq5OQ(0~3#eHPWc zfa3+NkL8zM}g)RVAmFp z9pY)J5IMu}a9Bt{Ljp8_erV}U83dnEbCgiL+Y`6-O>9f~d%6U;nqF-mtzM;f-^RE3 zh?Z8bpRWwwpHAmzkiy$!4#Qi%7FI!Tg+f<`Epy(8&X#oBtOzq2pDTFnep01;tWcff z{D~K@VX5Ii%DYD3c%~w>>Zx>Z7`C730Qfce+LxAJZZF(=7~DaS!qV3cs`pk@W>CB4 zNT9`-@`)%f#|*@nMtyAk{=NQ_fL=+QtrHAD^kYQRCA{ffO>|a;Io~`5=f1+voU2qW7z)BEmAC1CFAUS# zcV+zpRDvK&ePV7{9i5dN!qX!{z)&Xz18MnEYof^cr~K*{r-qM62D=bMzgTyuwC#I% zgiqaSY@0^eieWlngMNmLz1=;iZkTc??VBK`?l6-WNlq9qX3#uwpvUZ?Tj_lkO*w(AJV?YRZ%?>3aB1Dw^1m^vWgdik#tsDu#s?jrCtH>tnnT zc6EXG&tSX#ZNZvvHUL_~fdYSf7UiC}-CB_-a_n7%D@{e`F4 znrfTm18>;0@l&g<$hRCmG|Ct|dqm_tYlteT0OU>Buw$OIN|AI=Po{WDuF;O;J?gV= zfhenl+73wLwgS3W&keR$_C9vg|j`tH*D zy;wDm8d84|7;QVfcGjFk-Y3!11TTctJ6ED}KBh@mu_XGq%?$Q&+m-~*#fxw49;#iQ zCh+nbG^*#lgt9~f?P%l93vWX5lA;Fm-!kg_{mmOHBaDW>1?!UJi|zFw`2NIrRP`p+ zY^wSc-hgvnP_6M08d3ZkV1+(a7iIO#k)gIIZ^yC}#yhc8dPd5g)I^ihA4or!r&(Ur zipycZFrTeuLo#lA)^pIpOJB3n!dJ7%8?v;h%_oy9J(bnz+<6fvIMmo#*xh#-=kI-< zYul)!k6QDr?V+Q+imuUQ3ewVdmm)K%aHF{{y&jFmn>t0sz?;sZA}C&Q_>D%-znJMU3BdTG08&`FcC@% zzrfG{4$I67OHR>vayEZV=V7(#K3yq{i${0!mBq2yrYpw*x)AQ<8GAT#nR{9SR3sCI1n>HF>a`76;@ z25x!#9|L#->L8Aw93X(OI}*YuQ(eSyNDwUnp#k3mvLT`&xuDY^(xB2H@dI%Bp}4)l z9e)>Vl|d@(a6`QQ9#Gms|5V{qlD`yg z1zFx369@{=G;!__+Q1{W0CKM3HbESVsFO^EAf}a72vQ?x1PH#wPofF|NIO3tH2QC= z*!_`+H6b;i`5~D4;n5-eg(2$U>Iv#mo#1yggary9>mlnC1>&uyB_gae_zIwBKSe-XLD@lyLxw}L24m$oQ=28y>-0 zuZr4J#ETNayU=GX2?WER}Ip9w)!Kl1aslDeWKNuj;XZ>4)tJcZEYRJ z&rwm2R2eZlqnJX40~2NOAfb&XOkpmluMs%bu+hR`x(Y|5ln=RF z&{!E6Ie)l_g0qx*^jhHeW{^Ca2-$iS3eNC}qnQ5CX9-E)37_+^=<#)x}R>IIM@qC(V%K@qPfF zUt`{a#Js_0%BK+eQb6dZxAtD3A+3TCA1=D|dorTn1mXiznSeMg5MCNBef%~f(SI&Q0Pn+m6Vt! zaZwo5idtno7}xjP(?lWi?wOqLgg-cE_6~?{S@3-|0%RWGL;c4wQSWhZCVazb3Ux(1 zNmrP!;A7CrHg9uPs++54DKl`Exs`UI(`l>1N;%J-(0)~;K;7KG2**AMQ!+Aiz`i)W z6_3bMR%2GjaXSA_wDyLapqgGQZ7#*U-#v>~@+bUGLM;DMbk0G3pyhjDZG4KDFl5pZ zMTHe~_@g@j~t1wkUkE1b5$mDIDl= zWnNk*49nkrC~?(^uY_AV8$BRRc;XjElxO!qvc@iKr9#Ad0XF{+{N-_V^DUI z@hWE(J*CufmHH)VqRr6=g>K2GA&7UpvG)?I?xrfHC%0W)|ZMQ%fOS+EVAw#q7c z*Pn~%D9s4$SnNZGuHWU2KlXLzXc=`^n9`-|kAbrpYC2H^eOrF5MDZuA9&iCau7Gq& z&f+lQGi{Igwd&mpI5>e?K|+pIh9C#PS_Q~;az_!x_#gA z6pFnL-VY7{xq^-%8i)``V0^J|5O&aal>1E|@24;!Q&pebgPeP^_rL`l#L@PUq5IB#PMiZvxjU!Y)B=-WPSUDcjD$CJ^P zpEML2s;P^vZn8?KOTO~%wuAzC5R~KBQ9O9R|YBfXbHASA^0MDwNN z48uZd@zyaX`r~63_y^5h5VTj5UoN|FOjwE3?e0n2`HiTWm@9o2G2e{6O5 zqM}@1!9Y{9B@qhCD*)t;TW&_##C^VZFB8 zPFS0$F1>|$=40o$-LUT`srWI(+Ohr^<|Cy4AuYa!p3&80e0+~|JVQ?&T&|uPeje$e zO|{nh;k%2rSp`0h`@M85sN3^ame1JN3<0l=4rnBKR56(QVT_uWFJa<07?(k!e2uB_FzrjzuA2(4K&rE}K?&44Ng#gD3 zinTq}5LmCUWH*UqjVXd2Y`DGmn`HD}{?7p4y2C86D8K;U>vGT zJH^%&=C`S@u2jys4wiZ5A^P4^2#0y=GFxBzWjZse_pQv(RAZ`bmS%J9ILz`1w(MJw z_dL_p5nB?yE9WlVIy1dxRs$;f9zWFG=2Wj|d(x zRNe%SUon@-?oR6p&+8*az7o8G!eLX~c~0O@FRED1ps&f~7!tv^Hw$cz$y>oxYYQS~ zrOISkb98BA9EAEcr2O}_-Ve|47Wts?>1&ss&~8|^r!K;pAk=HwcLA0sqC(o7)D~Q} zMpOLmhfUegMJE4e*2tu0YUa0(-O>jlbcxFu7gq&X0xhspoCr9$^#9|n$YWq{Bk|_*q8Za7`oLG;YJT^3YWr zfBk2U&#bXe_e#3_w#$2ECG=(cYHbrdzS~R2pCx#UfDBlGM-6M&TgxOPxfbdqx*9Tl z3xsC|o-AXq?iV2?L_5HDaISWs%emZYry)%rx%lKdFb%%x3re6v^~0V&v*eI_d!-K= zV-bHqGMY$#zf3DSH!&`yR--%na5FUc2=&vPkZ%%wMKjI*tzF7R6{$TGomy0Qn%3-gmD5F|ji?L$kqh>=3k|w2xo;ERi9G)YYk=W8>+BqO^ zn>jV^E}{|5hDzhF);HTA#j|wrgf3dJT%Y5!vi~-ZJI*(A`*k@~XYVX6q1=^j&NFC8 zU@oqmP}<$y`Z1AHU8U_%qffNgQ|nVH;B9`iEAOleT-pmgNFU!&(=EU*hmpm*um6dG zbRGQ$zfP42%Wk~h(S_%ba~j8jIA?PNA!qYfyH{7TvutC{=2X*kE2nw*v(YfVZUKke zcX5fjEG!cJG=e!^Sk*@2$g#1OB#ZIbmm=HQy2gup&h+0txsY%n{cJ&aF#)63NBG&n zk6t|CqeretJWox-gr@F1o8CW|D(qUAgH2XZu}(0-{0K<8m3j5;7he}I!+Mz8Z4_x6?gGZFPj?Zx zzrY?$Q!uzE7ttnt^9Y-N&zB+tRQ!hW-cHoCM!i@p>GNm@A07*SJmozEj=nz$<@#G0 zg2(WF$O1 zf98msurYrOhbb&GX5iv%`#wvyPngz#Sama$z+tX*L&WeKI#YAUoXNQ&s+uq8oa$}L zqWD~K9dgvF8{cmozZ$SvqYM5fVaVJMc=CCYIKAfl)wd1-8dmFwncqh83?7jz+nYI6 zQJAfBjK&+?FgFf++&y<~+9*LCeg-sr?-NqC{{bQb`0S;Z`~I?fXY$CHd;pXECso6) zlkwlUDZGEi678%_{tHc$6j-dpG4`pj>FWJ1zp_d(8lidsS}ETT6#$(v65Zipm@~S1x=zqX%*fMA zPfIbZ`FMeA7Ie`7hTQ|d`+xWM5B)Z}9Ut!U>_En2Tx))x9L%MQmQBW%`G%x|SI5(3 za=gu;`&9eq$!N6APm%M3x8)JYVZcb4Fkm~uW!QChc_0{3gjI!h1y8Hjegdr9lHJBM)d~Pf0 zdM68tF%c=Dnf(uG|2Uj(*As~HJFV8ikFAv(YAW}I3Hhev4Q?Z^{ zwRd3myVO_WW${^n>fMA>s4;)=O2XsA`TMf$61po}nYyc4jbq(XU94kE%h}UI zQ-AzotWm3spIl^CUzQFbMtJYJH;mVdkb6=d^Wa>9e#gQhoDVSyh{S^oF+p&OK@VUK zVi%Wq+-UJL*4KWrFU-`j*lYd0I^NrSp`u|kP8HkTlv9g4(z7fymk?%#jR}Dz7kFF> zBhFk1;l<+YjE>wxuDuR2P&ptfinE%jUS#06PfAXkhmZ?a7Eio}hVjGm#1AJI4@9cR zBhtcrp$Y7RtPAy>5byJNx@X~(X1o67PNas*CRnGY0U!T)fvqXM@uwb5D+6oYjLDP6 zRG)zti)*YW`qCa27Cqgng2T|yeh7}WHYd(@@a%6DvOVH9`s09wNV%%7#Z6w>eZfQ( z?Y~L>tX8oU!Rd;fUbG+EzLU5~O3qxlwh8ER)u~#n3_H(w+)+3>E)qWk(N3)zg6C0Y zJZ^(0Gb^NuyPWSVgY|!Izr+3a2|sy442mcFJJXZ@zb4$x@j@TTQ|)_NZ8i+@42%df zq}V-bLNiE)8q%xeK0z2NFeG3;>C|;QM1glR(_c71T$um|PubNsD1vP-*iFfU*v+?g z`f75IcaL}a>WsUp7Dj2*ZDWqWH<3sEdE@GATK@S`fjZH-vQJ3;`QcL6tx_SE*RAsG zsKs=DtLM4l;#o>uOHO4hGY`XzTM`SM-V8GdN||s+PEj#l?&{TtyJ~<7VlC_#It*iA z?VVVd*9gW4+vtlCJ2^Bn9J7Xve-bP{JU1RQDKn%KsnKU6Omd4?ygf=qD6rC_t^p zttYKVRf27YaiZN}4Zyh(2>1&<|ACCn$cNr%69^_+Mo04n&f*^aMa|OfzTSpJl5^ZO zX$*J1f@^*5(gzK(R486&P$Si#dAy~N7Mrr!MJjV#6FdjRXGQsiYyjzz&Lqtt@y(*T zJQPo2@2?S3-6EY#BQ6$6*c8DFKH}fe>j4;4E}wr32e2nwq+Rp=UO`K0h>T#lr>aI9 zo&g{}@eGU+51VzzEkaT%qs?BA807@I{eA}1{sGJXu{`n9E{C`3R84pTD2Rh+#B%%3 z1Ac!9k>w}Gd+&&LFBg**oI=G+{Q-kv>nxFy;@S}&12(|vMX2>g;PmrCsK@BPSH%Ve zpjX~Sf+{7l9AiJ4MewPcz!UiK517^-`U#M=6~TMp;hxN zHB>t!sW9KX2gZQeFd6~`CuQ!_m$mG+u}3s#yqzE2TadTw+B2JX7e#)u*Qea`xla$R z0$-+YM&~g~ghX0tB^q1*K=jcpqP4_-SW@TK} zSguh+cy#Sl;#xuOL1e+#Hj_IZlIs#CxRCh9+{Ac$ic;*)AwBEtwi%dM-nCFqvx=XQ zAqj^VHV3(SMI^_5ntM=UJP~4107;&oIn%Dv0V=_l2{zRJBYk{fxH%}VE5(~doZx1f zx3-|$ivZ3Wh^2{fOgcc;HIMUw;$^jEsMf1vsD^EbN_&x@tvl3Pe%s1BQ?P6I4-xI` zh}>lHS6=@};&M!BwJK4+k}sLKGd-@rYPeoKxh>jw&gC-b5&VYzq0x1k=r~M1q6D3>n#=-p4YCzn`zSIQrC#=KSFORFCJJCZB78OQ zTnSgeOg6uVnF;chDAx3=@skhyZBx!>b*>mIg$tAD`D-8&+QN5}5DA@G#aAXuQcjiT z-DIyk+YENzVw=w-58yd&52b9O++;b0_}o7JtW=iO7Ft2sb;XaCgq1Xe4&C8qCMGx8 zBziZU47SMXT>F?&g@bj3XPd%pogj^R*sC8QspiTm6QcRN?&g>4GXU1kw>NE%?t~vR zUS*j!f;`5{=kb#n&bL^b*KSkRc5Ezre~MRY>m(<&+*D^;%Hn%m4LcHoEF8ZgmZjTS znCOiWDw`!|3Qd{aF*d$_KZvdRh2YO+d_LT118PWYHu|*U!$4#VB|?z?rj4b?(R4e5 z3;a3r!Bnyj6s`d(gMV39@Q5rE7RGBfDHqlWk}@28AqOuiIz#`Ijf`FjjgRI0yozZ_ zdjeE^vi~v;dXf^tP(KjDJvOqrFZ;+G)B>w{hvm0F&S7y88>gRF zRk2f}@;mSKD|mZ3JW~n@J^tRLzUnzTXll##_IG^FU0kNxR}j3BdwxW-S&od&N)C4v z`q*H&XxmL6R1|Ewe_>OcJ^16M&^FjKJnEO-T3wqpT_z>*Tsv4s3IGmmGPw!?UJmjk z|0s6ld!H>rSHtwY_pz(ivvq999SC9w>dcawL0JO;rL)GNf|}5e*5Pli(4hXXO%I0q zBMx0{!xF#G>~JH+;U$UfP~I98DP`E+`jE6nJ&N!Rfv1I^U$Dh0@yjhF=uG@n=M`}a zaQe9pZ=xAfv$%s31gl{pUA!H6Gjk6b$0&vG@@Q;}upb1zwFQ>wiES^5j?d_9p=b)` z$f9$i$x-K9m%8%4@@KrU{gg;tpihE+5|$>k!)D3pXZ%6H7Q~EF zN}`&Nq3q8nCp0m>d2TT~DtDAQ+P>Lq9NpsewF4Hq5vcc6>katkC&D$T0a{ARtp{W+ z4aO@vuN_7c*Ifi@5>;kAote%4>7I9M48ezFPW>NgbV z;$&46|6PX70L`FuF-e+o42C-0rZ2qK$&#kOSg9$AUBz}C4)!*1je%x(m(7UJ{fXQk zjat$hIL3Qu^@WEi*Cy0fbsYC(r>SQ^PfMkeiRSmpIU@4w&!VC|ph?eaf}zQI z>!El8T8id;9K&wB^hL$qF=}wBfI=(`sBmWH3&31?z*DPQ9Ft?i0#-2n14HE$07*Y; z_`$;uNNwjg^^4thoAu9Z*#{+*Mt3)h1-pG@>|-x$1Iw)5K8|0}y5l{cz!hP3&(bpe zk@ea4I<#86Q#YNbv4s>ky^jD*y#rim|GKHvvWidaojFf9d&|6vRVN0E^PjK zk8x1BQ&xQ8=2XWSxaIC^J*4?%V|6tiZ%~|?H9|X1-p$nrQ$<`E<@cU?+&C*~tH4%X z%PvLTeb+AgSjI&C6pxqhZ8NJUt~?;!7LMi;!Gb@-uj=#^-lx|#Akw;wfi-uUKV%YY zF4XbXaq>K|+o|4qjB^UnicNCG9%#kLaRvGmY^gOZ4l-Kqp0-9`8wzn&o|DVJTTx%y zZLYWuh8y0Al84_XriH(|Ak?-XwR=beH}jXwbYPvfK?yJ% z1qOT`by>)xufv?tmYVpLi_1Tw%9HmfWjjQI1>?bu(EhnW?=$SB{9ARlbK4+;)Ov)Q z=pczyaq(%cln=cYSI@c~=Q%@SR;ziynWD6fLhpKyP6ga3g?zBTTF|?e*{95i=4x^e z3h76x3Lws8++S>BKek5}TE^FmvIgpT9i!R}@_BAjBr9-#CGLHNSgL7%i-a&oN;gPF zL`hT1jXbs1Pw5>@)#?3Vb1L!miY*~6v_>+)6w(9N{6}-blZ}kZt7+=nue-tUqEsDW zTWTDiM!D>;W&%%vzg_LRgtU3+Z|Hz*V4xV0O<6}>d{GX)R1xB!U=c?_nLh4 zyd^>kphe@-^lwcvT6LhB(EgaSTy113O1rF2q2D+wu$1gnBJ+L&05GV#1RJvK9b*cDLKg@k?PXJfTx6rf035K?*~!P4`~>KpTfHSgGZ z;&Li$(uawA)I<6D+ZY&B@-=Qd{QZYXOGg}b11FQwqsAgru8-T4WLJbJNdCa}>PxMH zc`jXi?|mXC!82s-FM(f;(^G@*ggm*nk~)&*u`!d*TEsS0WPTIp@#FhMmSJ_Om0b;b z`S}6OJbL*vJ66AiaB`SOSCqyT`FZ!_D~N*pRK~m~BswVCEe(YA^QPwNQ3ujqug|H$ zngh^v0~~?5R@bV0U>ygci^qfy_CPCg7j z>`lI3SIUQIZ(DU6f&ZA~XfE{xjC4!e@7ygYVy`X-fVd6M_<$ZFE51I$ z`lcG72nkl?%G?pi7Xw=M8{WJjMf43lte^wL7Sz&|@QYvbk-xYXe3V^qgB;fzCclJ% zC(2pD_sVEhQ((kuK1@mg2;#D@FAKG`9N{do&X82A^TQ^l>0`nPjh@1+|1rM=RJp}} zXT^S*URnUM_-5M|;q*d33vNWYJ=pWWqg@K(UzyxL%2G{8i+3jy@eysM;GMHv2xZ6U zA%%JD2oTJ!N_5vu`Cy6qLYidXH}2+E!tYn4q8}@%gSae7`&jD2PLj9E?9>cZ9W7d7 z{^Lo4VE*U6HfvBGddHO}dCkxGHy=-_3jk8>TgX*2CfV}^+&u2BYX#X>p0kOeXN|-< zKyyZ6_A3A!j%uF5jFy7s9Tj}2jdZsIS2aJV(OJr&fb)ukd%+ZW0f_hso`_%@pN<}S z1}IT4+Ba!6uAJG@c(@tMK)vGa@@Eb0^l2Tw@S(Y-tO3`{;Wd|Ds#KRgvbab4u3h#W zAApaQcllw*bBjlc&v{pBsQ^19J8!7-c%hOX)HGg(68m;BPQ~(^(*~;CHN2l%Y!Kh# zV24Z|G#K`+=n`7fifbfwpbhdTrhG5)( z2#9AA1*cb|1QonVtqN8QttJHco)qtkS~kRM580)NW}J;RZbmYL^&Un!wUWPl$o_h( z5O)}TX9DmLwo!5$YLbrHQ%NRsN83+%Mw&{kC~kZ@z8=MGfLoVXB3vxfzNT5abS*J2 zx{h}0WftHvIHqKPozb2V(I>BWF-u~QyQyvpI0oQR)I^=HFG+Rr{LyfxmvA4j|pzd*>KWYLv2RKpC{}Lo08j8fyOMQ*aLQlyAigc-(29C2oc(n{x z#?)_$VnoNN_2}Y84U8hK0l3J&f!CG~5oiojF~DfJ-(YvLrND1@T;mHHz8e3|k_vhO{PAf;TuSbh zt1<~pz%8kg4Q6YX5H~q6ET0D_Mqk$`XM^LNeriAmz z8!r@Xq8OINyiP!L9uS3X6|Mr{_p%CJnGmDo+Llo!R=TftFV-d3nL^})e&^8h%ok2T zeNPKetkhp1*fu*8*LK#)7R3-|o#P3J z?9caOJ6Uq{n)F?L^_P&`i@rlLt>>ceW%T+-HsTpmsb?{=%TzCE9tdQjZ;InBwGMEs4bDB{51)rg)J}LNDnU|Sqcj@C}V)JX~TR5QWAT%mX zEPT0y^4V7@uSs5gH~;jSmhU4a7dsB^H&0jZNG8Y7EyL6HuzU5=*9zcQW8#zep9d2A zjC|vEV?#*I(}+WRt&!XBm17P*{c=G8)mChRsS^j4 zmzpRkg7kBOg*38@4I%Cb>So&u<#Wf;qiA3h*# z>%KkzcdAwpUrsB3)U)5n(y!walu|x?*c_giepl3yl<mkpVcQqfpu%&gkD)? zD$AGM2zj23e0qr8Z{AZbAO2Rn|4a9D5I50+>dAW_i@YQP%Fi+}e&~fJ<~(R;Mk7We zQX@ffv;-!pYlU|70_YQ1Yo>Gz;q5uCzgQJER20PUOLr)`VaVw)Iuj)Qux%$^CAL!7 z3P%vTjymKw$O%Zg8@{Mi*KK}-I@}WFYFs6FEu?bzYUpZsJ*alQpG2;f8dWbI!n$0-wJ=?x%&}Jfcvlc5=S9cr_(LBux8V++HZ|8 z+jt%KtdN))W{Ml0sV)xW4j zESeZNxbqo&?^ue8M)kWdXc}t&HyCf@9qm*auJS%xn-4~dQT;`5-0HgLYUcgA!o`(Z z*#=Na1pVu_Ffv!(I{FROOkZd{zjsp#OF8N3FHu(UD9-g=qEz4nyl^rFAFygE`WD^&XoxuuI))w|Fiw zOhAsvC|Xz~c79$CP+;m{9Y`IEPfGHp=ByT$j=moCtgbs<+xi#CTN-!o;Rc3Y>#=K_ zXzn`xY=G^ry32??9Xk_!d{=MrlJh61?Vj$PTTOev@B8YBW%ZkOa}=)uazga-g(w3P zu12#HWZN?DTg6-sKhg|AgPUY_f0FZltnupwQgX0GW%^Z@ZgC<2(GDta<+ne-Cd(M; zx}EJ*k!aTVm_KHt5cM+mRjS=7RkWhG--<2dQfH!f`xY zhAzLUR4v$hz!Dd=Q0`b>%axd(-9&FdrrS2K_m5;GYIK5%JesD|Pu(L()~24~-0R9p zu@IY8L_{jR2<4jP?M6%Hgp~Gpu z`d-S`y<=*|V@z|Y=||`C=D1>st9I;}6J5N1c>yboI^orXDOHfN>PHU)Vtchgq`Mat zLGBOa$T?(wgg&x^v)b0TS9aMG?$o|SH9<-QZi_$2W?AQZ&=Sp4rUzwR7RM24Ium*% zEtx$OzOuR~SH3#UY(t4oXL%%*Hq4a*4E8+LcBonqm2@;res!?VaSei}Vq*aI*EU9L z<$Eta^f4&dU-oT{dHkw(@mOKhim<5d zcCZJJlD-n|L76m8nnivQn@Wkuj8q;h8r$2DWB#?}Q`Z_ycm3DBw|;vG?bp!l9*^rQ zP@jJvfc_h6nt;slfVSXW{>_hl>GFj#2))#cHSnH?{%;SLa6iw;wkxxAk?BTPqLFRukPkEFF0{ z+-Nn9dfk41gDZi!duC%RbQVK1_VY$`SZvwNoSR?JbZA@j-2v7B`&m1B)=OWs&(gky z7s+{`QI@FW_9M=3XSG2gj(K@DWvYMaJNUlxqHugzS1sd@YQB*lqD=Z-lgocb@U8~_wq>MECEK_FrZF92*Bc^dO z?rr0%^+tueK-g-x2I+ zk-DzrTk-7&Vhq{GYuz(dPdgA=3zV+{Wbg+zz1|uF(U7W2LiW<3Ujd&R%UM5U3O*tb zssKZ;)tGouhA4|<7{)-!;qw{D18{`!M{$U5ff10g;3EcMF~29=I$!v9)Bla`ex+|< z*$~y#Q{?tM07!||Sos6AeZP>OMYdgw=+Be@pfBQAzmW`hv;3?C{ym~4q6D-aLp6Wl z{AE4W)Omqg*x^Z`I>^e=L`@I9i|@KQ*gu&wxMwx~I5DMFaHimS?ml6rp-BiEP$Dq70kxn>GI?X7tbN6k;kt02pYm;0z0gF&*v~=oySn?wXKrAi>Jg0 zWe|>YNbAPM`Khzqn#hmtJwET}Crnn~{LP*myq|y%M10EM%=m^$9so9lT-?@VNn^n7 z!}tqBN6k$2(QJWjfp<*4zKmd~73OT*sB5);0CQD8SW3eQbe|w_@j{Dl0hqu2TLl#$ zGV(ouMlc_&JnpMQ<4+a#nvb17(?@IC0YTF{)N>BIA8niuRwo7eKe@o#+!Q!k(6hrE z{}Kpt2hY6hxfP7v?Ub=9kYEcTsgmKhestV2>HRYKrUdltdpDFOWk|nib%5~+w8@kx zdKM-=%`PXKp5ZORFMPJG9HPFRcEy;JoG0Q7k@)80ddB26(~xiyXH{11$0nNPwrB8Z zeARYLr?^wEi(La#?n{>On;Aekl*gV!)E!1STU?#Q-KPGB7r!9>)`l(Quaq-`{N?tU zPCUMBnzZj}W)g#b@`Td?Xs-(M@I1UWF%`?wCD;|oltmWq(NO|MNfCy14u0yt_0V3m zynb#wBFjzwe32-DYc&DY*CR&BfH$@TfM%-Bdn{sSw{$;n@|$LA^tp}|HT}FD9WFBi za}Ij<9C?xT`{ahl;(mEJ6rM@ONO%F)V|%-u7%m%|>^&1_dm9-W?7S-`V_^Nm=E}5w z=4)1_rwT8bFD*RFQ+^nK>EwdH^1rl@k=f)u%4s82RIBP+ zI77HsOTB?L5v|-nown4jb#~m&Hd}Rm+htV&opfxTt=H%ML0Z}KxXd6XP!Q;K9Z%Tu za_%FRy!Li!LOO340lKghI~l%tz3WaZqQxCKj-&9S9(Mi2jK8SJ=@z(jTeb(R+djAE z%L^p4_+*bJR_ntEVI>}9VpvD*iJ{7xE4OSr z=2>3%(>Ry6R^dJ=V4T|=yi;9dW(gM!tUZM5%W<37JTyvE%i;U2W^M^kNs zNLw&*`}C7aOvhucOCtJ~&lQ7~ne|!xL7#-cLLQpgU{4JUaIh{ou#E-Bmd2mssp9Z{ z)DiLh#ZW~FY%G#izuy;SjfNVMK;@-t?osWl$%#!)8HtW)&E%;I{r)wBdU-7mi)hqd zC?CN1G{E!z0oc~Z><=PFWAQKTJHPfb!K=#4NB%gQ_4eWLel{n!M-y0fctArS2+of| zBiJB#6^m8OiOL>DB3|$VYG@09%*KrDmLA@w7piJ-uCIM8oiIkBQCs{o`@lD^;R-*$ z!)*dkP1e+r1D}Kh!ECb|Fuc6Lm-t=ol)dnG1X#nW$GRiZ_P zlBj%j?7k#D z`W!VK?ZSx0jpUq-#9BhAHRyvi4W}W}&XE7ZQGBLri^5wY*mjHXUbEd=_G8zZ-`sO?~87308eG-YZcFJ?EWoZo?H+gv$YSA->3UdrjOiy) zk1^OlWAilKH?TFaHMt16fbzIb`RduvMh0JZf0X6~6>+t=4s1~* zO?(NN9oP>}fk`TQ25B8D;f3a3jRxIso6m;em)Gc__ArADUXZp zP^@C0P8y!pbnh+98mm)9;SaRooBv5S8JqxhR0c+j!Hy)0xbt5lfigV!-T4Em1xJFT zPPdG>4a}kqNc_!Lgf^=IIi%JhKCyI}LM%m5GD3NxN1BdaqPo^PkIY9jsUFO%@!@n4 z^q^hV1^Pcb1DHO~rmA=51v)4MMg8+FOHV-0?ln@3d=wyZFz9KVs^yX}EmFx;k9 zxrA^yx$Is7aN=>c%&vfQNuXaoovNZf&T8N}bKp5kMyX1RDtm^!G{bLOhcBxcaeEDu} zXo>X*O3HRg1+EJeA@+#Sl0tL6YV(c{Ps~ALnBdt5{qU2ziiI_`ibE$;2ovB^9 zPP2Cw?@JoRrk!+BwxJTn)36Nza8*`&XOCF%2ta|#U>0C}sxh|sI>RSshcEuR6S4>b z=&Y*}ETr(p%CS01HM&lzoMysvq}Fk*9~`v+WYGTb_e=n~g~{jf4V5gAh5}0wLeiEa zfljI={*>)y=0aRU`_2BU>%6nDWuy`_=LH=LT638iZeq4gPxeM-T}6=c<69=lc%@pZ z;^K%Glv;4Oty(p8g+9SOtx-Aa*Yyo;$A|R`L$DT6XR_cXgHBa3eN2Z_gk+BG+H#2# zB-@&>i0y;GV!0xc)KrdK#aQg7WCp*TTF$I$8Pq zfDun&$u{*0aGpeFP~@yHO47u&iYsapFHa=c&T8bR3?K?sOfiI3MdddFi$Tj4Z(BCC z)m&=&^JWO6&`H!gas$#W2{^C!;nt{}Ze6fBgoYBh9?C%(BlU>yBsY+(FpXVbm!vH5 zeI|H>h@B|3l)c}QA}lMPrB(LQGk<{;)Lw9c)&6x@w}))(=0PS)x+&#vA$*N%BQ9#D z-byU{47gBebbbO@UuQjYhx#3RVX?OsI!^d72aM@lWc;v+5=4Co;c7h8qOU?Q9+^v0;#J?jEy>ft4BPt+lrmud+{m|m*m-_Uhh z2}q+ZN|#5w#;^PUqSc+X!?%|pobZDUCZ78(3XbM)E0J_RWLwV*P1@d@@^;cV5-x=v za#jd%PUn%^O81?_`a>v+RI5e_kdNLd_DDv@nP9a5VRzEj8rHril1DqBK3KSE zjas4Eth{)pHhyj>#bq-91nkzI5*Fqu?8F_x?onSl`Zm+g&ciDWUg!BSy+)=N& zaX+67a>>R>0oc?mG(xwi%(eFcv9)ES}wxZH5T5L zAcNzUTcUz?tXX8gNXu&@fQY80yX}CHDYsMX<{c^4pf3^`z78`%SujH)+N+Xh7Fy4}3*Zl*5Vbv_;M_C{TXzq#BWg17fWF7B(NzMMb$>$`Drw!7X>Zj-y& zy@Ss2y#3jHwG_wq^=lVMR4O)ER& zD5yeGoF%XZP;DS$f2YqJQYs2kBT*ub8zCD1s=sgFeHw{|VWP)G+YQwiIm{_S%G1tM zN(BYFhu5b-x$V5MV12U(Sy!9ov1t)QG_y`Ct(eP2_EXmJBb<+Yp>(WEBkEY&^}&(~ zB&#Dbp+>vc7{3o+Vyo_8hOKwVNGKtfPMpeRGwg)N{klCEoacmUzV7Pqu`hPG{+hkL zR|)U#XmNeN^8d5h?(@Bl=JR^-Sf7lZKP^M&C-e2SdY&&5{j<;0xF$PBmnf7b5Pw2U zmw{`=6p$-n(!y=nh?!0Om-9HJuK|Khhs}5i4dihBHl)pbs7tzRp%teXj5Hbp0WT~7 zn-wzA(N|X!nQnH?Y$C4_8n1wIPubHDT-~Bn3W5N(L;4D z)9hcZ(6vG}K7kL+-0M^u<78)obQ3AoOX=7h2N5OrtH>!zMLV!W`=h5KorBVT%Uh0c z=O?a?ro#B%i!p^F)r3e{ers8Q2Byl{B5j=csV4s{vfoj9b8tmdb1POYVbOOau7T$e zCtG{OLoof13>e2n?rI{8B+r?| z;4d^oLF$pSi+p?W@Fd|-uVO3cC2Ddv4mE1bo);c3?4s8;PAQbyoii9|Y}h*!;Y7sI zNUh|>lzfLZHJMQcGi1U^6biQU$e!~Ml2cR+>8O(O5@(TWn1!}yG&`QoGL)riGPX1J z+F5%Gt3+kWY)&Xj)QqT#i8M<}q#N?FMG*qNbrho*_0n477X=EO&9>^M6S7rj^PXHb^4K-qHmh!3c@6`mI|7N;dR4X~g77l73>j z_`plXE_)Fx7uGH&Qv8Wu$xBM5nkq3dh0Yf{K`jGzrurAepv0!R4}PX@qGKd^r5yG3 zU2(iryI>YaoF-GRQ$|zN$F5R;stQvb{w5ufR-+#o0Xjdv@V;|i!6vtNermyA**d|m z+Gzs<8g@_+U^GPCjt!6CkHa|{foJbBpYZ>3zV(xcSyxXBb^ns)LP{kKFM>rQ7fR0i z{Cq9kfCkz4U6Ua8$*3T?9cGf0m#U%AJ=f?|QTpJvt8LhJ8UqSv76#yiGn#uEDQbC` zp7Qd7eJnu2M}Z<)Ht?Z+(7unc5y2kV?T# z>7A_;I#9A%^kXAV|M8w{{+7!am#WBYZ+Yrh38f)Em+j}l2rgV`{HPz*se?nao+_G@ z?D@Nf-kXbhR47XQuCd2nuMi?_HBoe~W_Wa56s9wDyqBJAb6lN*5mq!MLtDK$q9aDE z{H5xtzVb#rH#Z^wndXf>xq@XXinY-DkCtoU!zbQ__K^?Xo}jXf|~gvNuFKI zrECAJRpc`R%DUwz;EpYT63mORYenvCnZN&*LGb$@%#vS*$JeLj1o;`aP9AL1LHX!6 zdbnaAIlxrhf6waF=bz!w?LUj36+uh!|5Z|&9gFT7G#Zi10P#pI(iy@X^b=I@a;L_xSqma z0+-Q~6976cY7vja#5*GTV2ca~rm8W9pSQjuT}top6gJMFCFI2Pd6`tEov&ye~tlT-tEdP%uL9q{3>W z0V1?SKN`KVI$Cv=wf5d(!@85XlgQ!EQf@PO5IH!h|JAoWUpsFb0VBfbuS!a(X_^2A zzM}5(I0|U;NoNZHa~2eUrHhjpXr=t61QX~6T{&SdDvW*sn&xYGCc&qOwfpxv$H`9Z zh&rWAm2M6gwBFa()?fY-RXk?-)T6X{&YMJmPf1OJ?ebQ5o&TCq_=F%l7S>G)y=k(3 zvi2=SVqGT-T5)}kggW;^Bfle2#Hx3%7tuKdojFd9g zPjvM*=%V>rbd=UU?y{c_sCHm~ll%E@gMG8Pm`wM3NBk(=k2VQY^q{9*``U!6t1Er8 z_n1G)4U3fDtV&{%m$W4Nu<%G9@R?d2GIeaQ2u4NXcZxn;l<7oWq+CZh8xn#-)+4L5 zLJb`xq$0I4^^-GwghXdTASUl;>K&qYKA~U&s+e1A>DC|0)Dvc!lwqRF*^%%71rP~l zEZ%(s#M1{JNB3(N@@I*vpY93dc}4>CgkD&)Mp|ae)|bx!)2Yey`3P$0gC%c%e(vk100DQeBnM(3pG}+wBfc1DV@D=ytL@Z6PxZ@RenOfliaHDkY< zYUW*jbG%^lC@2_NXIfQTAUELdF4jxZrp`4t^fdY=kal>%x75o-6^32XNI_wyxc$8f zj(HFH3&+Z98m@?ie@eQnQ1!qX_wK!I_r9%DQUc*nuFCq*v0a~yf5Ogo9+DVSA0%z7 z?cN<;&w{OH?R7^{ zY6nFrI_{4#{+l(80{gG^vLRKxFlR=y;n7npiJR7g+T;f-S188SX!>~Yv_rwyByD$8 z@r%9JJ&Kpj{P1jWgb@Kh@G)M;^N1!xyJMMnjB1kJScVq7)*P+Zx7N@01x){E+KT9p zVTu33f73c6@xZQ8D@~2H6t_8-AV=i*64MME4KO$95!Sv!|I2+;LAV6(Dv7_J9}7x8 zGJd~{O`2YU8RqRN?@stZXq&IE2c(KCSrtUU{0}%>u?16ErFx^VSA!B;N=RTiRzG|? z{}*1pEf>VM7i{%A1mYPtFN-t>>IR})pI;c1y&@WJ^=?Rtk)!oVTsnD&EI6@ zZ-jScg#C<7_-hC{S=B6BrOcwg+`*f=!9K0gg#eu!&A+%oIr3k1b$u|8v0eTQf)l{` zYb7HpB$#&N-Q5&_l0+ffVU9EP`2fomGs;6}4rz~|YQh)8fH7Dsf(n$fqaC@#pco!r zJTFIuh@+-eJV`4v>ubfdJ(YV!fB%==z**&jJ%OM6#h{<|#`d4LHq$_bb@O#zc&{ej zZ#rVxjJ=T}g4`A}(K4pUUW%ZWK%Ue`b3>R!=Rs}D^1{!jsWDPPvpL8J6_e=L{>pci>wQ!ZsQ&Z(moqJQ$bffRYJL2OR=4?DyqsobpsD`P2!&AImU! z)noX>ZApZJl#oK6<7CAe#L8Wil4jOa=_HvfCgOszt2(F}Y7JKYDBRshm5{VQypg;b zyL2^hxM1ng5u73tAeBZrk3t3;oN(pF?9ZOwo*eWVX~%$+G6H|Ofc&yHI;E*Z2pG#@ zX=4eHPATHfx3j{@MM{o$%<4g-QU-5jnK?5ul;zk_k$35PDcidzM7(v(*bUx4s7iCMHjS2D-jptytj8^f_-T{ zWVe6?yGw;}+`6PlbsljHs`@sI%4PIR;<2-?L0*%Y0&M=-q_~*OMC95}%cc|V3&&Na zrY8#{17i}((CxtsgSw~9l1tm6xRKq5+Upi_0N`s}ji=Tv7Lt`~&iZb>R6nmt@>cQRMh*T3zm zvmix_TNREv+y30-WMBXQSpNHk`Tv}^naUpjoVVW^pm#V`FvhY;mn#%OFtvsg()E3R z&p<5v^hP@V#+jy<2(}_8PH41GcM(0-91we8)Cl5U-?o!EEpeXyeeE}DTbJlsrNqyL zInJML_V0Z)^|XflLq0kPx}|_({kWGYd9Q`%iP^)ESOXt6NWV>&Ya5vmK$!*El4Leg zCn>Q}V@oy1wt4X`yw7hKR<21ex=fQwRlDm)Z&eMKY#M0525) z8uU)vK%^KFB>*KfeJBV45aY0saOt3_Es66_Ac7(w*}fkqUkd!`TUvTV)@v>V461u* zeQ%g!vsnG6vwcT?$NJY=b>9iQnx7g-xXWpn7VbxJ+}}1NqWwXea5;Q?R+>G zp!S@mMQtC{$Tk^6x~K(tixOSNS)X!Mx}Pj4@UU?^e^&~Kc=s{?hQnQ=)WJ~3B1C1p zIBiE+5Q&d#TzdOe&0ZccNTD3yhF-rMhhq!@p%6=* z=uk{|FFUva#q?AZm5kDd4Cyi}ha{=ci`v9ItJK>$3*1t^{A8JOyNyvByTeAB&5?c2 z*=3JyB`abP)LvR_*5oW?7hBJ7(B9Xo>JhXmcI6c62=^KeWxW2v`61HoSXZyxCyb}J7kI`Pw zo*P(FXFOP9QbH*<0K2pqELphB@$GuUE*0wghEc~&N~m@bXibv~Y);vRDGHta#D$J% z>JE`WbtEqgzP>mBCl4JjZcn6Y-;V6{ew~4Ho*42;|CH6nM@EJzt!Ga|i_YQ`Fr92i zSXSOimB_5%1d+i7vt*I>>%9D0ndm1zysyihlO#RwE6{b~ zfH}m16ws!7M@;ZSus^dGR~$)tNFp*Q~3Uz_Sr|jBij^d35xOq@@6BCB()8; zvc-P6S;2+d2t_qYVN!(`Efh@Im)QFJxWxWV;@sl=wKWxi_7R-Z#`w8<3g{gO`kL~E zv(C|r=NGF*bQM%|9IJt6z(zMg!KGEUqM;dlRe)ByLF^e4KhJt(N| zEG87hNVT4Ya(*)$=?WP&N|e%Hv~M>XCnqX{^3u-bXGU^Y-N@DalbN;|D6WlIY*l9x zh3sqJ?Wg_l2tt9M|0QVxb`D%H_y;aNe&B-XKkMN?U}0skP6z*`De%=l+b1f%wN|+) zs-v3bR7pVP+Z5pi8Rl6Vy(%AL*u1sk{VpxOv`AqT#CDh8ew=mehvJKM9GSL z61%|&3^uqQu5)YmW{1vli$j1ikhX7hg0?E+w~AIu7zlNvuPXb5gSZ^KHlsYahHfO(ANZ(yY(H`|Y(t~q*dndSkp-khkl&>xLicaw!M zXSO;mN{Lea_JMfgsi^3vEnJseU+L+nZ6|3@-^{QGs#ddZuQSvni^M7&M*r`l2Aak_ zf#%;BkxS|_+4b4ofU|+$L)1-SZd%!|Z0T>^2Azdo+tJpk?KCTMaGH#F#7cd+HX?-- zzEBO;q|n>MJSU`_BpTHE=N_|Gs;--GHTf^|2^Ag$d3>r9lMv9LvLParW4|I~&04lP zLMhUcZ|C7{=xJ;X7&m~B8KC@cn|*S3ixRBU^|Qs4Ev(3@FCrrm8n-Qly8S-54?G$z zh5kJ!y5z?^vRDJzr}G0R9zSrx^WQIQK{I@CqQ zK}8snNVWBPp2A3aSzP`2BpQTN^Poe;&nj1Kwqp|vN9o&=;h^Bvh_ACeuC545$HSj6 zN_<+xoZl0y_yL1#`f`@vr<%Yzzj$f1!J-4+nf{)e#urEi(8FuvMZN~vi7O1T-q1_k zW!k4B^&(2=4c#SF#3h6fZ}xMD>Gj=WPzki;dq=r?v=n=f#FMYmrTNn1$&k4`7x`t} zNYceZL5{ZVYCz5Uro(SDLN4<_n06#Lx$xv~B-_T1u5`6_&ATqk0aIQ=%Rh+XnaL&| zm>dw22QPYq&yNCqxO0EgrTPGWFcKzRL+I!=Tw~;G?YVeWAruoM!IJ@MFzU!*`Bmg^ zUa$MxP+h#o810Y&f_$J5fV{0n-$iiCE3Im!UC0ZAh&`WW7V#V9O5{q0F}3B~;4;+Z zmgN9Sl+prhqtkAE5=WVxFJvgv>YH8SsmL|!0v5<0NAEzdOlF?5( z4;06Q?uhScYiEHuMotE--v$RqkFSr)?5DpU8hUen2~}+`^uYu_#``1)Z?D}*FD5BsPChEh0-csmDz%XYO7~GJ^rM2R zQd8JJ9C2pAiuNwSe{=amHafC`V`c=w_&dwE|1GA;mZXykzD?*Q&#OVfqRBLXF3?1c zp=s<3 z$D)r-+7v`v(bK#Jo3=UpV*--7wL0oSLfV_W)b)0!$9oqA$>~tXH!-NQ-UA-CNGu(e zyzB3m64&7!65iQXG%x@TREzp5Jh?d3qGQWQmDf>^j=*gW&5FpqeZYlA;%eB?i!Qfi zFRaSm6fe5=?%U;(J^WD>1m^OUWZ^$98GO?Tu~QV@PZcP>d#2SFV-ku<4Q@bRf49X& zP5#wBIEd-TKwP6dM3E&F%&-3xub*vvCAmu|Ap>UVWmX$xLUK zVZKHC*M#t&)@{xlxTo^NBso7!!u5aFx=jP+_5NX#Pfh>tf7nDKz6nE1gky+-)e43n zfW!#P09c4;eb|yh)Lz}jvfIm~l}c=s#oy?4Ym;-+gM%Fs=!RC%T?uQ<9t_6~{BwSO zdDHs)q2jt%uMSmQ|5rcZe2}KLpKQ7hQDQ7VQvpK@eVh7gU8rqAB6-tJ?GI{ZurL>_ z@m9Ffco9y>Do?2NV;faD<}&g_Wsd%M9FBss7?hV{%d!2Wo6T9(u>}(Dw+NvNMQbY3 zH&Tfe>vF^QQ% z9#~(8)Q}mV8%D7?YgJoS$g+X`bKwu=mx{93H(K@N+#STb^42h93Y^#`o<&i&d zb9zkkoQ*YFK1atpY{yktJxE3V{^S!H3>|vQfJ?`k==B3s_NR#D|zy=|}g1 z07}CE?%z2XH??cj-`GsLPr0QMGs^RY+|V zc1U!%)dgS&{XMD1V=*MxVqDIV?sfxnZm<%D&5YJSxlvzJc)h}K7pMjmJb9pj0dT1Q zak%*UIv!q~+|KK~7@8?6X5LG-8W|d#xq^@&wQ&WkJarLK?~lSl^5>HrY(#|>#((=? z1*`NUgzyaXSCap*hSJYSTkyYMu)=x{Kcw+*S$6*rN22nr%^nN#SE~3Y-d5Eb1qHEe znVABCCGR?tyhi4db9<@42r+ESFJPU?CkF6&gp5hY+O9w z&ptM-${+AzX3K@zls-nAK6jpKbH3A-AVsy6aBN|MyEaU#RJRp4f-goSQq0vNb;R-ZTXyR zfh>wAe%}yqWd!F}fd#cGMr!kyt>alx3qKIyx$P?J_=OXoOi) zI}&$$vMTr)u6}g0fAQJ}+U92W?#$ngQ}35TzvQ+i5p&VmUEob<$cc&1YY~T!2;KMh z@l2)1gTNGG(PEA{k!P&F-*|zslH&3ZfgCx2!Fa_Juvm$DY>eNW+%z%6R=KWRAC?bVi6HcJ)+nSOw^_5DyO|MuZ@EToI`+u3Cs`Wu_c z6a`u0S1;&MN%v7pII!?cAX)Dk)d+>F#Srr16)@Nq%pTC%PgHA}dG2ZLSR|R+m8WA_ z=WCM9Cn7RQ5Zo&?F746_6-KNMkU780hp&f@or4)_Xdq2)$Rp4tH;} zf@ExU`zi%D2_7PyFG_{+)r|vb5aKL{w2r2=CNY!+CJ>GosRRg&XgLX;283?x=70@rV^5H z=9D7w8srsVc2*dysrDR&lb3Z*l_WRM7vv19_*~7|vgkomSc_Arq~7MJN`y77>j@|S z9H8za#--K3@Us%NRo&|iF0gW3uIE3y(WSYIz4P~u(J$5Ql%~GmQKhH5sXY zE!9Oqa<6Ki(rn; z3bfWg_S|aNe9-lxF@s-8>5(1_;`=SfK2+rZ)t^WgJ|PA3P;fN3CfA;s`OY#+u%4Z} z=J^Ump~0Van~RKA$fPnh2WY*(mG>H}Pj1BsfYI<_&l*IG)E&=HJ+y|R&2xnL~S z&A*w8{y_&Ri%SWwA9Ps%K?nZ-8=d%niW``G@Lw4~-~BPXa7{@N;kG4^mmMb2}|L}=Pmt$>;@RmW6V&!#}0HqiJxyXjg0`_TEi30F0&!4jG zmy1|GRPe}qm5=bFZ45Sn?Z2S%JlkvyvL^F(mmv=(m4ZBaPysig+t?{VDH#~!7;+#; z^!D3w--I!7(xw+@f?ceNtL|{{7-pqT_rA}0nhccY7ePtfh zBHxm+M}4ZNFvrvDZ8s_p^Nf+yqkyRG%b`bqn*^s803p*)L%#N~Wt<*JiY$p?m313G+ltpAOZ z$ja_2$#laMvCz}x1G~FNNbyH5Rcd=rNB{65Dbu7{qdkw)wvigHm^}ZJ-suKf0rDwR^T{cz=^#=SGW-O_u$Yyoz8plBZ0Duqx z00{s0i~9#L=o#4lKcI1`HW|G>g!0G2_Y-f3z71a`k7ubCK{XF^R2%Epk_J&zI&f(JD;zvr_}gqQ$mR7AnvN9oDlzG`%jk-D=VM=V4+Ifv)fnGya3WL>DruhF z4360I*kZXBHK?MWwAiE^$&=Dk>xErCJlX4j0`d1&tD4Iv$zX+Gqd4EO=Tm#p!2L-X6i!1dQPBQ zaahm86bvy24;!LPtz@+JMFs=Q)vw(+&@O(?8DzBVMj*c6cqGhNEN|OBr6H1~#5y5Y z5eXZRt%aFj4*o(13Eqj-V+x&l4&#KP1W2h3X`}ZgLoG33)vPomp|r1Q*UunIx+m9!5Xpq06YfY2nB(AL<7yfIWs8^hs*603 z86UlaRpa;}N0+}Wbqy4me@x6gzg(Iz)atUl8xzGfX+nj1Uj#M)GrR#d6?WISFW~gbwO4f~?(c8a2KOJL-8N|b=nHaoE$mrfZW_gujNpP1j&OY9U^XI-I~ja9;{J z2GN4{5V$Hm&gJv@Sz7HEKb&fL78=z;95-B zrIiiQnzsDjvW-+up5l;esUv-CE7L*;7i)|rt8=^Ji&F3N&qWh)Pkp3R+Q<_?dijCB z^+Evki*WvdADCJh5x%?OPcRGsvbcZeapQ4s2mM#gz3!izZMt5^b-wR^5}@8URdjrw zKmT}t7hi98iPfNNu(&xrh2Iy)oA^(MfNV;g)r2Sp?Jk+WY+z_8H!r^RV=deqcY8fP zHh+7*gED{J>fj^-K#r21JRv&C+r&{S77KHZnwn4-*`ZRP20Gm4!rK>c2;+Gc$Rp+HPfZ@h zef#08!%GLIDCrVFA3sqdqlaWqPioFP1Q9_`-LI?@Ej3Dvk`bDuri6pWH2UJB8hNl@ z2*m4!hSH;4N)Y`DXFgVcy_h1igp=Npf0mI^haX|ssFQhqjNpYESc5TuqBB{vyfCQ5 znW^|mw8u0uRcoem(Qi-<1fEB<_!nYBSkVvYP-gTJ6_SMCRWa!Z8QSvCV ztR<`c1N2VFk^dtHaiCe8lU+C7ko*G+~6dGuesI}Wga|UqwpM8~iQC`x- zdhEU!Lo7%m8b@Ze9(^DwCS-h=05$UIBI2lHiZ~T3Y+i$EItoX}zg3m|r@YVH78I33 z8j}Ze@E9xjtPRDR*y0x$S}^k*0R(KuC-NQT6!UW{WQR#D$(0LR4KOqZeM2S=G0c(L z_~ZVjl?DK%S8%oD@PAW4@<2-Y3RrV#*}DEf>~>hDsQZj^u4~$~u%>cc&FR*4nI|zT zIuW-CRcfPM7cBY-?4a3VDZRi3TxYSw@_r1 zI`snyS}mz6C516&Yw36HBw8qb)NYP+L`@M^(%@uy5;0HP?DsE&*^nMMc==s&P!bhe zaPdndGD%kM0TDaS8wM_LEUjLS|5$Q zvmJZYa=W@md@-P$RjFa^+MF0gsvSd9ydYJsZmgvqWZmnfWSO6@G^YpFa-qvYYQV0b-gE8hd3J>A zJ4|;qXyAIs&1Q#C^}Z`BigmC6=b+Yx(AtZ2ocm)#Gp7-OIpx_PRr7Bbe1l=%O`g-Ab)(I>u+k=V!0?zt z=%H8@*nSshHAGAmEpwWMCu|2ECQJsF`xl)nki~^R%KGfSN$5%BM3&skn3J=A>r$4> z@W`mrmA8Nd%&QVDkNicI>$=_lg<+>Sob{OuWJ=Cn4s{vIk(=B8Uc?Jd%K5pOcMWf% z|5XgZD)QWr&q$6WO~CB~pGCBy9r!)so?7X=Hqq~Ib&Gn8PQBu651l-wn-tQ`9&#*k zAxohJn6TsaYAqDY_Z6=M7NYj~k(VHtm|RE2a-@aAbq!V66VMIPm}lVx&zW9+c(2N# zQk{$<;fiSKs)Td(K;y#Hni;+trf_Jn72~Za43snpCB-%r6sn~E^ezT8rKa;sfck60 zZlNoyzqo;zOnF1!fB70C_j`%kQ4E|kQS;=hyf*ac zJPZQKS6Y{|dQou$(xke2LvVZxcRY2OuL?B9hqKi3(~pF!4tATIs?QQyz{ z#HaN?o||>h57=c?@B|DCr-(yAWkL@ZUpYUJ@Eq|{PFYO3AoiwP+Y)Y4Rniv(U zGw}HO8xj)F+m-E*C?$-L2cgLuGL|FT7p6`zfzS{2s*WU>lCojnLhL7ChFGyh)K-&Y z3mOW}x6X1$q8}nC?F8(`dbrxEH@kXSNX4B$%@CpSBhnmT&-8|+D_|O-Z(>iGB0I!} zKrp6!=4-pUCkfyZL#$wt^bdOCx$jcFeCB*RtoQ)FI3OlXLUi{4 zc7h%H38My(Ku3s4GMP7q=Z@t`klpnhE@t(ed&z=tA$SUO4iY72=Kt&o89iO|LC zlVU6iPFZD(TZK}b)Nr_AO4YblBd5wr^n{3En)TrB3;jVf6E_-&VP|L~){GB*91jGI zBi^II>DAB_iao`?w2EbalS-8j8m~nzg-I|hAy;yU9h0t9FXz!W;K?&!!wveZcRnsP zi_-pbpXr~f&)*ITCL`-NP!zz?Y_TcD;EHm@=Y*4~C-3v+A*Hk)f~yW~OHN6T;j2ue zs7GKED@}_H@tY%>&LO8^l>B3$iDlBJ?4?t#%uuxwU@#WC6aRsfF- z-_rx;*Ru5pG2F0uWnKK`o6#(;#;LNUm1!&4E_-!Q7ya_uf_a3RLSqotrz6;bJgT}X z8%bl0K77#gkpxz;-Yb(YC&IJRBhp!Ps!A4jCTZ_lVYltx%(;4#mOA*KT$HHUXQ$s69Y`#}S!ThcAID_5WUlV!}N$OdS*=v-i( znV1O^3bALJGxBr?6eb7=+&9Q3vvMS_BkRu7>W z*&n@_h_|IAgV+mQ#<-n_a^5L2Af;!oa6{osPeop@h6nYAx&~`pF0qOxy?wibN(``P z`X`mCj&}7wEy+%{D(C4!r&|cQ%8`h9$k;*3emb6mF~kG!FJs!S^%sPCvpiJ`W#UzP z2k411%@E1!FM@MO6gOtZRU3qJAGlXZxgZ+6O}piF;lCCVHXJNM;>PF&t`zrXEgd6vD^@5Y=u6v?5sk9P>{F%yNoIP1R`C127%)at|F5M-st%fL??stt_~illKjd4&T^@wg ziNBd;9G2BVe5WwhVyE^{W3Va8vIni4hP=%v{yKvaWX%!ov^RO>0Quhs?`ssH?2yWQ+J&7c2D@pEGS2eyy@T^;$Cv*~Ag$frk4Vi(u9lGJFV zmedqf5zx2^RfsIqwK9zSzov&|BTY)_Lp)LlyV+TtM$lP5kaZUh?!6*XyjB@ z2^8tl7bzCUqszFx)VPb1j$)YfJ5IV2rYG>i^2jZg{8z2S3mYivZak+^KjwLA7HkTT z*lwV466Z)EXWFZHl54sC4vapg?f}~S`sUYFh?_-uMOOZ4jB6MKV}4`#W`jjVHaH1| z89zf})&RO#>u({KneJ;ZxmX}GNMP@GNWklYGMpcy^>1CH$uUHCy>!$3N4eo7FVJM^ z1oUCm7@<=F=R=t}jbNs65_K_tU-Bh>4>@5vD=zTD37VfNQx`*H@Oq{EkXoFBULKT1 zQhJeZW(oUj+xzOn9I=$MSuT`j ERGyUt09h1@i=E41>D@!~3Asg5$@fQXh4paFN z0d_@dU9CtjMWQY2kRJDidPxTT)!czcTE$r_A-iOJ=5Vj_yHm-!TKpsP_~+}ht?D{X zX@tRUgA{rnN(fb35bQ+%Ii@BJRT8!5&$J$tb@}oU7l1r}eA2-9cDk*pVAk_#3ax)v zc$%*gC(#|q^#NKC>?@to2JZg92UKgtfBR!Ih?4cu&vD`{OzJ6tuDG8* zxfxeKZ~~U=?jo=|NBJvseU=rv!kt?ULaWYY>u*_l8{z`Q`X?6_blq1u(Ujrc#MynpLS&IYcw_BQ61>Z{iKEXZE8Gd}PE(0g2h4?&W1 zBbY07@$_eGL79g}0RBlQDL7X6rIH)c-4$@31z-H7i%B#Z+6knS2P8Em4sg?*T*yL{ z-ye_7AE%>C0V0CrO_gb?abbCXsVA3eA7zoWSa^6){!sk+CVme2#F|T)5i~f#ya0^@ z8!(l!Y+0ER+8t_waYvg~s$E&D%Md&mFEzb;KUsGwrowv&ogv2EM7ZQHh;RBYR3#kP|93ECWmO z(pClW?>C=#n#m3*eTGPSLjVWv8it`KxRGIIT7)c7;0xyke$mfWk>|lw)OEXnUqGTr92UFjHeT>9nW$I?-9RhSTCm=fhY9VIE5_ zZc7|=&C)abW{)}c8g$Jw`|@?GB!J6_YAJC!mnkjwr@4>tf-T!zU;-dr3V{`D9m$~o zr!gm+zTl_|GCY*41$(?_oODdL)=;9NGY)0eS;9bi8HHaHiMz7XE{;6nbfLnh(__D7)0i~aH~o)qD9|?QSBI|*3b%Y3S7U=)5p=i1$SuH|-Il+TRdS6|R8Ke^Uk zD?Kc(DAQ+BpUjo?+zQW!#U3x67dk0V^{D9$p zBMS60x7FDZs8rin#9QT z#}=-ZtHv=t6!ncLliCo9tMgE%l-WbP?^_ka{+;xzpdpM6e?)V)rTr8@MS4lCtdWvB z23AC47AF8jK?a#Qa1gMIvuh%Vuo#b*b3?~}WLW?vyu|0}#?%3}yx9>txR3o2<2qgQ z;!DjW#xg9Y%fE3KvWy=K{T({LuT!SU*$O<6qMD7`mR4E=apgbUjI4ys61>NM2?Ig< z*s_D=QXBgG=+nB@g#(EXC27ZNrN2={>wqSvAqh_THMOw%_3?_o{ub&)<=c4+8+UqH zEb`_4t?6WOq|q>3eGa=iwcvODac`5oVv=1ovPu1Gy2IXuQD&c=JSNLqqq?%XrHDi3 z;VUg>9dfXBTFlT|QdD+L&o+F2!&(S0zg{0QGhZi&$k#!QVHk-T%e@1Y_ z?-q#nr?LL&baK#ktH4X*adkrG4I?1rlJu&UNtaw^bvw&K_zXhnx97e?f)L z01<~%piQ?SI1rE-5)csIzmE!)9E^?s0fpJB?f_d0%0DeOu8t;6oY$yKi2iRY_r}I1 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 F@PFxb4{87a literal 0 HcmV?d00001