#include #include #include #include #include #include #include #include "kni_replace.h" #include "kni_entry.h" int g_kni_version_VERSION_20181113_hithalf; struct kni_var_comm g_kni_comminfo; struct kni_var_struct g_kni_structinfo; struct kni_var_maat g_kni_maatinfo; struct kni_fs2_info g_kni_fs2_info; struct kni_switch_info g_kni_switch_info; char g_kni_cardname[KNI_CARD_NUM][KNI_CONF_MAXLEN]; int g_kni_threadseq[KNI_MAX_THREADNUM]; int kni_init_pmeinfo(void** pme) { struct kni_pme_info* pmeinfo=(struct kni_pme_info*)malloc(sizeof(struct kni_pme_info)); memset(pmeinfo,0,sizeof(struct kni_pme_info)); *pme=pmeinfo; return 0; } int kni_free_pmeinfo(void** pme) { struct kni_pme_info* pmeinfo=(struct kni_pme_info*)*pme; Maat_clean_status(&(pmeinfo->mid)); free(pmeinfo); pmeinfo=NULL; return 0; } /*************************************************************************************** return :state_flag kni_bmd:STAT_FLAG_SNIBMD not kni_bmd:STAT_FLAG_SSL_NOBMD ***************************************************************************************/ int kni_scan_domain(char* domain,int domain_len,int thread_seq,struct kni_pme_info* pmeinfo) { int string_scan_num=0; int found_pos; struct Maat_rule_t maat_result[KNI_MAX_SAMENUM]; string_scan_num=Maat_full_scan_string(g_kni_maatinfo.maat_feather,g_kni_maatinfo.tableid_domain,CHARSET_GBK,domain,domain_len,maat_result,&found_pos,KNI_MAX_SAMENUM,&(pmeinfo->mid),thread_seq); kni_process_maatresult(string_scan_num,maat_result,pmeinfo); if(string_scan_num <= 0) { string_scan_num=Maat_full_scan_string(g_kni_maatinfo.ipd_dyn_maat_feather,g_kni_maatinfo.tableid_dynamic_domain,CHARSET_GBK,domain,domain_len,maat_result,&found_pos,KNI_MAX_SAMENUM,&(pmeinfo->mid),thread_seq); kni_process_maatresult(string_scan_num,maat_result,pmeinfo); } return string_scan_num; } /*************************************************************************************** return :state_flag kni_bmd:STAT_FLAG_SNIBMD not kni_bmd:STAT_FLAG_SSL_NOBMD ***************************************************************************************/ int kni_scan_pktbin(char* data,int datalen,int thread_seq,struct kni_pme_info* pmeinfo) { int string_scan_num=0; int found_pos; struct Maat_rule_t maat_result[KNI_MAX_SAMENUM]; string_scan_num=Maat_full_scan_string(g_kni_maatinfo.maat_feather,g_kni_maatinfo.tableid_pktbin,CHARSET_GBK,data,datalen,maat_result,&found_pos,KNI_MAX_SAMENUM,&(pmeinfo->mid),thread_seq); kni_process_maatresult(string_scan_num,maat_result,pmeinfo); return string_scan_num; } /*************************************************************************************** return :action default:ipscan_num =0 or =1,not >1 ***************************************************************************************/ int kni_scan_ip(struct ipaddr* addr,int thread_seq,int protocol,struct kni_pme_info* pmeinfo) { int ipscan_num = 0; struct Maat_rule_t maat_result[KNI_MAX_SAMENUM]; ipscan_num = Maat_scan_proto_addr(g_kni_maatinfo.maat_feather,g_kni_maatinfo.tableid_ip,addr,protocol,maat_result,KNI_MAX_SAMENUM,&(pmeinfo->mid),thread_seq); kni_process_maatresult(ipscan_num,maat_result,pmeinfo); //20181030add ,ipscan_action is monitor,use this keyringid;ipscan_action is replace,udp data not ipscan and pktscan pmeinfo->ipsscan_action = pmeinfo->action; //end return ipscan_num; } int kni_htable_add(const struct streaminfo* pstream,const void* a_packet,struct kni_pme_info* pmeinfo) { int iprevers=0; struct stream_tuple4_v4 ipv4_addr; struct stream_tuple4_v6 ipv6_addr; struct layer_addr_mac* mac_addr=(struct layer_addr_mac*)((char*)a_packet-KNI_ETHER_LEN); struct kni_htable_datainfo* datainfo=(struct kni_htable_datainfo*)malloc(sizeof(struct kni_htable_datainfo)); memset(datainfo,0,sizeof(struct kni_htable_datainfo)); //send pkt info if(iprevers==0) { datainfo->route_dir=pstream->routedir; memcpy(datainfo->smac,mac_addr->src_mac,MAC_ADDR_LEN); memcpy(datainfo->dmac,mac_addr->dst_mac,MAC_ADDR_LEN); } else { if(g_kni_switch_info.sendpkt_mode == 1) { datainfo->route_dir=1-pstream->routedir; } else { datainfo->route_dir=MESA_dir_reverse(pstream->routedir); } memcpy(datainfo->smac,mac_addr->dst_mac,MAC_ADDR_LEN); memcpy(datainfo->dmac,mac_addr->src_mac,MAC_ADDR_LEN); } //send wnd_pro_reply info memcpy(&(datainfo->tcpopt_info),&(pmeinfo->tcpopt_info),KNI_DIR_DOUBLE*sizeof(struct kni_tcpopt_info)); memcpy(&(datainfo->lastpkt_info),&(pmeinfo->lastpkt_info),KNI_DIR_DOUBLE*sizeof(struct kni_wndpro_reply_info)); if(pstream->addr.addrtype == ADDR_TYPE_IPV4) { iprevers=kni_get_ipaddr_v4((void*)a_packet,&ipv4_addr); MESA_htable_add(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),(void*)datainfo); } else { iprevers=kni_get_ipaddr_v6((void*)a_packet,&ipv6_addr); MESA_htable_add(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),(void*)datainfo); } return 0; } /*************************************************************************************** return :state_flag ssl:STAT_FLAG_SSL_NOBMD not ssl:STAT_FLAG_NOTSSL ***************************************************************************************/ int kni_judge_ssl(int thread_seq,char* tcp_data,int tcp_datalen,char* sni,int* sni_len,int* clienthello_flag,int* sni_flag) { int ssl_header_len=0; char* ssl_header=NULL; unsigned char content_type=0; unsigned short version_in_header=0; unsigned short len_in_header=0; int ssl_body_len=0; char* ssl_body=NULL; unsigned char handshark_type=0; unsigned int len_in_body=0; unsigned short version_in_body=0; unsigned char session_id_len=0; unsigned short ciphersuite_len=0; unsigned char compression_method_len=0; int ssl_extention_len=0; char* ssl_extention=NULL; unsigned short extension_len_less=0; unsigned short type_in_extension=0; unsigned short len_in_extension=0; //ssl header ssl_header=tcp_data; content_type=*(unsigned char*)&ssl_header[ssl_header_len]; if(content_type!=SSL_CONTENTTYPE_HANDSHAKE) { return KNI_FLAG_UNKNOW; } ssl_header_len+=1; version_in_header=ntohs(*(unsigned short*)&(ssl_header[ssl_header_len])); if((version_in_header!=SSL_VERSION_TLS1_0)&&(version_in_header!=SSL_VERSION_TLS1_1)&&(version_in_header!=SSL_VERSION_TLS1_2)) { return KNI_FLAG_UNKNOW; } ssl_header_len+=2; len_in_header=ntohs(*(unsigned short*)&(ssl_header[ssl_header_len])); if(len_in_header!=tcp_datalen-SSL_HEADER_LEN) { return KNI_FLAG_UNKNOW; } ssl_header_len+=2; //ssl body ssl_body=ssl_header+ssl_header_len; handshark_type=*(unsigned char*)&(ssl_body[ssl_body_len]); if(handshark_type!=SSL_HANDSHAR_TYPE_CLIENTHELLO) { return KNI_FLAG_UNKNOW; } ssl_body_len+=1; *clienthello_flag = 1; kni_filestate2_set(thread_seq,FS2_COLUME_CLIENTHELLO,0,1); // memcpy(&len_in_body,&ssl_body[ssl_body_len],3); len_in_body=*(unsigned char*)&ssl_body[ssl_body_len+2]+256*(*(unsigned char*)&ssl_body[ssl_body_len+1])+65536*(*(unsigned char*)&ssl_body[ssl_body_len]); if(len_in_body!=(len_in_header-SSL_BODY_LEN)) { return KNI_FLAG_UNKNOW; } ssl_body_len+=3; version_in_body=ntohs(*(unsigned short*)&(ssl_body[ssl_body_len])); if((version_in_body!=SSL_VERSION_TLS1_0)&&(version_in_body!=SSL_VERSION_TLS1_1)&&(version_in_body!=SSL_VERSION_TLS1_2)) { return KNI_FLAG_UNKNOW; } ssl_body_len+=2; ssl_body_len+=32; //4byte time,28bytes random session_id_len=*(unsigned char*)&(ssl_body[ssl_body_len]); ssl_body_len+=1; ssl_body_len+=session_id_len; ciphersuite_len=ntohs(*(unsigned short*)&(ssl_body[ssl_body_len])); ssl_body_len+=2; ssl_body_len+=ciphersuite_len; compression_method_len=*(unsigned char*)&(ssl_body[ssl_body_len]); ssl_body_len+=1; ssl_body_len+=compression_method_len; //ssl extention ssl_extention=ssl_body+ssl_body_len; extension_len_less=ntohs(*(unsigned short*)&ssl_extention[ssl_extention_len]); if(extension_len_less!=len_in_body-2-32-1-session_id_len-2-ciphersuite_len-1-compression_method_len-2) { return KNI_FLAG_UNKNOW; } ssl_extention_len+=2; while(ssl_extention_lenKNI_SNI_MAXLEN) { //error return KNI_FLAG_UNKNOW; } if(len_in_extension>KNI_DEFAULT_MTU) { len_in_extension=KNI_DEFAULT_MTU; } memcpy(sni,&ssl_extention[ssl_extention_len],len_in_extension); *sni_len=len_in_extension; return KNI_FLAG_SSL; } else { ssl_extention_len+=len_in_extension; continue; } } return KNI_FLAG_UNKNOW; } int kni_judge_http(const struct streaminfo *stream,char* domain,int* domain_len) { int val=1; struct kni_http_project* host=(struct kni_http_project*)project_req_get_struct(stream,g_kni_comminfo.project_id); if(host==NULL) { *domain_len=0; return -1; } *domain_len=host->host_len>KNI_DEFAULT_MTU?KNI_DEFAULT_MTU:host->host_len; memcpy(domain,host->host,*domain_len); return val; } int kni_protocol_identify(const struct streaminfo* pstream,const void* a_packet,char* tcp_data,int tcp_datalen,char* domain,int* domain_len) { int clienthello_flag = 0; int sni_flag = 0; if(kni_judge_http(pstream,domain,domain_len)==1) { kni_filestate2_set(pstream->threadnum,FS2_COLUME_HTTP,0,1); return KNI_FLAG_HTTP; } else if(kni_judge_ssl(pstream->threadnum,tcp_data,tcp_datalen,domain,domain_len,&clienthello_flag,&sni_flag)==KNI_FLAG_SSL) { kni_filestate2_set(pstream->threadnum,FS2_COLUME_SSL,0,1); return KNI_FLAG_SSL; } //modify by liuyang 20180911 for client_hello but no sni else if((clienthello_flag == 1)&&(sni_flag == 0)) { kni_log_debug(RLOG_LV_FATAL,(char*)"SSL_IDENTIFY",(void*)a_packet,(char*)"this ssl has client_hello,but no sni!"); return KNI_FLAG_SSL; } return KNI_FLAG_NOTPROC; } char kni_process_udppkt(unsigned char routdir,struct kni_pme_info* pmeinfo,int thread_seq,const void* a_packet) { char ret = APP_STATE_FAWPKT|APP_STATE_DROPME; switch(pmeinfo->action) { case KNI_ACTION_RATELIMIT: ret = kni_process_ratelimit(thread_seq,a_packet,pmeinfo); break; case KNI_ACTION_REPLACE: ret = kni_process_replace(routdir,thread_seq,a_packet,pmeinfo); break; case KNI_ACTION_HALFHIT: ret = APP_STATE_GIVEME | APP_STATE_FAWPKT; default: break; } return ret; } char kni_first_tcpdata(const struct streaminfo* pstream,const void* a_packet,struct kni_pme_info* pmeinfo,char* data,int datalen) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; int domain_len=0; char domain[KNI_DEFAULT_MTU]={0}; pmeinfo->protocol=kni_protocol_identify(pstream,a_packet,data,datalen,domain,&domain_len); if((pmeinfo->protocol==KNI_FLAG_HTTP) ||(pmeinfo->protocol==KNI_FLAG_SSL)) { if(domain_len != 0) { kni_scan_domain(domain,domain_len,pstream->threadnum,pmeinfo); } switch(pmeinfo->action) { case KNI_ACTION_WHITELIST: kni_filestate2_set(pstream->threadnum,FS2_COLUME_WITELIST_DOMAIN,0,1); kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),pmeinfo->protocol,domain,(char*)"WHITE_LIST_DOMAIN",(char*)"BYPASS",pmeinfo); pmeinfo->protocol=KNI_FLAG_NOTPROC; return ret; case KNI_ACTION_RATELIMIT: kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),pstream->type,NULL,(char*)"RATELIMITE",(char*)"RATELIMITE",pmeinfo); ret = kni_process_ratelimit(pstream->threadnum,a_packet,pmeinfo); return ret; case KNI_ACTION_NONE: case KNI_ACTION_HALFHIT: if(g_kni_switch_info.maat_default_mode==KNI_DEFAULT_MODE_BYPASS) { kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),pmeinfo->protocol,domain,(char*)"NOT_HIT",(char*)"BYPASS",pmeinfo); pmeinfo->protocol=KNI_FLAG_NOTPROC; pmeinfo->action = KNI_ACTION_NONE; return ret; } else { pmeinfo->action = KNI_ACTION_MONITOR; break; } } // kni_get_keyring(pmeinfo); if(tcp_repair_process(pstream,a_packet,pmeinfo,pmeinfo->protocol)<0) { MESA_handle_runtime_log(g_kni_comminfo.logger,RLOG_LV_INFO,"tcp_repair_process","tcp_repair_process() error!"); return ret; } kni_htable_add(pstream,a_packet,pmeinfo); kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),pmeinfo->protocol,domain,(char*)"INTERCEPT",(char*)"INTERCEPT",pmeinfo); ret=APP_STATE_DROPPKT|APP_STATE_GIVEME; } else { kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),pmeinfo->protocol,NULL,(char*)"NOT_HTTP_SSL",(char*)"BYPASS",pmeinfo); } return ret; } char kni_pending_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const void* a_packet,int protocol) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; char* data=NULL; int datalen=0; int iplen=0; int tcphdr_len = 0; struct ip* ipv4_hdr = NULL; struct kni_ipv6_hdr* ipv6_hdr = NULL; struct kni_tcp_hdr* tcphdr=NULL; data=kni_get_data(pstream,&datalen); if(pstream->addr.addrtype==ADDR_TYPE_IPV4) { ipv4_hdr = (struct ip*)a_packet; iplen=ntohs(ipv4_hdr->ip_len); tcphdr_len = iplen-4*(ipv4_hdr->ip_hl)-datalen; tcphdr=(struct kni_tcp_hdr*)((char*)ipv4_hdr+4*(ipv4_hdr->ip_hl)); } else if(pstream->addr.addrtype==ADDR_TYPE_IPV6) { ipv6_hdr = (struct kni_ipv6_hdr*)a_packet; iplen = ntohs(ipv6_hdr->ip6_payload_len) + sizeof(struct kni_ipv6_hdr); tcphdr_len = ntohs(ipv6_hdr->ip6_payload_len) -datalen; tcphdr =(struct kni_tcp_hdr*)( (unsigned char*)a_packet + sizeof(struct kni_ipv6_hdr)); } else { return ret; } kni_scan_ip((struct ipaddr*)&(pstream->addr),thread_seq,protocol,pmeinfo); if(pmeinfo->action==KNI_ACTION_WHITELIST) { kni_log_info((char*)KNI_MODULE_INFO,&(pstream->addr),0,NULL,(char*)"WHITE_LIST_IP",(char*)"BYPASS",pmeinfo); kni_filestate2_set(thread_seq,FS2_COLUME_WITELIST_IP,0,1); return ret; } pmeinfo->protocol=KNI_FLAG_UNKNOW; if(protocol == PROTO_TYPE_TCP) { kni_get_tcpopt(tcphdr,tcphdr_len,&(pmeinfo->tcpopt_info[pstream->curdir-1].mss),&(pmeinfo->tcpopt_info[pstream->curdir-1].wnscal),&(pmeinfo->tcpopt_info[pstream->curdir-1].sack),&(pmeinfo->tcpopt_info[pstream->curdir-1].timestamps)); kni_get_tcpinfo(&(pmeinfo->lastpkt_info[pstream->curdir-1]),tcphdr,datalen); #ifndef KNI_DEBUG_TCPREPAIR if(datalen>0) #endif { ret=kni_first_tcpdata(pstream,a_packet,pmeinfo,data,datalen); if((pmeinfo->protocol==KNI_FLAG_HTTP) ||(pmeinfo->protocol==KNI_FLAG_SSL)) { ret=tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)ipv4_hdr,iplen,(struct streaminfo*)pstream,thread_seq); } } #ifndef KNI_DEBUG_TCPREPAIR else { ret=APP_STATE_FAWPKT|APP_STATE_GIVEME; } #endif } else { kni_scan_pktbin((char*)(pstream->pudpdetail->pdata),pstream->pudpdetail->datalen,thread_seq,pmeinfo); ret = kni_process_udppkt(pstream->routedir,pmeinfo,thread_seq,a_packet); } return ret; } char kni_data_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const void* a_packet,int protocol) { char ret=APP_STATE_DROPPKT|APP_STATE_GIVEME; char* data=NULL; int datalen=0; int iplen=0; int tcphdr_len = 0; struct ip* ipv4_hdr = NULL; struct kni_ipv6_hdr* ipv6_hdr = NULL; struct kni_tcp_hdr* tcphdr=NULL; data=kni_get_data(pstream,&datalen); if(pstream->addr.addrtype==ADDR_TYPE_IPV4) { ipv4_hdr = (struct ip*)a_packet; iplen=ntohs(ipv4_hdr->ip_len); tcphdr_len = iplen-4*(ipv4_hdr->ip_hl)-datalen; tcphdr=(struct kni_tcp_hdr*)((char*)ipv4_hdr+4*(ipv4_hdr->ip_hl)); } else if(pstream->addr.addrtype==ADDR_TYPE_IPV6) { ipv6_hdr = (struct kni_ipv6_hdr*)a_packet; iplen = ntohs(ipv6_hdr->ip6_payload_len) + sizeof(struct kni_ipv6_hdr); tcphdr_len = ntohs(ipv6_hdr->ip6_payload_len) -datalen; tcphdr = (struct kni_tcp_hdr*)((unsigned char*)a_packet + sizeof(struct kni_ipv6_hdr)); } else { return ret; } if(protocol== PROTO_TYPE_TCP) { if(pmeinfo->protocol==KNI_FLAG_UNKNOW) { if((tcphdr->th_flags&TH_SYN)&&(tcphdr->th_flags&TH_ACK)) { kni_get_tcpopt(tcphdr,tcphdr_len,&(pmeinfo->tcpopt_info[pstream->curdir-1].mss),&(pmeinfo->tcpopt_info[pstream->curdir-1].wnscal),&(pmeinfo->tcpopt_info[pstream->curdir-1].sack),&(pmeinfo->tcpopt_info[pstream->curdir-1].timestamps)); } kni_get_tcpinfo(&(pmeinfo->lastpkt_info[pstream->curdir-1]),tcphdr,datalen); if(datalen>0) { ret=kni_first_tcpdata(pstream,a_packet,pmeinfo,data,datalen); } else { ret=APP_STATE_FAWPKT|APP_STATE_GIVEME; } } if((pmeinfo->action == KNI_ACTION_MONITOR) && ((pmeinfo->protocol==KNI_FLAG_HTTP)||(pmeinfo->protocol==KNI_FLAG_SSL))) { ret=tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)a_packet,iplen,(struct streaminfo*)pstream,thread_seq); } else if(pmeinfo->action == KNI_ACTION_RATELIMIT) { ret = kni_process_ratelimit(pstream->threadnum,(void*)a_packet,pmeinfo); return ret; } } else { if(pmeinfo->ipsscan_action == KNI_ACTION_NONE) { kni_scan_ip((struct ipaddr*)&(pstream->addr),thread_seq,protocol,pmeinfo); } else if((pmeinfo->ipsscan_action != KNI_ACTION_REPLACE) && (pmeinfo->ipsscan_action != KNI_ACTION_RATELIMIT)) { kni_scan_pktbin((char*)(pstream->pudpdetail->pdata),pstream->pudpdetail->datalen,thread_seq,pmeinfo); } ret = kni_process_udppkt(pstream->routedir,pmeinfo,thread_seq,a_packet); } return ret; } char kni_close_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const void* a_packet,int protocol) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; if(a_packet==NULL) { return ret; } ret=kni_data_opstate(pstream,pmeinfo,thread_seq,a_packet,protocol); return ret|APP_STATE_DROPME; } extern "C" char kni_udp_entry(const struct streaminfo* pstream,void** pme,int thread_seq,const void* a_packet) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; struct kni_ipv6_hdr* ipv6_hdr = NULL; if((g_kni_switch_info.replace_switch == 0) && (g_kni_switch_info.ratelimit_switch == 0)) { return APP_STATE_FAWPKT|APP_STATE_DROPME; } if(pstream->addr.addrtype==ADDR_TYPE_IPV6) { ipv6_hdr = (struct kni_ipv6_hdr*)a_packet; if(ipv6_hdr->ip6_nex_hdr != NEXTHDR_UDP) { return ret; } } kni_filestate2_set(thread_seq,FS2_COLUME_RECV,0,1); switch(pstream->opstate) { case OP_STATE_PENDING: kni_init_pmeinfo(pme); ret=kni_pending_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_UDP); break; case OP_STATE_DATA: ret=kni_data_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_UDP); break; case OP_STATE_CLOSE: ret=kni_close_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_UDP); break; default: break; } if((ret&APP_STATE_DROPME)&&(*pme!=NULL)) { kni_free_pmeinfo(pme); *pme=NULL; } return ret; } extern "C" char kni_tcpall_entry(const struct streaminfo* pstream,void** pme,int thread_seq,const void* a_packet) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; struct kni_ipv6_hdr* ipv6_hdr = NULL; if(g_kni_comminfo.kni_mode_cur==KNI_MODE_BYPASS) { return ret; } if(pstream->addr.addrtype==ADDR_TYPE_IPV6) { ipv6_hdr = (struct kni_ipv6_hdr*)a_packet; if((a_packet != NULL) && (ipv6_hdr->ip6_nex_hdr != NEXTHDR_TCP)) { kni_filestate2_set(thread_seq,FS2_COLUME_DROP_SAPP,0,1); return ret; } } kni_filestate2_set(thread_seq,FS2_COLUME_RECV,0,1); switch(pstream->pktstate) { case OP_STATE_PENDING: kni_init_pmeinfo(pme); ret=kni_pending_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_TCP); break; case OP_STATE_DATA: ret=kni_data_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_TCP); break; case OP_STATE_CLOSE: ret=kni_close_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,a_packet,PROTO_TYPE_TCP); break; default: break; } if((ret&APP_STATE_DROPME)&&(*pme!=NULL)) { kni_free_pmeinfo(pme); *pme=NULL; } return ret; } extern "C" char kni_http_entry(stSessionInfo* session_info, void **pme, int thread_seq,struct streaminfo *a_stream,const void *a_packet) { char ret=PROT_STATE_DROPME; int host_len=session_info->buflen>KNI_DEFAULT_MTU?KNI_DEFAULT_MTU:session_info->buflen; struct kni_http_project* host_info=(struct kni_http_project*)malloc(sizeof(struct kni_http_project)); host_info->host_len=host_len; memcpy(host_info->host,session_info->buf,host_len); project_req_add_struct(a_stream,g_kni_comminfo.project_id,host_info); return ret; } extern "C" char kni_ipv4_entry(const struct streaminfo *pstream,unsigned char routedir,int thread_seq, struct ip* ipv4_hdr) { if((ipv4_hdr->ip_p == IPPROTO_TCP) || (ipv4_hdr->ip_p == IPPROTO_UDP) || ((g_kni_switch_info.replace_switch == 0) && (g_kni_switch_info.ratelimit_switch == 0))) { return APP_STATE_DROPME; } char ret = APP_STATE_GIVEME; scan_status_t mid = NULL; struct kni_pme_info pmeinfo; /* int payload_len = ntohs(ipv4_hdr->ip_len) - 4*(ipv4_hdr->ip_hl); char* payload = (char*)ipv4_hdr + 4*(ipv4_hdr->ip_hl); */ struct ipaddr addr; struct tuple4 ipv4_addr; addr.addrtype = ADDR_TYPE_IPV4; addr.paddr = (void*)(&ipv4_addr); memset(&ipv4_addr,0,sizeof(struct tuple4)); ipv4_addr.daddr = *((unsigned int*)&(ipv4_hdr->ip_dst)); ipv4_addr.saddr = *((unsigned int*)&(ipv4_hdr->ip_src)); memset(&pmeinfo,0,sizeof(struct kni_pme_info)); pmeinfo.mid = mid; kni_scan_ip(&addr,thread_seq,ipv4_hdr->ip_p,&pmeinfo); // kni_scan_pktbin(payload,payload_len,thread_seq,&pmeinfo); Maat_clean_status(&(pmeinfo.mid)); ret = kni_process_udppkt(routedir,&pmeinfo,thread_seq,ipv4_hdr); return ret; } extern "C" char kni_ipv6_entry(const struct streaminfo *pstream,unsigned char routedir,int thread_seq, struct kni_ipv6_hdr* ipv6_hdr) { if((ipv6_hdr->ip6_flags[0] & 0xF0) != 0x60) { return -1; } char ret = APP_STATE_GIVEME; scan_status_t mid = NULL; struct kni_pme_info pmeinfo; struct ipaddr addr; struct tuple6 ipv6_addr; unsigned char next_hdr_type = ipv6_hdr->ip6_nex_hdr; if((next_hdr_type == PROTO_TYPE_TCP) || (next_hdr_type == PROTO_TYPE_UDP)) { return ret; } addr.addrtype = ADDR_TYPE_IPV6; addr.paddr = (void*)(&ipv6_addr); memset(&ipv6_addr,0,sizeof(struct tuple4)); memcpy(ipv6_addr.saddr,&(ipv6_hdr->ip6_src),sizeof(struct in6_addr)); memcpy(ipv6_addr.daddr,&(ipv6_hdr->ip6_dst),sizeof(struct in6_addr)); memset(&pmeinfo,0,sizeof(struct kni_pme_info)); pmeinfo.mid = mid; kni_scan_ip(&addr,thread_seq,next_hdr_type,&pmeinfo); Maat_clean_status(&(pmeinfo.mid)); ret = kni_process_udppkt(routedir,&pmeinfo,thread_seq,ipv6_hdr); return ret; } void kni_free_project(int thread_seq, void *project_req_value) { free(project_req_value); project_req_value=NULL; return ; } int kni_read_cardname() { int offset=0; char* token=NULL; char buf[KNI_CONF_MAXLEN]={0}; int routdir=0; FILE* fp=fopen("./conf/send_raw_pkt.conf","r"); if(fp==NULL) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"kni_read_cardname","fopen ./conf/send_raw_pkt.conf err,errno:%d,%s",errno,strerror(errno)); return -1; } while(feof(fp)==0) { routdir=0; memset(buf,0,KNI_CONF_MAXLEN); if((fgets(buf,KNI_CONF_MAXLEN,fp)==NULL)) { break; } if(buf[0]=='#') { continue; } token=strtok(buf,"\t, "); offset=1; while(token!=NULL) { switch(offset) { case KNI_OFFSET_ROUTDIR: routdir=atoi(token); if((routdir!=0)&&(routdir!=1)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"kni_read_cardname","routdir :%d error",routdir); return -1; } break; case KNI_OFFSET_CARDNAME: memcpy(g_kni_cardname[routdir],token,strlen(token)); break; default: break; } token=strtok(NULL,"\t, "); offset++; } } fclose(fp); fp=NULL; MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"kni_read_cardname","card name:%s,%s",g_kni_cardname[0],g_kni_cardname[1]); return 0; } int init_profile_info() { //main.conf // MESA_load_profile_int_def((char*)KNI_CONF_FILENAME_MAIN,(char*)KNI_CONF_MODE,(char*)"thread_num",&(g_kni_comminfo.thread_num),1); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME_MAIN,(char*)KNI_CONF_MODE,(char*)"pcapdevice",g_kni_comminfo.card_in,KNI_CONF_MAXLEN,"cap0"); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME_MAIN,(char*)KNI_CONF_MODE,(char*)"pcapdevice2",g_kni_comminfo.card_out,KNI_CONF_MAXLEN,"cap1"); //kni.conf MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"replay_win_update",&(g_kni_switch_info.replay_win_update),1); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"default_work_mode",&(g_kni_switch_info.maat_default_mode),KNI_DEFAULT_MODE_INTERCEPT); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"ratelimit_switch",&(g_kni_switch_info.ratelimit_switch),1); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"replace_switch",&(g_kni_switch_info.replace_switch),1); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"sendpkt_mode",&(g_kni_switch_info.sendpkt_mode),0); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"tun_name",g_kni_comminfo.tun_name,KNI_CONF_MAXLEN,"tun0"); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"domain_path",g_kni_comminfo.domain_path,KNI_CONF_MAXLEN,"/home/server_unixsocket_file"); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"socketopt_mark",&(g_kni_comminfo.mark),101); return 0; } int init_kni_stat_htable() { MESA_htable_create_args_t hash_frags; memset(&hash_frags,0,sizeof(MESA_htable_create_args_t)); hash_frags.thread_safe=KNI_THREAD_SAFE; hash_frags.recursive=1; hash_frags.hash_slot_size=KNI_HTABLE_SIZE; hash_frags.max_elem_num=KNI_HTABLE_MAXNUM; hash_frags.eliminate_type=HASH_ELIMINATE_ALGO_FIFO; hash_frags.expire_time=0; hash_frags.key_comp=NULL; hash_frags.key2index=NULL; hash_frags.data_free=NULL; hash_frags.data_expire_with_condition=NULL; g_kni_structinfo.htable_to_tun_v4=MESA_htable_create(&hash_frags,sizeof(MESA_htable_create_args_t)); g_kni_structinfo.htable_to_tun_v6=MESA_htable_create(&hash_frags,sizeof(MESA_htable_create_args_t)); if((g_kni_structinfo.htable_to_tun_v4==NULL)||(g_kni_structinfo.htable_to_tun_v6==NULL)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"MESA_htable_create() error!action:%s",KNI_ACTION_EXIT); return -1; } return 0; } int init_kni_runtimelog() { int logger_level; char logger_filepath[KNI_CONF_MAXLEN]={0}; MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_level",&logger_level,RLOG_LV_INFO); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_filepath",logger_filepath,KNI_CONF_MAXLEN,"./log/kni.log"); g_kni_comminfo.logger=MESA_create_runtime_log_handle(logger_filepath,logger_level); if(g_kni_comminfo.logger==NULL) { printf("MESA_create_runtime_log_handle() error!exit...\n"); return -1; } return 0; } int init_kni_dyn_maat_info() { int ret = 0; int maat_readconf_mode=0; char redis_ip[INET_ADDRSTRLEN]={0}; int redis_db_index=0; int redis_port=0; unsigned short redis_port_real=0; int scandir_interval=KNI_SCANDIR_INTERVAL; int effect_interval=KNI_EFFECT_INTERVAL; char table_info_path[KNI_CONF_MAXLEN]={0}; char stat_file_dir[KNI_CONF_MAXLEN]={0}; MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_maat_readconf_mode",&maat_readconf_mode,KNI_READCONF_IRIS); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_scandir_interval",&scandir_interval,KNI_SCANDIR_INTERVAL); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_effect_interval",&effect_interval,KNI_EFFECT_INTERVAL); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_redis_db_index",&redis_db_index,0); MESA_load_profile_int_nodef((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_redis_port",(int*)&redis_port); MESA_load_profile_string_nodef((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_redis_server",redis_ip,INET_ADDRSTRLEN); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_stat_file_path",stat_file_dir,KNI_CONF_MAXLEN,KNI_DYN_STAT_FILEPATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"dyn_table_info_path",table_info_path,KNI_CONF_MAXLEN,KNI_TABLEINFO_PATH); g_kni_maatinfo.ipd_dyn_maat_feather=Maat_feather(g_iThreadNum,table_info_path,g_kni_comminfo.logger); if(g_kni_maatinfo.ipd_dyn_maat_feather==NULL) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"dyn_Maat_feather() error!table_info_path:%s,action:%s",table_info_path,KNI_ACTION_EXIT); return -1; } if(maat_readconf_mode==KNI_READCONF_JSON) { Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_JSON_FILE_PATH, KNI_MAATJSON_FILEPATH,strlen(KNI_MAATJSON_FILEPATH)); } else if(maat_readconf_mode==KNI_READCONF_REDIS) { redis_port_real=(unsigned short)redis_port; Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_REDIS_IP,(void*)redis_ip,strlen(redis_ip)+1); Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_REDIS_PORT,(void*)&redis_port_real,sizeof(unsigned short)); Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_REDIS_INDEX,(void*)&redis_db_index,sizeof(int)); } Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_SCANDIR_INTERVAL_MS, (void*)&scandir_interval,sizeof(int)); Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_EFFECT_INVERVAL_MS, (void*)&effect_interval,sizeof(int)); Maat_set_feather_opt(g_kni_maatinfo.ipd_dyn_maat_feather,MAAT_OPT_STAT_FILE_PATH,stat_file_dir,strlen(stat_file_dir)); ret=Maat_initiate_feather(g_kni_maatinfo.ipd_dyn_maat_feather); if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_initiate_feather() error!action:%s",KNI_ACTION_EXIT); return -1; } g_kni_maatinfo.tableid_dynamic_domain=Maat_table_register(g_kni_maatinfo.ipd_dyn_maat_feather,KNI_TABLENAME_DNY_DOMAIN); if(g_kni_maatinfo.tableid_dynamic_domain<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"dyn_Maat_table_register() error!tableid_dynamic_domain:%d,action:%s",g_kni_maatinfo.tableid_dynamic_domain,KNI_ACTION_EXIT); return -1; } return 0; } int init_kni_maat_info() { int ret = 0; int maat_readconf_mode=0; char redis_ip[INET_ADDRSTRLEN]={0}; int redis_db_index=0; int redis_port=0; unsigned short redis_port_real=0; int scandir_interval=KNI_SCANDIR_INTERVAL; int effect_interval=KNI_EFFECT_INTERVAL; char table_info_path[KNI_CONF_MAXLEN]={0}; char stat_file_dir[KNI_CONF_MAXLEN]={0}; char full_cfg_dir[KNI_CONF_MAXLEN]={0}; char inc_cfg_dir[KNI_CONF_MAXLEN]={0}; MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"maat_readconf_mode",&maat_readconf_mode,KNI_READCONF_IRIS); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"scandir_interval",&scandir_interval,KNI_SCANDIR_INTERVAL); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"effect_interval",&effect_interval,KNI_EFFECT_INTERVAL); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"redis_db_index",&redis_db_index,0); MESA_load_profile_int_nodef((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"redis_port",(int*)&redis_port); MESA_load_profile_string_nodef((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"redis_server",redis_ip,INET_ADDRSTRLEN); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"table_info_path",table_info_path,KNI_CONF_MAXLEN,KNI_TABLEINFO_PATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"inc_cfg_dir",inc_cfg_dir,KNI_CONF_MAXLEN,KNI_INCCFG_FILEPATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"stat_file_path",stat_file_dir,KNI_CONF_MAXLEN,KNI_STAT_FILEPATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"full_cfg_dir",full_cfg_dir,KNI_CONF_MAXLEN,KNI_FULLCFG_FILEPATH); g_kni_maatinfo.maat_feather=Maat_feather(g_iThreadNum,table_info_path,g_kni_comminfo.logger); if(g_kni_maatinfo.maat_feather==NULL) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_feather() error!table_info_path:%s,action:%s",table_info_path,KNI_ACTION_EXIT); return -1; } if(maat_readconf_mode==KNI_READCONF_JSON) { Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_JSON_FILE_PATH, KNI_MAATJSON_FILEPATH,strlen(KNI_MAATJSON_FILEPATH)); } else if(maat_readconf_mode==KNI_READCONF_IRIS) { Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_FULL_CFG_DIR,full_cfg_dir,strlen(full_cfg_dir)); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_INC_CFG_DIR,inc_cfg_dir,strlen(inc_cfg_dir)); } else if(maat_readconf_mode==KNI_READCONF_REDIS) { redis_port_real=(unsigned short)redis_port; Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_REDIS_IP,(void*)redis_ip,strlen(redis_ip)+1); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_REDIS_PORT,(void*)&redis_port_real,sizeof(unsigned short)); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_REDIS_INDEX,(void*)&redis_db_index,sizeof(int)); } Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_SCANDIR_INTERVAL_MS, (void*)&scandir_interval,sizeof(int)); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_EFFECT_INVERVAL_MS, (void*)&effect_interval,sizeof(int)); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_STAT_FILE_PATH,stat_file_dir,strlen(stat_file_dir)); ret=Maat_initiate_feather(g_kni_maatinfo.maat_feather); if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_initiate_feather() error!action:%s",KNI_ACTION_EXIT); return -1; } g_kni_maatinfo.tableid_ip=Maat_table_register(g_kni_maatinfo.maat_feather,KNI_TABLENAME_IP); g_kni_maatinfo.tableid_domain=Maat_table_register(g_kni_maatinfo.maat_feather,KNI_TABLENAME_DOMAIN); g_kni_maatinfo.tableid_pktbin=Maat_table_register(g_kni_maatinfo.maat_feather,KNI_TABLENAME_PKTBIN); if((g_kni_maatinfo.tableid_ip<0)||(g_kni_maatinfo.tableid_domain<0)||(g_kni_maatinfo.tableid_pktbin<0)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_table_register() error!ip_tableid:%d,sni_tableid:%d,action:%s",g_kni_maatinfo.tableid_ip,g_kni_maatinfo.tableid_domain,KNI_ACTION_EXIT); return -1; } return 0; } int init_kni_project() { g_kni_comminfo.project_id=project_producer_register(KNI_PROJECT_NAME,PROJECT_VAL_TYPE_STRUCT,kni_free_project); if(g_kni_comminfo.project_id<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"project_producer_register() error!project_id:%d",g_kni_comminfo.project_id); return -1; } g_kni_comminfo.project_id=project_customer_register(KNI_PROJECT_NAME,PROJECT_VAL_TYPE_STRUCT); if(g_kni_comminfo.project_id<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"project_customer_register() error!project_id:%d",g_kni_comminfo.project_id); return -1; } return 0; } int init_kni_sendpkt() { int i=0; pthread_t pid_read_tun; kni_read_cardname(); g_kni_comminfo.ipv4_fd=(int*)malloc(g_kni_comminfo.thread_num*sizeof(int)); for(i=0;i