#include #include #include #include #include "rulescan.h" #include "UniversalBoolMatch.h" #include "Maat_rule.h" #include "Maat_rule_internal.h" #include "dynamic_array.h" #include "config_monitor.h" #include "map_str2int.h" #include "rulescan.h" #include "json2iris.h" struct _Maat_table_info_t * acqurie_table(struct _Maat_feather_t* _feather,int table_id,enum MAAT_TABLE_TYPE expect_type) { struct _Maat_table_info_t *p_table=NULL; if(table_id>MAX_TABLE_NUM) { return NULL; } if(_feather->p_table_info[table_id]==NULL) { return NULL; } p_table=_feather->p_table_info[table_id]; if(p_table==NULL||p_table->table_type!=expect_type) { return NULL; } return p_table; } inline void INC_SCANNER_REF(_Maat_scanner_t*scanner,int thread_num) { int offset=(CPU_CACHE_ALIGMENT/sizeof(int))*thread_num; scanner->ref_cnt[offset]++; return; } inline void DEC_SCANNER_REF(_Maat_scanner_t*scanner,int thread_num) { int offset=(CPU_CACHE_ALIGMENT/sizeof(int))*thread_num; scanner->ref_cnt[offset]--; return; } //return 1 if insert a unique id //return 0 if id is duplicated //return -1 if set is full int insert_set_id(unsigned int **set,int* size,int cnt,unsigned int id) { int i=0; for(i=0;ibool_item_num);j++) { if(hitted_id[i]==compile_hit->bool_item_ids[j]) { region_pos[k]=i; k++; } } } return k; } int region_compile(struct _scan_status_t *_mid,void* region_hit,int region_type_size,int group_offset,int region_hit_num,struct Maat_rule_t* result,_compile_result_t *rs_result, int size) { int scan_ret=0,result_cnt=0; int ret=0,i=0,j=0; int r_in_c_cnt=0; void* expr_compiler=_mid->feather->scanner->expr_compiler; int shortcut_avilable_cnt=0; struct _Maat_group_rule_t* group_rule=NULL; struct _Maat_compile_rule_t* array_mi_rule[MAX_SCANNER_HIT_NUM]; struct _Maat_compile_rule_t* _mi_rule=NULL; int region_pos[MAX_SCANNER_HIT_NUM]; _mid->cur_hit_cnt=0; for(i=0;igroup_id<0) { continue; } if(group_rule->compile_shortcut!=NULL&&group_rule->ref_cnt==1&&shortcut_avilable_cntcompile_shortcut); shortcut_avilable_cnt++; } _mid->cur_hit_id[_mid->cur_hit_cnt]=(int)group_rule->group_id; _mid->cur_hit_cnt++; ret=insert_set_id(&(_mid->hitted_group_id), &(_mid->hit_group_size), _mid->hit_group_cnt, (unsigned int)group_rule->group_id); _mid->hit_group_cnt+=ret; } if(shortcut_avilable_cnt==region_hit_num||shortcut_avilable_cnt==MAX_SCANNER_HIT_NUM) { //short cut for rules contains one group scan_ret=shortcut_avilable_cnt; } else { scan_ret=boolexpr_match(expr_compiler,_mid->thread_num, _mid->hitted_group_id,_mid->hit_group_cnt, (void **)array_mi_rule, MAX_SCANNER_HIT_NUM); } for(i=0,j=0;idb_c_rule==NULL) { continue; } if(0==pthread_rwlock_tryrdlock(&(_mi_rule->rwlock))) { make_group_set(_mi_rule,&(rs_result[result_cnt].group_set)); r_in_c_cnt=pickup_hit_region_from_compile(&(rs_result[result_cnt].group_set),_mid->cur_hit_id,_mid->cur_hit_cnt, region_pos, MAX_SCANNER_HIT_NUM); if(r_in_c_cnt>0)//compile config hitted becasue of new reigon { memcpy(&(result[result_cnt]),&(_mi_rule->db_c_rule->m_rule_head),sizeof(struct _head_Maat_rule_t)); memcpy(result[result_cnt].service_defined ,_mi_rule->db_c_rule->service_defined ,_mi_rule->db_c_rule->m_rule_head.serv_def_len); rs_result[result_cnt].compile_id=_mi_rule->compile_id; result_cnt++; } pthread_rwlock_unlock(&(_mi_rule->rwlock)); } } return result_cnt; } int exprid2region_id(struct _Maat_group_rule_t* group_rule,int expr_id) { int i=0,region_id=-1;; struct _Maat_region_rule_t* region_rule=NULL; assert(group_rule->group_id>=0); pthread_mutex_lock(&(group_rule->mutex)); for(i=0;iregion_boundary;i++) { region_rule=(struct _Maat_region_rule_t*)dynamic_array_read(group_rule->region_rules, i); if(region_rule==NULL) { continue; } if(region_rule->expr_id==expr_id) { region_id=region_rule->region_id; } } pthread_mutex_unlock(&(group_rule->mutex)); return region_id; } int fill_regex_pos(struct regex_pos_t *regex_pos,int size,rule_result_t *rs_result,const char* buff) { int i=0,j=0; int group_num=rs_result->group_num; unsigned int * position=rs_result->position; unsigned int * length=rs_result->length; regex_pos->group_num=group_num; for(i=0;i<(int)rs_result->result_num&&iMAX_MATCH_POS_NUM) { break; } regex_pos[i].hitting_regex_pos=buff+position[(group_num+1)*i]; regex_pos[i].hitting_regex_len=length[(group_num+1)*i]; for(j=0;jMAAT_MAX_REGEX_GROUP_NUM) { break; } regex_pos[i].grouping_pos[j]=buff+position[(group_num+1)*i+j+1]; regex_pos[i].grouping_len[j]=length[(group_num+1)*i+j+1]; } } return i; } int fill_substr_pos(struct str_pos_t* str_pos,int size,rule_result_t *rs_result,const char* buff) { int i=0; unsigned int * position=rs_result->position; unsigned int * length=rs_result->length; for(i=0;i<(int)rs_result->result_num&&iMAX_MATCH_POS_NUM) { break; } str_pos[i].hit_pos=buff+position[i]; str_pos[i].hit_len= length[i]; } return i; } int hit_pos_RS2Maat(struct sub_item_pos_t* maat_sub_item,int size,rule_result_t* rs_result,int rs_cnt,const char* buff) { int k=0; for(k=0;kcur_hit_id,_mid->cur_hit_cnt, region_pos, MAX_SCANNER_HIT_NUM); assert(r_in_c_cnt>0);//previous hitted compile was elimited in region_compile for(j=0,k=0;jfeather=feather; _mid->thread_num=thread_num; _mid->cur_hit_cnt=0; _mid->hit_group_cnt=0; _mid->hit_group_size=4; _mid->hitted_group_id=(unsigned int*)malloc(sizeof(unsigned int)*_mid->hit_group_size); return _mid; } int detain_last_data(char* buff,int buff_size,int detained_len,const char* data,int data_len) { int to_copy_size=0,foward_offset=0; int ret_len; if(data_len<=buff_size-detained_len) { to_copy_size=data_len; memcpy(buff+detained_len,data,data_len); ret_len=detained_len+data_len; } else if(data_len>buff_size-detained_len&&data_len=buff_size { memcpy(buff,data+data_len-buff_size,buff_size); ret_len=buff_size; } return ret_len; } Maat_feather_t Maat_summon_feather(int max_thread_num, const char* table_info_path, const char* ful_cfg_dir, const char* inc_cfg_dir, void* logger) { _Maat_feather_t* feather=(_Maat_feather_t*)calloc(sizeof(struct _Maat_feather_t),1); feather->table_cnt=read_table_info(feather->p_table_info, MAX_TABLE_NUM,table_info_path,logger); feather->map_tablename2id=map_create(); int i=0; for(i=0;ip_table_info[i]!=NULL) { if(feather->p_table_info[i]->table_type==TABLE_TYPE_GROUP) { feather->GROUP_MODE_ON=1; } map_register(feather->map_tablename2id,feather->p_table_info[i]->table_name,feather->p_table_info[i]->table_id); } } memcpy(feather->inc_dir,inc_cfg_dir,strlen(inc_cfg_dir)); memcpy(feather->full_dir,ful_cfg_dir,strlen(ful_cfg_dir)); feather->logger=logger; feather->scan_thread_num=max_thread_num; feather->garbage_q=MESA_lqueue_create(0,0); config_monitor_traverse(feather->maat_version, ful_cfg_dir, maat_start_cb, maat_update_cb, maat_finish_cb, feather, logger); if(feather->update_tmp_scanner==NULL) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , "At initiation: no valid index file in %s",ful_cfg_dir); } feather->scanner=feather->update_tmp_scanner; feather->update_tmp_scanner=NULL; feather->still_working=1; if(feather->scanner!=NULL) { feather->maat_version=feather->scanner->version; } feather->effect_interval_ms=60*1000; feather->scan_interval_ms=1*1000; pthread_t cfg_mon_t; pthread_create(&cfg_mon_t, NULL, thread_rule_monitor, (void*)feather); return feather; } Maat_feather_t Maat_summon_feather_json(int max_thread_num, const char* table_info_path, const char* json_rule, void* logger) { Maat_feather_t feather; char full_index_dir[256]={0}; int ret=-1; MESA_handle_runtime_log(logger,RLOG_LV_INFO,maat_module , "Maat initial with JSON file %s.",json_rule); ret=json2iris(json_rule, full_index_dir,sizeof(full_index_dir),logger); if(ret<0) { return NULL; } MESA_handle_runtime_log(logger,RLOG_LV_INFO,maat_module , "generate index file %s OK.",full_index_dir); feather=Maat_summon_feather(max_thread_num,table_info_path, full_index_dir, full_index_dir,logger); return feather; } int Maat_set_feather_opt(Maat_feather_t feather,int type,void* value,int size) { _Maat_feather_t* _feather=(_Maat_feather_t*)feather; int intval=0; switch(type) { case MAAT_OPT_EFFECT_INVERVAL_MS: intval=*(int*)value; if(size!=sizeof(int)||intval<=0) { return -1; } _feather->effect_interval_ms=intval; break; case MAAT_OPT_SCANDIR_INTERVAL_MS: intval=*(int*)value; if(size!=sizeof(int)||intval<0) { return -1; } _feather->scan_interval_ms=intval; break; default: return -1; } return 0; } void Maat_burn_feather(Maat_feather_t feather) { _Maat_feather_t* _feather=(_Maat_feather_t*)feather; _feather->still_working=0;//destroy will proceed in thread_rule_monitor return; } int Maat_table_register(Maat_feather_t feather,const char* table_name) { struct _Maat_feather_t *_feather=(struct _Maat_feather_t *)feather; int table_id=-1,ret=0; ret=map_str2int(_feather->map_tablename2id, table_name,&table_id); if(ret>0) { return table_id; } else { return -1; } } int Maat_table_callback_register(Maat_feather_t feather,short table_id, Maat_start_callback_t *start,//MAAT_RULE_UPDATE_TYPE_*,u_para Maat_update_callback_t *update,//table line ,u_para Maat_finish_callback_t *finish,//u_para void* u_para) { struct _Maat_feather_t *_feather=(struct _Maat_feather_t *)feather; int idx=0,i=0; _Maat_table_info_t *p_table=_feather->p_table_info[table_id]; const char* lines=NULL; if(p_table==NULL) { return -1; } if(p_table->table_type!=TABLE_TYPE_PLUGIN) { return -1; } idx=p_table->cb_info->cb_plug_cnt; if(idx==MAX_PLUGING_NUM) { return -1; } p_table->cb_info->cb_plug_cnt++; p_table->cb_info->cb_plug[idx].start=start; p_table->cb_info->cb_plug[idx].update=update; p_table->cb_info->cb_plug[idx].finish=finish; p_table->cb_info->cb_plug[idx].u_para=u_para; if(p_table->cb_info->line_num>0) { start(MAAT_RULE_UPDATE_TYPE_FULL,u_para); for(i=0;icb_info->line_num;i++) { lines=(const char*)dynamic_array_read(p_table->cb_info->cache_lines,i); if(lines==NULL) { break; } update(table_id,lines,u_para); } finish(u_para); } return 1; } int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id ,enum MAAT_CHARSET charset,const char* data,int data_len ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num ,int* detail_ret,scan_status_t* mid,int thread_num) { int region_ret=0,compile_ret=0,hit_region_cnt=0; unsigned int sub_type=0; struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _scan_status_t* _mid=NULL; scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num];//dynamic array struct _Maat_table_info_t *p_table=NULL; p_table=acqurie_table(_feather, table_id,TABLE_TYPE_EXPR); if(p_table==NULL) { return -1; } if(p_table->cfg_num==0) { return 0; } if(p_table->do_charset_merge==1) { sub_type=make_sub_type(table_id,CHARSET_NONE,0); } else { sub_type=make_sub_type(table_id,charset,0); } scan_data_t scan_data; scan_data.text_data.text=data; scan_data.text_data.tlen=data_len; scan_data.text_data.toffset=0; _Maat_scanner_t* my_scanner=NULL; my_scanner=_feather->scanner; if(my_scanner==NULL) { return 0; } assert(thread_num<_feather->scan_thread_num); region_result=my_scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*thread_num; INC_SCANNER_REF(my_scanner, thread_num); if(p_table->expr_rule_cnt>0) { scan_data.rule_type=RULETYPE_STR; scan_data.sub_type=sub_type; region_ret=rulescan_search(my_scanner->region, thread_num, &scan_data, region_result, MAX_SCANNER_HIT_NUM); if(region_ret>0) { hit_region_cnt+=region_ret; } } if(p_table->regex_rule_cnt>0) { scan_data.rule_type=RULETYPE_REG; scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE,0); region_ret=rulescan_search(my_scanner->region, thread_num, &scan_data, region_result+hit_region_cnt, MAX_SCANNER_HIT_NUM-hit_region_cnt); if(region_ret>0) { hit_region_cnt+=region_ret; } } if(hit_region_cnt>0) { if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); *mid=_mid; } else { _mid=(struct _scan_status_t*)(*mid); } compile_ret=region_compile(_mid, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); if(hit_detail!=NULL) { *detail_ret=fill_region_hit_detail(data,_mid, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); } } DEC_SCANNER_REF(my_scanner, thread_num); if(compile_ret==0&&hit_region_cnt>0) { return -2; } return compile_ret; } int Maat_full_scan_string(Maat_feather_t feather,int table_id ,enum MAAT_CHARSET charset,const char* data,int data_len ,struct Maat_rule_t*result,int* found_pos,int rule_num ,scan_status_t* mid,int thread_num) { int detail_ret=0,compile_ret=0; compile_ret=Maat_full_scan_string_detail(feather,table_id, charset, data,data_len, result, rule_num, NULL, 0, &detail_ret,mid,thread_num); return compile_ret; } int Maat_scan_intval(Maat_feather_t feather,int table_id ,unsigned int intval ,struct Maat_rule_t*result,int rule_num ,scan_status_t *mid,int thread_num) { int region_ret=0,compile_ret=0; struct _scan_status_t* _mid=NULL; scan_data_t intval_scan_data; scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num]; struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* my_scanner=NULL; intval_scan_data.rule_type=RULETYPE_INT; intval_scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE, 0); intval_scan_data.int_data=intval; _Maat_table_info_t* p_table=NULL; p_table=acqurie_table(_feather,table_id,TABLE_TYPE_INTVAL); if(p_table==NULL) { return -1; } if(p_table->cfg_num==0) { return 0; } my_scanner=_feather->scanner; if(my_scanner==NULL) { return 0; } region_result=my_scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*thread_num; INC_SCANNER_REF(my_scanner,thread_num); region_ret=rulescan_search(my_scanner->region, thread_num, &intval_scan_data, region_result, MAX_SCANNER_HIT_NUM); if(region_ret<0) { DEC_SCANNER_REF(my_scanner, thread_num); return -1; } else if(region_ret>0) { if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); *mid=_mid; } else { _mid=(struct _scan_status_t*)(*mid); } compile_ret=region_compile(_mid, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, result,compile_result,rule_num); } DEC_SCANNER_REF(my_scanner,thread_num); if(compile_ret==0&®ion_ret>0) { return -2; } return compile_ret; } int Maat_scan_proto_addr(Maat_feather_t feather,int table_id ,struct ipaddr* addr,unsigned short int proto ,struct Maat_rule_t*result,int rule_num ,scan_status_t *mid,int thread_num) { int region_ret=0,compile_ret=0; struct _scan_status_t* _mid=NULL; scan_data_t ip_scan_data; scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num]; _Maat_table_info_t* p_table=NULL; struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* my_scanner=NULL; p_table=acqurie_table(_feather, table_id, TABLE_TYPE_IP); if(p_table==NULL) { return -1; } if(p_table->cfg_num==0) { return 0; } my_scanner=_feather->scanner; if(my_scanner==NULL) { return 0; } ip_scan_data.rule_type=RULETYPE_IPv4; ip_scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE, 0); switch(addr->addrtype) { case ADDR_TYPE_IPV4: ip_scan_data.ipv4_data.saddr=ntohl(addr->paddr.v4->saddr); ip_scan_data.ipv4_data.daddr=ntohl(addr->paddr.v4->daddr); ip_scan_data.ipv4_data.sport=ntohs(addr->paddr.v4->source); ip_scan_data.ipv4_data.dport=ntohs(addr->paddr.v4->dest); ip_scan_data.ipv4_data.proto=proto; break; case ADDR_TYPE_IPV6: ip_scan_data.rule_type=RULETYPE_IPv6; memcpy(ip_scan_data.ipv6_data.saddr,addr->paddr.v6->saddr,sizeof(ip_scan_data.ipv6_data.saddr)); ipv6_ntoh(ip_scan_data.ipv6_data.saddr); memcpy(ip_scan_data.ipv6_data.daddr,addr->paddr.v6->daddr,sizeof(ip_scan_data.ipv6_data.daddr)); ipv6_ntoh(ip_scan_data.ipv6_data.daddr); ip_scan_data.ipv6_data.sport=ntohs(addr->paddr.v6->source); ip_scan_data.ipv6_data.dport=ntohs(addr->paddr.v6->dest); ip_scan_data.ipv6_data.proto=proto; break; default: return -1; break; } region_result=my_scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*thread_num; INC_SCANNER_REF(my_scanner,thread_num); region_ret=rulescan_search(my_scanner->region, thread_num, &ip_scan_data, region_result, MAX_SCANNER_HIT_NUM); if(region_ret<0) { DEC_SCANNER_REF(my_scanner,thread_num); return -1; } else if(region_ret>0) { if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); *mid=_mid; } else { _mid=(struct _scan_status_t*)(*mid); } compile_ret=region_compile(_mid, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, result,compile_result,rule_num); } DEC_SCANNER_REF(my_scanner,thread_num); if(compile_ret==0&®ion_ret>0) { return -2; } return compile_ret; } int Maat_scan_addr(Maat_feather_t feather,int table_id ,struct ipaddr* addr ,struct Maat_rule_t*result,int rule_num ,scan_status_t *mid,int thread_num) { int compile_ret=0; compile_ret=Maat_scan_proto_addr(feather,table_id, addr, 0, result, rule_num, mid,thread_num); return compile_ret; } stream_para_t Maat_stream_scan_string_start(Maat_feather_t feather,int table_id,int thread_num) { struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* scanner=NULL; struct _Maat_table_info_t *p_table=NULL; assert(thread_num<_feather->scan_thread_num); p_table=acqurie_table(_feather, table_id, TABLE_TYPE_EXPR); if(p_table==NULL) { return NULL; } struct _stream_para_t* sp=(struct _stream_para_t*)calloc(sizeof(struct _stream_para_t),1); scanner=_feather->scanner; sp->feather=_feather; sp->version=_feather->maat_version; sp->acc_scan_len=0; if(scanner==NULL) { return sp; } INC_SCANNER_REF(scanner, thread_num); sp->table_id=table_id; sp->thread_num=thread_num; sp->max_cross_size=p_table->cross_cache_size; sp->caching_size=0; sp->scan_buff=NULL; sp->last_cache=NULL; if(p_table->do_charset_merge==1) { sp->do_merge=1; } if(p_table->expr_rule_cnt>0) { sp->do_expr=1; } if(p_table->regex_rule_cnt>0) { sp->do_regex=1; } sp->rs_stream_para=rulescan_startstream(_feather->scanner->region,thread_num); return sp; } int Maat_stream_scan_string_detail(stream_para_t* stream_para ,enum MAAT_CHARSET charset,const char* data,int data_len ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num ,int* detail_ret,scan_status_t* mid) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; int sub_type=0; int region_ret=0,hit_region_cnt=0,compile_ret=0; struct _scan_status_t* _mid=(struct _scan_status_t*)(*mid); scan_result_t *region_result; _compile_result_t compile_result[rule_num];//dynamic array scan_data_t region_scan_data; if(data==NULL||data_len==0) { return 0; } if(scanner==NULL) { return 0; } if(sp->version!=sp->feather->maat_version) { return 0; } if(sp->feather->p_table_info[sp->table_id]->cfg_num==0) { return 0; } region_result=scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*sp->thread_num; *detail_ret=0; if(sp->do_merge==1) { sub_type=make_sub_type(sp->table_id,CHARSET_NONE,0); } else { sub_type=make_sub_type(sp->table_id,charset,0); } if(sp->max_cross_size>0&&sp->caching_size>0) { if(sp->scan_buff!=NULL) { free(sp->scan_buff); sp->scan_buff=NULL; } sp->scan_buff=(char*)malloc(sp->caching_size+data_len); memcpy(sp->scan_buff,sp->last_cache,sp->caching_size); memcpy(sp->scan_buff+sp->caching_size,data,data_len); region_scan_data.text_data.text=sp->scan_buff; region_scan_data.text_data.tlen=sp->caching_size+data_len; } else { region_scan_data.text_data.text=data; region_scan_data.text_data.tlen=data_len; } if(sp->last_cache==NULL&&sp->max_cross_size>0) { assert(sp->caching_size==0); sp->last_cache=(char*)malloc(sizeof(char)*sp->max_cross_size); } if(sp->max_cross_size>0) { sp->caching_size=detain_last_data(sp->last_cache,sp->max_cross_size,sp->caching_size,data,data_len); } region_scan_data.text_data.toffset=(int)MIN(0xffffffff/2, sp->acc_scan_len);//longger then int sp->acc_scan_len+=data_len; if(sp->do_expr==1) { region_scan_data.rule_type=RULETYPE_STR; region_scan_data.sub_type=sub_type; region_ret=rulescan_searchstream(sp->rs_stream_para, ®ion_scan_data, region_result, MAX_SCANNER_HIT_NUM); if(region_ret<0) { return -1; } else if(region_ret>0) { hit_region_cnt+=region_ret; } } if(sp->do_regex==1) { region_scan_data.rule_type=RULETYPE_REG; region_scan_data.sub_type=make_sub_type(sp->table_id,CHARSET_NONE,0); region_ret=rulescan_searchstream(sp->rs_stream_para, ®ion_scan_data, region_result+hit_region_cnt, MAX_SCANNER_HIT_NUM-hit_region_cnt); if(region_ret<0) { return -1; } else if(region_ret>0) { hit_region_cnt+=region_ret; } } if(hit_region_cnt>0) { if(*mid==NULL) { _mid=_Maat_make_status(sp->feather,sp->thread_num); *mid=_mid; } else { _mid=(struct _scan_status_t*)(*mid); } compile_ret=region_compile(_mid, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); if(hit_detail!=NULL) { if(sp->scan_buff!=NULL) { *detail_ret=fill_region_hit_detail(sp->scan_buff,_mid, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); } else { *detail_ret=fill_region_hit_detail(data,_mid, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); } } } if(*detail_ret==0) { free(sp->scan_buff); sp->scan_buff=0; } if(compile_ret==0&&hit_region_cnt>0) { return -2; } return compile_ret; } int Maat_stream_scan_string(stream_para_t* stream_para ,enum MAAT_CHARSET charset,const char* data,int data_len ,struct Maat_rule_t*result,int* found_pos,int rule_num ,scan_status_t* mid) { int compile_ret=0; int detail_ret=0; compile_ret=Maat_stream_scan_string_detail(stream_para, charset,data,data_len, result,rule_num, NULL, 0,&detail_ret,mid); return compile_ret; } void Maat_stream_scan_string_end(stream_para_t* stream_para) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) { DEC_SCANNER_REF(scanner, sp->thread_num); } rulescan_endstream(sp->rs_stream_para); } if(sp->last_cache!=NULL) { free(sp->last_cache); sp->last_cache=NULL; sp->caching_size=0; } if(sp->scan_buff!=NULL) { free(sp->scan_buff); sp->scan_buff=NULL; } free(sp); *stream_para=NULL; return; } stream_para_t Maat_stream_scan_digest_start(Maat_feather_t feather,int table_id,unsigned long long total_len,int thread_num) { struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* scanner=NULL; struct _Maat_table_info_t *p_table=NULL; p_table=acqurie_table(_feather, table_id, TABLE_TYPE_DIGEST); if(p_table==NULL) { return NULL; } struct _stream_para_t* sp=(struct _stream_para_t*)calloc(sizeof(struct _stream_para_t),1); scanner=_feather->scanner; sp->feather=_feather; sp->version=_feather->maat_version; sp->acc_scan_len=0; if(scanner==NULL) { return sp; } INC_SCANNER_REF(scanner, thread_num); sp->table_id=table_id; sp->thread_num=thread_num; sp->total_len=total_len; sp->fuzzy_hash_handle=fuzzy_create_handle(total_len); return sp; } inline int REACH_QUERY_THRESH(unsigned long long total_len,unsigned long long acc_len,unsigned char* query_point,int point_size) { const unsigned long long QUERY_MIN_RATE=(3); //30% // const unsigned long long QUERY_MIN_LEN=(1024*1024*4); //do query every 10 percent since 30%, e.g. 0.3/0.4/0.5/.../1.0 unsigned long long rate=(acc_len*10)/total_len; // if(acc_len>QUERY_MIN_LEN) // { // return 1; // } assert(rate<(unsigned long long)(point_size+QUERY_MIN_RATE)); if(rate>=QUERY_MIN_RATE&&query_point[rate-QUERY_MIN_RATE]==0) { query_point[rate-QUERY_MIN_RATE]=1; return 1; } return 0; } int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int data_len, unsigned long long offset, struct Maat_rule_t * result, int rule_num, scan_status_t * mid) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); int do_query=0; GIE_result_t query_result[MAX_SCANNER_HIT_NUM]; int hit_region_cnt=0,compile_ret=0; _compile_result_t compile_result[rule_num];//dynamic array GIE_handle_t* GIE_handle=sp->feather->scanner->digest_handle[sp->table_id]; unsigned long long digest_len=0; char* digest_buff=NULL; struct _scan_status_t* _mid=(struct _scan_status_t*)(*mid); pthread_rwlock_t *GIE_rwlock=&(sp->feather->scanner->digest_rwlock[sp->table_id]); sp->acc_scan_len+=fuzzy_feed(sp->fuzzy_hash_handle, data, (unsigned int)data_len,offset); do_query=REACH_QUERY_THRESH(sp->total_len, sp->acc_scan_len, sp->query_point,8); if(do_query==0) { return 0; } digest_len=fuzzy_status(sp->fuzzy_hash_handle, HASH_LENGTH); if(digest_len==0) { return 0; } digest_buff=(char*)malloc(sizeof(char)*digest_len); fuzzy_digest(sp->fuzzy_hash_handle,digest_buff, digest_len); if(0==pthread_rwlock_tryrdlock(GIE_rwlock)) { hit_region_cnt=GIE_query(GIE_handle, sp->total_len, digest_buff, query_result, MAX_SCANNER_HIT_NUM); pthread_rwlock_unlock(GIE_rwlock); } free(digest_buff); digest_buff=NULL; if(hit_region_cnt<0)//error occurs { return -1; } if(hit_region_cnt==0) { return 0; } if(*mid==NULL) { _mid=_Maat_make_status(sp->feather,sp->thread_num); *mid=_mid; } else { _mid=(struct _scan_status_t*)(*mid); } compile_ret=region_compile(_mid, query_result,sizeof(GIE_result_t),offsetof(GIE_result_t, tag), hit_region_cnt, result,compile_result,rule_num); if(compile_ret==0&&hit_region_cnt>0) { return -2; } return compile_ret; } void Maat_stream_scan_digest_end(stream_para_t* stream_para) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) { DEC_SCANNER_REF(scanner, sp->thread_num); } } fuzzy_destroy_handle(sp->fuzzy_hash_handle); assert(sp->last_cache==NULL); assert(sp->scan_buff==NULL); free(sp); *stream_para=NULL; return; } void Maat_clean_status(scan_status_t* mid) { struct _scan_status_t* _mid=NULL; if(*mid==NULL) { return; } _mid=(struct _scan_status_t*)(*mid); free(_mid->hitted_group_id); free(_mid); *mid=NULL; return; }