#include #include #include #include #include #include #include #include #include "kni_replace.h" #include "kni_entry.h" #include "kni_utils.h" int g_kni_version_VERSION_20181204; 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=ALLOC(struct kni_pme_info, 1); pmeinfo->tun_index = -1; *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; } void kni_free_htable(void* htable_data) { struct kni_htable_datainfo* datainfo = (struct kni_htable_datainfo*)htable_data; if(datainfo != NULL) { free(datainfo); datainfo = NULL; } return; } int kni_htable_del(const struct streaminfo* pstream,const void* a_packet) { int ret = 0; struct stream_tuple4_v4 ipv4_addr; struct stream_tuple4_v6 ipv6_addr; if((pstream->addr.addrtype == ADDR_TYPE_IPV4)) { kni_get_ipaddr_v4((void*)a_packet,&ipv4_addr); ret = MESA_htable_del(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),kni_free_htable); if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"MESA_htable_del",a_packet,"IPv4 MESA_htable_del() error,ret:%d",ret); return -1; } else { kni_filestate2_set(pstream->threadnum,COLUME_HTABLE_DEL,0,1); } } else { kni_get_ipaddr_v6((void*)a_packet,&ipv6_addr); ret = MESA_htable_del(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),kni_free_htable); if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"MESA_htable_del",a_packet,"IPv6 MESA_htable_del() error,ret:%d",ret); return -1; } } return 0; } int kni_htable_add(const struct streaminfo* pstream,const void* a_packet,struct kni_pme_info* pmeinfo) { int ret = 0; 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=ALLOC(struct kni_htable_datainfo, 1); //send pkt info by self if(iprevers==0) { datainfo->route_dir=pstream->routedir; memcpy(datainfo->smac, mac_addr->src_mac, sizeof(datainfo->smac)); memcpy(datainfo->dmac, mac_addr->dst_mac, sizeof(datainfo->dmac)); } 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, sizeof(datainfo->smac)); memcpy(datainfo->dmac, mac_addr->src_mac, sizeof(datainfo->dmac)); } //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), sizeof(datainfo->lastpkt_info)); if(pstream->addr.addrtype == ADDR_TYPE_IPV4) { iprevers=kni_get_ipaddr_v4((void*)a_packet,&ipv4_addr); ret = MESA_htable_add(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),(void*)datainfo); if(ret == MESA_HTABLE_RET_DUP_ITEM) { kni_log_debug(RLOG_LV_FATAL,(char*)"kni_htable_add dup",a_packet,"-5"); return -1; } else if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"kni_htable_add",a_packet,"IPv4 MESA_htable_add() error,ret:%d",ret); return -1; } else { kni_filestate2_set(pstream->threadnum,COLUME_HTABLE_ADD,0,1); } } else { iprevers=kni_get_ipaddr_v6((void*)a_packet,&ipv6_addr); ret = MESA_htable_add(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),(void*)datainfo); if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"kni_htable_add",a_packet,"IPv6 MESA_htable_add() error,ret:%d",ret); return -1; } } return 0; } /* int kni_htable_add(const struct streaminfo* pstream,const void* a_packet,struct kni_pme_info* pmeinfo) { int ret = 0; 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 by self 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); ret = MESA_htable_add(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),(void*)datainfo); if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"kni_htable_add",a_packet,"IPv4 MESA_htable_add() error,ret:%d",ret); return -1; } } else { iprevers=kni_get_ipaddr_v6((void*)a_packet,&ipv6_addr); ret = MESA_htable_add(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),(void*)datainfo); if(ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"kni_htable_add",a_packet,"IPv6 MESA_htable_add() error,ret:%d",ret); return -1; } } 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 ext_offset=0; char* ssl_extention=NULL; unsigned short extension_len_less=0; unsigned short type_in_extension=0; unsigned short ext_len=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,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; if(ssl_body - tcp_data + ssl_body_len >= tcp_datalen) return KNI_FLAG_UNKNOW; extension_len_less=ntohs(*(unsigned short*)&ssl_extention[ext_offset]); 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; } ext_offset+=2; while(ext_offsetKNI_SNI_MAXLEN) { //error return KNI_FLAG_UNKNOW; } if(ext_len>KNI_DEFAULT_MTU) { ext_len=KNI_DEFAULT_MTU; } memcpy(sni,&ssl_extention[ext_offset],ext_len); *sni_len=ext_len; return KNI_FLAG_SSL; } else { ext_offset+=ext_len; 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,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,COLUME_SSL,0,1); return KNI_FLAG_SSL; } else if((clienthello_flag == 1)&&(sni_flag == 0)) { kni_log_debug(RLOG_LV_DEBUG,(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) { struct timespec start, end; long elapse=0; 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); assert(domain_len<(int)sizeof(domain)); 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,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_filestate2_set(pstream->threadnum,COLUME_RATELIMIT,0,1); 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; default: pmeinfo->action = KNI_ACTION_MONITOR; break; } kni_filestate2_set(pstream->threadnum,COLUME_INTERCEPT,0,1); if(kni_htable_add(pstream,a_packet,pmeinfo) < 0) { pmeinfo->action = KNI_ACTION_NOTPROC; kni_filestate2_set(pstream->threadnum,COLUME_DROP_ADDHTABLE_ERROR,0,1); return ret; } clock_gettime(CLOCK_MONOTONIC, &start); if(tcp_repair_process(pstream,a_packet,pmeinfo,pmeinfo->protocol)<0) { kni_htable_del(pstream,a_packet); pmeinfo->action = KNI_ACTION_NOTPROC; clock_gettime(CLOCK_MONOTONIC, &end); elapse=(end.tv_sec-start.tv_sec)*1000000+(end.tv_nsec-start.tv_nsec)/1000; FS_operate(g_kni_fs2_info.handler, g_kni_fs2_info.metric_tcprepair, 0, FS_OP_SET, elapse); MESA_handle_runtime_log(g_kni_comminfo.logger,RLOG_LV_INFO,"tcp_repair_process","tcp_repair_process() error!"); return ret; } clock_gettime(CLOCK_MONOTONIC, &end); elapse=(end.tv_sec-start.tv_sec)*1000000+(end.tv_nsec-start.tv_nsec)/1000; FS_operate(g_kni_fs2_info.handler, g_kni_fs2_info.metric_tcprepair, 0, FS_OP_SET, elapse); 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_filestate2_set(pstream->threadnum,COLUME_TCP_NOT_HTTPSSL,0,1); 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_payload(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 { kni_filestate2_set(thread_seq,COLUME_DROP_NOTIPV46_SAPP,0,1); 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,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); if(datalen>0)//TODO:get link create mode from sapp { ret=kni_first_tcpdata(pstream,a_packet,pmeinfo,data,datalen); if((pmeinfo->action == KNI_ACTION_MONITOR) && ((pmeinfo->protocol==KNI_FLAG_HTTP) ||(pmeinfo->protocol==KNI_FLAG_SSL))) { if(g_kni_switch_info.write_listq_switch == 1) { if(pmeinfo->tun_index<0) { pmeinfo->tun_index=random()%g_kni_comminfo.tun_threadnum; } ret = kni_add_lqueue(ADDR_TYPE_IPV4,thread_seq,(char*)ipv4_hdr,iplen,pstream,pmeinfo->tun_index); } else { ret=tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)ipv4_hdr,iplen,(struct streaminfo*)pstream,thread_seq); } } } else { ret=APP_STATE_FAWPKT|APP_STATE_GIVEME; } } 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_payload(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 { kni_filestate2_set(thread_seq,COLUME_DROP_NOTIPV46_SAPP,0,1); 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))) { kni_filestate2_set(pstream->threadnum,COLUME_INTERCEPT,0,1); if(g_kni_switch_info.write_listq_switch == 1) { if(pmeinfo->tun_index<0) { pmeinfo->tun_index=random()%g_kni_comminfo.tun_threadnum; MESA_handle_runtime_log(g_kni_comminfo.logger,RLOG_LV_FATAL,"get tun_index","index:%d",pmeinfo->tun_index); } ret = kni_add_lqueue(ADDR_TYPE_IPV4,thread_seq,(char*)a_packet,iplen,pstream,pmeinfo->tun_index); } else { 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; int htable_ret = 0; if(a_packet==NULL) { if(pmeinfo->action == KNI_ACTION_MONITOR) { htable_ret = MESA_htable_del(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)(pstream->addr.tuple4_v4),sizeof(struct stream_tuple4_v4),kni_free_htable); if(htable_ret < 0) { kni_log_debug(RLOG_LV_FATAL,(char*)"MESA_htable_del",a_packet,"IPv4 MESA_htable_del() error,ret:%d",ret); } else { kni_filestate2_set(pstream->threadnum,COLUME_HTABLE_DEL,0,1); } } return ret; } ret=kni_data_opstate(pstream,pmeinfo,thread_seq,a_packet,protocol); //del htable if(pmeinfo->action==KNI_ACTION_MONITOR) { kni_htable_del(pstream,a_packet); } 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,COLUME_UDP_ENTRY,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; struct timespec start, end; long elapse=0; clock_gettime(CLOCK_MONOTONIC, &start); 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,COLUME_DROP_IPV6OPT,0,1); return ret; } } kni_filestate2_set(thread_seq,COLUME_TCPALL_ENTRY,0,1); switch(pstream->pktstate) { case OP_STATE_PENDING: kni_filestate2_set(thread_seq,COLUME_PENDING,0,1); kni_filestate2_set(thread_seq,COLUME_PMENUM,0,1); 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: if(a_packet == NULL) { kni_filestate2_set(thread_seq,COLUME_CLOSE_TIMEOUT,0,1); } else { kni_filestate2_set(thread_seq,COLUME_CLOSE_FIN,0,1); } 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_filestate2_set(thread_seq,COLUME_PMENUM,0,-1); kni_free_pmeinfo(pme); *pme=NULL; if(pstream->pktstate != OP_STATE_CLOSE) { kni_filestate2_set(thread_seq,COLUME_CLOSE_DROPME,0,1); } } clock_gettime(CLOCK_MONOTONIC, &end); elapse=(end.tv_sec-start.tv_sec)*1000000+(end.tv_nsec-start.tv_nsec)/1000; FS_operate(g_kni_fs2_info.handler, g_kni_fs2_info.metric_sapp_proc, 0, FS_OP_SET, elapse); 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=MIN(session_info->buflen, KNI_DEFAULT_MTU); struct kni_http_project* host_info=ALLOC(struct kni_http_project, 1); 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; } kni_filestate2_set(thread_seq,COLUME_IP_ENTRY,0,1); 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(ipv4_addr)); ipv4_addr.daddr = *((unsigned int*)&(ipv4_hdr->ip_dst)); ipv4_addr.saddr = *((unsigned int*)&(ipv4_hdr->ip_src)); memset(&pmeinfo,0,sizeof(pmeinfo)); 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; } kni_filestate2_set(thread_seq,COLUME_IP_ENTRY,0,1); addr.addrtype = ADDR_TYPE_IPV6; addr.paddr = (void*)(&ipv6_addr); memset(&ipv6_addr,0,sizeof(ipv6_addr)); memcpy(ipv6_addr.saddr,&(ipv6_hdr->ip6_src),sizeof(ipv6_addr.saddr)); memcpy(ipv6_addr.daddr,&(ipv6_hdr->ip6_dst),sizeof(ipv6_addr.saddr)); // ipv6_addr.saddr=ipv6_hdr->ip6_src.s6_addr32; // ipv6_addr.daddr=ipv6_hdr->ip6_dst.s6_addr32; memset(&pmeinfo,0,sizeof(pmeinfo)); 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,sizeof(buf)); 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)); assert(strlen(token)