#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "forge_socket.h" #include "stream.h" #include "MESA_prof_load.h" #include "MESA_handle_logger.h" #include "MESA_htable.h" #include "MESA_list_queue.h" #include "Maat_rule.h" #include "field_stat2.h" #include "kni.h" int g_kni_version_VERSION_20180718; 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]; const char *g_kni_fs2_name[FS2_COLUMN_NUM] ={"RECV_PKTS","FWD_PKTS","DROP_PKTS","WRITE_PKTS","READ_PKTS","SEND_PKTS"}; extern int g_iThreadNum; extern "C" int sendpacket_do_checksum(unsigned char* buf,int protocol,int len); extern "C" int sendpacket_build_ethernet(unsigned char* dst,unsigned char* src,unsigned short type,const unsigned char* payload,int payload_s,unsigned char* buf); extern "C" unsigned char MESA_dir_reverse(unsigned char route_dir); /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ int kni_debug_info_v4(char* module,int state_flag,struct ip* a_packet) { int iplen=ntohs(a_packet->ip_len); struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(a_packet->ip_hl)); unsigned int seq=ntohl(tcphdr->seq); unsigned short sport=0; unsigned short dport=0; char saddr_v4[INET_ADDRSTRLEN]={0}; char daddr_v4[INET_ADDRSTRLEN]={0}; sport=ntohs(tcphdr->source); dport=ntohs(tcphdr->dest); inet_ntop(AF_INET, (void *)&((a_packet->ip_src).s_addr), saddr_v4, INET_ADDRSTRLEN); inet_ntop(AF_INET, (void *)&((a_packet->ip_dst).s_addr), daddr_v4, INET_ADDRSTRLEN); MESA_handle_runtime_log(g_kni_comminfo.logger,RLOG_LV_DEBUG,module,"addr:%s,%d,%s,%d,state_flag:%d,ip_len:%d,seq:%u",saddr_v4,sport,daddr_v4,dport,state_flag,iplen,seq); return 0; } /* int kni_filestate2_init() { int i=0; int j=0; int value=1; unsigned int fs2_sport; char fs2_filename[KNI_MAX_BUFLEN]={0}; char fs2_sip[KNI_MAX_BUFLEN]={0}; MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"filestat2_filename",fs2_filename,KNI_MAX_BUFLEN,(char*)"./log/kni_fs2.log"); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"filestat2_sip",fs2_sip,KNI_MAX_BUFLEN,(char*)"10.127.208.15"); MESA_load_profile_uint_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"filestat2_sport",(unsigned int*)&fs2_sport,8125); g_kni_fs2_info.handler=FS_create_handle(); FS_set_para(g_kni_comminfo.fs2_handler, OUTPUT_DEVICE,fs2_filename, strlen(fs2_filename)+1); FS_set_para(g_kni_comminfo.fs2_handler, PRINT_MODE, &value, sizeof(value)); FS_set_para(g_kni_comminfo.fs2_handler, STAT_CYCLE, &value, sizeof(value)); FS_set_para(g_kni_comminfo.fs2_handler, CREATE_THREAD, &value, sizeof(value)); FS_set_para(g_kni_comminfo.fs2_handler, APP_NAME, STEWARD_FS2_APPNAME, strlen(STEWARD_FS2_APPNAME)+1); FS_set_para(g_kni_comminfo.fs2_handler, STATS_SERVER_IP, fs2_sip, strlen(fs2_sip)+1); FS_set_para(g_kni_comminfo.fs2_handler, STATS_SERVER_PORT,&fs2_sport,sizeof(int)); for(i=0;iip_hl)); sport=ntohs(tcphdr->source); dport=ntohs(tcphdr->dest); if((sportip_src).s_addr)ip_dst).s_addr)))) { reverse_flag=1; } if(reverse_flag==1) { ipaddr->saddr=(iphdr->ip_dst).s_addr; ipaddr->daddr=(iphdr->ip_src).s_addr; ipaddr->source=tcphdr->dest; ipaddr->dest=tcphdr->source; } else { ipaddr->saddr=(iphdr->ip_src).s_addr; ipaddr->daddr=(iphdr->ip_dst).s_addr; ipaddr->source=tcphdr->source; ipaddr->dest=tcphdr->dest; } return reverse_flag; } /**************************************************************************** if(sportsource); dport=ntohs(tcphdr->dest); if(sportsaddr,ipv6_hdr->ip6_dst.s6_addr32,IPV6_ADDR_LEN); memcpy(ipaddr->daddr,ipv6_hdr->ip6_src.s6_addr32,IPV6_ADDR_LEN); ipaddr->source=tcphdr->dest; ipaddr->dest=tcphdr->source; } else { memcpy(ipaddr->saddr,ipv6_hdr->ip6_src.s6_addr32,IPV6_ADDR_LEN); memcpy(ipaddr->daddr,ipv6_hdr->ip6_dst.s6_addr32,IPV6_ADDR_LEN); ipaddr->source=tcphdr->source; ipaddr->dest=tcphdr->dest; } return reverse_flag; } static int kni_send_fds(int socket, int *fds, int n,int protocol) { int flags=MSG_NOSIGNAL; struct msghdr msg = {0}; struct cmsghdr *cmsg; char buf[CMSG_SPACE(n * sizeof(int))], dup[256]; memset(buf, 0, sizeof(buf)); struct iovec io = { .iov_base = &dup, .iov_len = sizeof(dup) }; //tlv info struct kni_tlv_info tlv_info; tlv_info.type=KNI_TLV_TYPE_PRO; tlv_info.len=0x0001; tlv_info.value=protocol; memcpy(dup,&tlv_info,sizeof(struct kni_tlv_info)); //end msg.msg_iov = &io; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(n * sizeof(int)); memcpy ((int *) CMSG_DATA(cmsg), fds, n * sizeof (int)); // if (sendmsg (socket, &msg, 0) < 0) if (sendmsg (socket, &msg, flags) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"kni_send_fds","sendmsg()error,errno:%d,%s",errno,strerror(errno)); return -1; } return 0; } int tun_set_queue(int fd, int enable) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); if (enable) ifr.ifr_flags = IFF_ATTACH_QUEUE; else ifr.ifr_flags = IFF_DETACH_QUEUE; return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } int tun_error(int i,int* fds) { for (--i; i >= 0; i--) { close(fds[i]); } return 0; } /* Flags: IFF_TUN - TUN device (no Ethernet headers) * IFF_TAP - TAP device * * IFF_NO_PI - Do not provide packet information * IFF_MULTI_QUEUE - Create a queue of multiqueue device */ int tun_alloc_mq(char *dev, int queues, int *fds) { int i=0; int err=0; int fd; int flag=0; struct ifreq ifr; char *clonedev = (char*)"/dev/net/tun"; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN | IFF_NO_PI | IFF_MULTI_QUEUE; if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } for (i = 0; i < queues; i++) { if ((fd = open(clonedev, O_RDWR)) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"tun_alloc_mq():open error,errno is:%d,%s,action:%s",errno,strerror(errno),KNI_ACTION_EXIT); tun_error(i,fds); return -1; } err = ioctl(fd, TUNSETIFF, (void *)&ifr); if (err) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"tun_alloc_mq():ioctl error,errno is:%d,%s,action:%s",errno,strerror(errno),KNI_ACTION_EXIT); close(fd); tun_error(i,fds); return -1; } //20180618 add set noblock flag= fcntl(fd, F_GETFL, 0); if(flag<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"fcntl():getfl error,errno is:%d,%s",errno,strerror(errno)); } if( fcntl( fd, F_SETFL, flag|O_NONBLOCK ) < 0 ) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"fcntl():setfl error,errno is:%d,%s",errno,strerror(errno)); } //end fds[i] = fd; } return 0; } int tun_alloc(char *dev, int flags) { struct ifreq ifr; int fd, err; char *clonedev = (char*)"/dev/net/tun"; /* open the clone device */ if( (fd = open(clonedev, O_RDWR)) < 0 ) { return fd; } /* preparation of the struct ifr, of type "struct ifreq" */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } /* try to create the device */ if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { close(fd); return err; } strcpy(dev, ifr.ifr_name); return fd; } /******************************************************************************************************************** name: function: args: return: *********************************************************************************************************************/ int tun_read_data(int fd,char* recv_buf,int max_buflen) { int recv_len=0; while(1) { recv_len = read(fd, recv_buf, KNI_MAX_BUFLEN); if((recv_len <0)&&(errno==11)) { continue; } else if(recv_len <0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_WRITETUN,"tun_read_data error %d, %s\n",errno,strerror(errno)); return -1; } else { return recv_len; } } return 0; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ char tun_write_data(int fd,char* send_buf,int send_buflen,struct streaminfo* pstream) { char ret=APP_STATE_DROPPKT|APP_STATE_GIVEME; int succ_sendlen=0; succ_sendlen = write(fd, send_buf,send_buflen); if((succ_sendlen<0)&&(pstream!=NULL)) { MESA_kill_tcp(pstream,(const void*)send_buf); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_WRITETUN,"write() error %d, %s",errno,strerror(errno)); ret=APP_STATE_DROPPKT|APP_STATE_DROPME; } else if(succ_sendlenip_hl)); struct kni_wndpro_reply_info* tcpinfo=&(datainfo->lastpkt_info[index]); struct ip* snd_iphdr=NULL; struct tcphdr* snd_tcphdr=NULL; char* sendbuf=(char*)malloc(iplen); memcpy(sendbuf,a_packet,iplen); snd_iphdr=(struct ip*)sendbuf; snd_tcphdr=(struct tcphdr*)((char*)snd_iphdr+4*(snd_iphdr->ip_hl)); (snd_iphdr->ip_src).s_addr=(iphdr->ip_dst).s_addr; (snd_iphdr->ip_dst).s_addr=(iphdr->ip_src).s_addr; // snd_iphdr->ip_id=ipid; // snd_iphdr->ip_id=htons(datainfo->lastpkt_info[index].ipid+1); // snd_iphdr->ip_ttl=datainfo->lastpkt_info[index].ttl; snd_tcphdr->source=tcphdr->dest; snd_tcphdr->dest=tcphdr->source; snd_tcphdr->seq=htonl(tcpinfo->seq+tcpinfo->len); snd_tcphdr->ack_seq=htonl(tcpinfo->ack); if(tcpinfo->syn_flag==1) { snd_tcphdr->seq=htonl(ntohl(snd_tcphdr->seq)+1); } /* if(iprever_flag==0) { snd_iphdr->ip_id=ipid; snd_tcphdr->window=htons((win>>win_scale)+1); } */ sendpacket_do_checksum((unsigned char*)sendbuf,IPPROTO_TCP,(iplen-4*(iphdr->ip_hl))); sendpacket_do_checksum((unsigned char*)sendbuf,IPPROTO_IP,sizeof(struct ip)); tun_write_data(g_kni_comminfo.fd_tun[thread_seq],sendbuf,iplen,NULL); kni_debug_info_v4((char*)"recv_keepalive_request",5,(struct ip*)a_packet); kni_debug_info_v4((char*)"send_keepalive_replay",5,(struct ip*)sendbuf); free(sendbuf); sendbuf=NULL; datainfo->wndpro_flag[index]=1; return 1; } long kni_readtun_htable_cb_v4(void* data,const unsigned char* key,unsigned int size,void* user_arg) { long result=0; struct stream_tuple4_v4* ipv4_addr=(struct stream_tuple4_v4*)key; struct args_read_tun* args=(struct args_read_tun*)user_arg; struct kni_htable_datainfo* datainfo=(struct kni_htable_datainfo*)data; if(datainfo!=NULL) { memcpy(args->smac,datainfo->smac,KNI_MACADDR_LEN); memcpy(args->dmac,datainfo->dmac,KNI_MACADDR_LEN); if(args->iprevers==0) { args->routdir=datainfo->route_dir; } else { // args->routdir=MESA_dir_reverse(datainfo->route_dir); args->routdir=1-datainfo->route_dir; } if(datainfo->wndpro_flag[1-args->iprevers]>0) { result=1; } else { kni_keepalive_replay(ipv4_addr,args->iprevers,datainfo,args->a_packet,args->iplen,args->thread_seq); result=1; } } #ifdef KNI_DEBUG_TCPREPAIR else if(ipv4_addr->saddr==1698867392) { printf("sip is 192.168.66.101\n"); args->smac[0]=0x18; args->smac[1]=0x66; args->smac[2]=0xda; args->smac[3]=0xe5; args->smac[4]=0xfa; args->smac[5]=0xa1; args->dmac[0]=0xe8; args->dmac[1]=0x61; args->dmac[2]=0x1f; args->dmac[3]=0x13; args->dmac[4]=0x70; args->dmac[5]=0x7a; result=1; } else { kni_debug_info_v4((char*)"read_tun,data=NULL,sip not 192.168.66.101",0,(struct ip*)args->a_packet); } #endif return result; } int init_domain_fd() { int i_fd = 0; struct sockaddr_un addr; // char serverpath[32] = "/home/server_unixsocket_file"; int i_addr_len = sizeof( struct sockaddr_un ); if ( ( i_fd = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) // if ( ( i_fd = socket( AF_UNIX, SOCK_DGRAM, 0 ) ) < 0 ) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd():socket error,errno is %d,%s,,action:%s",errno,strerror(errno),KNI_ACTION_EXIT); return -1; } //fill socket adress structure with server's address memset( &addr, 0, sizeof( addr ) ); addr.sun_family = AF_UNIX; // strncpy( addr.sun_path, serverpath, sizeof( addr.sun_path ) - 1 ); strncpy( addr.sun_path, g_kni_comminfo.domain_path, sizeof( addr.sun_path ) - 1 ); if ( connect( i_fd, ( struct sockaddr * )&addr, i_addr_len ) < 0 ) { close(i_fd); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd():connect error,errno is %d,%s,action:%s",errno,strerror(errno),KNI_ACTION_EXIT); return -1; } MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd():domain socket connect succ! "); return i_fd; } int kni_process_readdata(int thread_seq,int buflen,char* buf) { int iprever_flag=0; long result=0; struct ip* iphdr=(struct ip*)buf; struct stream_tuple4_v4 ipv4_addr; struct args_read_tun args; if(iphdr->ip_v==4) { iprever_flag=kni_get_ipaddr_v4((void*)buf,&ipv4_addr); kni_debug_info_v4((char*)KNI_MODULE_READTUN,KNI_FLAG_SSL,(struct ip*)buf); args.a_packet=buf; args.iplen=buflen; args.iprevers=iprever_flag; args.thread_seq=thread_seq; MESA_htable_search_cb(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),kni_readtun_htable_cb_v4,(void*)&args,&result); if(result==1) { // kni_sendpkt_eth(thread_seq,buflen,buf,&ipv4_addr,iprever_flag,args.routdir,args.smac,args.dmac); kni_sendpkt_routdir(thread_seq,buflen,buf,&ipv4_addr,iprever_flag,args.routdir,args.smac,args.dmac); } } return 0; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ void* kni_read_tun(void* arg) { int thread_seq=*(int*)arg; int recv_len=0; char recv_buf[KNI_MAX_BUFLEN] = {0}; while(1) { if(g_kni_comminfo.kni_mode_cur==KNI_MODE_BYPASS) { sleep(KNI_USLEEP_TIME); continue; } recv_len=0; memset(recv_buf,0,KNI_MAX_BUFLEN); recv_len=tun_read_data(g_kni_comminfo.fd_tun[thread_seq],recv_buf, KNI_MAX_BUFLEN); if(recv_len <0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_READTUN,"tun_read_data()error,recv_len:%d",recv_len); } else if(recv_len>0) { kni_process_readdata(thread_seq,recv_len,recv_buf); } } return 0; } int kni_sendfds_domain() { int ret=0; long fds_len=KNI_FDS_NUM*sizeof(int); int fds[KNI_FDS_NUM]={0}; while(1) { memset(fds,0,KNI_FDS_NUM*sizeof(int)); fds_len=KNI_FDS_NUM*sizeof(int); // ret=MESA_lqueue_try_get_tail(g_kni_structinfo.lqueue_for_domain,fds,&fds_len); ret=MESA_lqueue_get_tail(g_kni_structinfo.lqueue_for_domain,fds,&fds_len); if(ret==MESA_QUEUE_RET_QEMPTY) { continue; } else if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_READTUN,"MESA_lqueue_try_get_tail() error!ret:%d\n",ret); continue; } ret=kni_send_fds(g_kni_comminfo.fd_domain,fds,2,fds[KNI_FDS_INDEX_PROTOCOL]); if(ret<0) //check errno { g_kni_comminfo.kni_mode_cur=KNI_MODE_BYPASS; return -1; } close(fds[KNI_FDS_INDEX_CLIENT]); close(fds[KNI_FDS_INDEX_SERVER]); } return 0; } int kni_connect_domain() { while(1) { g_kni_comminfo.fd_domain=init_domain_fd(); if(g_kni_comminfo.fd_domain<0) { sleep(1); } else { g_kni_comminfo.kni_mode_cur=KNI_MODE_WORK; return 0; } } return 0; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ void* kni_process_domain(void* arg) { while(1) { if(g_kni_comminfo.kni_mode_cur==KNI_MODE_BYPASS) { kni_connect_domain(); } else { kni_sendfds_domain(); } } return 0; } int tcprepair_get_state(struct kni_tcp_state* fake_client,struct kni_tcp_state* fake_server,void* a_packet,struct kni_pme_info* pmeinfo) { struct ip* iphdr=(struct ip*)a_packet; struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(iphdr->ip_hl)); fake_client->src_ip=(iphdr->ip_src).s_addr; fake_client->sport=tcphdr->source; fake_client->dst_ip=(iphdr->ip_dst).s_addr; fake_client->dport =tcphdr->dest; fake_client->seq=ntohl(tcphdr->seq); fake_client->ack=ntohl(tcphdr->ack_seq); fake_client->mss_src=pmeinfo->mss[KNI_DIR_C2S]; fake_client->wscale_src=pmeinfo->wnscal[KNI_DIR_C2S]; fake_client->wscale_dst=pmeinfo->wnscal[KNI_DIR_S2C]; fake_client->sack_src=pmeinfo->sack[KNI_DIR_C2S]; fake_client->sack_dst=pmeinfo->sack[KNI_DIR_S2C]; fake_client->timestamps_src=pmeinfo->timestamps[KNI_DIR_C2S]; fake_client->timestamps_dst=pmeinfo->timestamps[KNI_DIR_S2C]; fake_server->src_ip=(iphdr->ip_dst).s_addr; fake_server->sport=tcphdr->dest; fake_server->dst_ip=(iphdr->ip_src).s_addr; fake_server->dport =tcphdr->source; fake_server->seq=ntohl(tcphdr->ack_seq); fake_server->ack=ntohl(tcphdr->seq); fake_server->mss_src=pmeinfo->mss[KNI_DIR_S2C]; fake_server->wscale_src=pmeinfo->wnscal[KNI_DIR_S2C]; fake_server->wscale_dst=pmeinfo->wnscal[KNI_DIR_C2S]; fake_server->sack_src=pmeinfo->sack[KNI_DIR_S2C]; fake_server->sack_dst=pmeinfo->sack[KNI_DIR_C2S]; fake_server->timestamps_src=pmeinfo->timestamps[KNI_DIR_S2C]; fake_server->timestamps_dst=pmeinfo->timestamps[KNI_DIR_C2S]; return 0; } int tcprepair_set_state(int sk,struct kni_tcp_state* tcp) { int val,yes=1, onr = 0; // int mark = 2; // int mark_tmp=0; // socklen_t mark_len=sizeof(mark_tmp); struct tcp_repair_opt opts[KNI_TCPREPAIR_OPT_NUM]; struct sockaddr_in addr; if (setsockopt(sk, SOL_TCP, TCP_REPAIR, &yes, sizeof(yes))==-1) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR error,errno:%d,%s",errno,strerror(errno)); return -1; } if (setsockopt(sk, SOL_IP, IP_TRANSPARENT, &yes, sizeof(yes)) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() IP_TRANSPARENT error,errno:%d,%s",errno,strerror(errno)); return -1; } if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() SO_REUSEADDR error,errno:%d,%s",errno,strerror(errno)); return -1; } /* if(setsockopt(sk, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() SO_MARK error,errno:%d",errno); return -1; } getsockopt(sk, SOL_SOCKET, SO_MARK, &mark_tmp, &mark_len); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","getsockopt() SO_MARK :%d",mark_tmp); */ /* ============= Restore TCP properties ==================*/ val = TCP_SEND_QUEUE; if (setsockopt(sk, SOL_TCP, TCP_REPAIR_QUEUE, &val, sizeof(val))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR_QUEUE,TCP_SEND_QUEUE error,errno:%d,%s",errno,strerror(errno)); return -1; } val = tcp->seq; if (setsockopt(sk, SOL_TCP, TCP_QUEUE_SEQ, &val, sizeof(val))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_QUEUE_SEQ error,errno:%d,%s",errno,strerror(errno)); return -1; } val = TCP_RECV_QUEUE; if (setsockopt(sk, SOL_TCP, TCP_REPAIR_QUEUE, &val, sizeof(val))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR_QUEUE,TCP_RECV_QUEUE error,errno:%d,%s",errno,strerror(errno)); return -1; } val = tcp->ack; if (setsockopt(sk, SOL_TCP, TCP_QUEUE_SEQ, &val, sizeof(val))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_QUEUE_SEQ error,errno:%d,%s",errno,strerror(errno)); return -1; } /* struct tcp_repair_window win; win.snd_wl1=tcp->seq; win.snd_wnd=tcp->wnscale[KNI_DIR_C2S]<wnscale[KNI_DIR_S2C]; win.max_window=win.snd_wnd; win.rcv_wnd=win.snd_wnd; win.rcv_wup=win.snd_wl1; if (setsockopt(sk, SOL_TCP, TCP_REPAIR_WINDOW, &win, sizeof(win))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR_WINDOW error,errno:%d",errno); return -1; } */ /* ============= Bind and connect ================ */ memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = tcp->sport; addr.sin_addr.s_addr=tcp->src_ip; if (bind(sk, (struct sockaddr *) &addr, sizeof(addr))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","bind() error,errno:%d,%s",errno,strerror(errno)); return -1; } memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = tcp->dport; addr.sin_addr.s_addr=tcp->dst_ip; if (connect(sk, (struct sockaddr *) &addr, sizeof(addr))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","connect() error,errno:%d,%s",errno,strerror(errno)); return -1; } opts[onr].opt_code = TCPOPT_WINDOW; opts[onr].opt_val = tcp->wscale_src+ (tcp->wscale_dst<< 16); onr++; opts[onr].opt_code = TCPOPT_MAXSEG; opts[onr].opt_val = tcp->mss_src; onr++; if((tcp->sack_src)&&(tcp->sack_dst)) { opts[onr].opt_code = TCPOPT_SACK_PERMITTED; opts[onr].opt_val = 0; onr++; } /* opts[onr].opt_code = TCPOPT_TIMESTAMP; opts[onr].opt_val = (tcp->timestamps_src)&&(tcp->timestamps_dst); onr++; */ MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","onr:%d,wscale_src:%d,wscale_dst:%d,wscale:%x,mss:%d,sack:%d",onr,tcp->wscale_src,tcp->wscale_dst,opts[0].opt_val,opts[1].opt_val,opts[2].opt_val); if (setsockopt(sk, SOL_TCP, TCP_REPAIR_OPTIONS,opts, onr * sizeof(struct tcp_repair_opt)) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR_OPTIONS error,errno:%d,%s",errno,strerror(errno)); return -1; } val = 0; if (setsockopt(sk, SOL_TCP, TCP_REPAIR, &val, sizeof(val))) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","setsockopt() TCP_REPAIR close error,errno:%d,%s",errno,strerror(errno)); return -1; } return 0; } int tcp_repair_process(const struct streaminfo* pstream,const struct ip* a_packet,struct kni_pme_info* pmeinfo,int protocol) { #ifdef KNI_DEBUG_TCPREPAIR return 0; #endif int ret=0; int fds[KNI_FDS_NUM]; int fd_client,fd_server; struct kni_tcp_state fake_client; struct kni_tcp_state fake_server; struct ip* iphdr=(struct ip*)a_packet; struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(iphdr->ip_hl)); // int tcplen=ntohs(iphdr->ip_len)-4*iphdr->ip_hl-4*tcphdr->doff; fd_client = socket(AF_INET, SOCK_STREAM, 0); fd_server = socket(AF_INET, SOCK_STREAM, 0); if ((fd_client < 0)||(fd_server<0)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","socket() error"); return -1; } tcprepair_get_state(&fake_client,&fake_server,(void*)a_packet,pmeinfo); ret=tcprepair_set_state(fd_client,&fake_server); if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","fd_client tcprepair_set_state() error,dropme and fwdpkt"); return -1; } ret=tcprepair_set_state(fd_server,&fake_client); if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"tcprepair_set_state","fd_server tcprepair_set_state() error,dropme and fwdpkt"); return -1; } fds[0]=fd_client; fds[1]=fd_server; fds[2]=protocol; // ret=MESA_lqueue_try_join_head(g_kni_structinfo.lqueue_for_domain,(void*)fds,KNI_FDS_NUM*sizeof(int)); ret=MESA_lqueue_join_head(g_kni_structinfo.lqueue_for_domain,(void*)fds,KNI_FDS_NUM*sizeof(int)); if(ret <0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_SENDFD,"MESA_lqueue_try_join_head() error,ret:%d",ret); } /* kni_send_fds(g_kni_comminfo.fd_domain,fds,2,protocol); close(fds[0]); close(fds[1]); */ return 0; } /*************************************************************************************** return :state_flag kni_bmd:STAT_FLAG_SNIBMD not kni_bmd:STAT_FLAG_SSL_NOBMD ***************************************************************************************/ int kni_judge_sni(char* sni,int sni_len,int thread_seq,scan_status_t mid) { int i=0; int action=KNI_ACTION_NONE; int state_flag=KNI_FLAG_NOTPROC; 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,sni,sni_len,maat_result,&found_pos,KNI_MAX_SAMENUM,&mid,thread_seq); for(i=0;iKNI_SNI_MAXLEN) { //error return STAT_FLAG_NOTSSL; } memcpy(sni,&ssl_extention[ssl_extention_len],len_in_extension); *sni_len=len_in_extension; return STAT_FLAG_SSL_NOBMD; } else { ssl_extention_len+=len_in_extension; continue; } } return STAT_FLAG_NOTSSL; } */ /*************************************************************************************** return :action default:ipscan_num =0 or =1,not >1 ***************************************************************************************/ int kni_judge_ipbmd(struct ipaddr* addr,int thread_seq,int protocol,scan_status_t mid) { int i=0; int action=KNI_ACTION_NONE; 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,&mid,thread_seq); for(i=0;iseq=ntohl(tcphdr->th_seq); lastpkt_info->ack=ntohl(tcphdr->th_ack); lastpkt_info->ipid=ntohs(ip_hdr->ip_id); lastpkt_info->ttl=ip_hdr->ip_ttl; lastpkt_info->len=tcplen; lastpkt_info->wndsize=ntohs(tcphdr->th_win); if(tcphdr->th_flags&TH_SYN) { lastpkt_info->syn_flag=1; } return 0; } int kni_get_tcpopt(struct kni_tcp_hdr* tcphdr,int tcp_hdr_len,unsigned short* mss,unsigned char* winscale,unsigned char* scak,unsigned char* timestamps) { *mss=KNI_DEFAULT_MSS; *winscale=KNI_DEFAULT_WINSCLE; int remain_len=tcp_hdr_len; struct kni_tcp_opt_format* tcp_opt=NULL; if((tcp_hdr_len<=20)||(tcp_hdr_len>64)) { return 0; } tcp_opt=(struct kni_tcp_opt_format*)((char*)tcphdr+TCPHDR_DEFAULT_LEN); remain_len-=TCPHDR_DEFAULT_LEN; while(remain_len) { if(tcp_opt->type==KNI_TCPOPT_MSS) //MSS { remain_len-=tcp_opt->len; *mss=htons(*(unsigned short*)(tcp_opt->content)); tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+tcp_opt->len); continue; } else if(tcp_opt->type==KNI_TCPOPT_WINSCALE) //winscale { remain_len-=tcp_opt->len; *winscale=*(unsigned char*)(tcp_opt->content); tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+tcp_opt->len); continue; } else if(tcp_opt->type==KNI_TCPOPT_SACKOK) //scak { remain_len-=tcp_opt->len; *scak=1; tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+tcp_opt->len); continue; } else if(tcp_opt->type==KNI_TCPOPT_TIMESTAMP) //timestamp { remain_len-=tcp_opt->len; *timestamps=1; tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+tcp_opt->len); continue; } else if((tcp_opt->type==0)||(tcp_opt->type==1)) { remain_len-=1; tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+1); continue; } else { remain_len-=tcp_opt->len; tcp_opt=(struct kni_tcp_opt_format*)((char*)tcp_opt+tcp_opt->len); continue; } } return 0; } char* kni_get_data(const struct streaminfo* pstream,int* datalen) { char* data=NULL; if(pstream->type==STREAM_TYPE_TCP) { data=(char*)(pstream->ptcpdetail->pdata); *datalen=pstream->ptcpdetail->datalen; } else if(pstream->type==STREAM_TYPE_UDP) { data=(char*)(pstream->pudpdetail->pdata); *datalen=pstream->pudpdetail->datalen; } else { data=NULL; *datalen=0; } return data; } int kni_htable_add(const struct streaminfo* pstream,const struct ip* ip_hdr,struct kni_pme_info* pmeinfo) { int iprevers=0; struct stream_tuple4_v4 ipv4_addr; struct layer_addr_mac* mac_addr=(struct layer_addr_mac*)((char*)ip_hdr-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)); iprevers=kni_get_ipaddr_v4((void*)ip_hdr,&ipv4_addr); //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 { // datainfo->route_dir=MESA_dir_reverse(pstream->routedir); datainfo->route_dir=1-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->wnscal,pmeinfo->wnscal,KNI_DIR_DOUBLE*sizeof(unsigned char)); memcpy(datainfo->mss,pmeinfo->mss,KNI_DIR_DOUBLE*sizeof(unsigned short)); memcpy(&(datainfo->lastpkt_info),&(pmeinfo->lastpkt_info),KNI_DIR_DOUBLE*sizeof(struct kni_wndpro_reply_info)); MESA_htable_add(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),(void*)datainfo); return 0; } /*************************************************************************************** return :state_flag ssl:STAT_FLAG_SSL_NOBMD not ssl:STAT_FLAG_NOTSSL ***************************************************************************************/ int kni_judge_ssl(char* tcp_data,int tcp_datalen,char* sni,int* sni_len) { // int state_flag=KNI_FLAG_UNKNOW; // return KNI_FLAG_SSL; 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; // 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; } 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) { int val=project_req_get_int(stream,g_kni_comminfo.project_id); return val; } int kni_protocol_identify(const struct streaminfo* pstream,char* tcp_data,int tcp_datalen,char* sni,int* sni_len) { if(kni_judge_http(pstream)==1) { return KNI_FLAG_HTTP; } else if(kni_judge_ssl(tcp_data,tcp_datalen,sni,sni_len)==KNI_FLAG_SSL) { return KNI_FLAG_SSL; } return KNI_FLAG_NOTPROC; } int kni_protocol_identify_bak(const struct streaminfo* pstream,char* tcp_data,int tcp_datalen,char* sni,int* sni_len) { int pro_flag=KNI_FLAG_NOTPROC; unsigned short sport=ntohs(pstream->addr.tuple4_v4->source); unsigned short dport=ntohs(pstream->addr.tuple4_v4->dest); if((sport==80)||(dport==80)) { pro_flag=KNI_FLAG_HTTP; } else if(kni_judge_ssl(tcp_data,tcp_datalen,sni,sni_len)==KNI_FLAG_SSL) { pro_flag=KNI_FLAG_SSL; } return pro_flag; } char kni_first_tcpdata(const struct streaminfo* pstream,const struct ip* ip_hdr,struct kni_pme_info* pmeinfo,char* data,int datalen) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; int sni_len=0; char sni[KNI_MAX_BUFLEN]={0}; pmeinfo->status_flag=kni_protocol_identify(pstream,data,datalen,sni,&sni_len); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_DEBUG,(char*)"kni_protocol_identify","protocol:%d",pmeinfo->status_flag); if(pmeinfo->status_flag==KNI_FLAG_SSL) { pmeinfo->status_flag=kni_judge_sni(sni,sni_len,pstream->threadnum,pmeinfo->mid); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_DEBUG,(char*)"kni_judge_sni","status_flag:%d",pmeinfo->status_flag); } if((pmeinfo->status_flag==KNI_FLAG_HTTP) ||(pmeinfo->status_flag==KNI_FLAG_SSL)) { if(tcp_repair_process(pstream,ip_hdr,pmeinfo,pmeinfo->status_flag)<0) { return ret; } kni_htable_add(pstream,ip_hdr,pmeinfo); ret=APP_STATE_DROPPKT|APP_STATE_GIVEME; } return ret; } 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; } char kni_pending_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const struct ip* ip_hdr,int protocol) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; char* data=NULL; int datalen=0; int ipscan_action=0; int iplen=ntohs(ip_hdr->ip_len); struct kni_tcp_hdr* tcphdr=(struct kni_tcp_hdr*)((char*)ip_hdr+4*(ip_hdr->ip_hl)); ipscan_action=kni_judge_ipbmd((struct ipaddr*)&(pstream->addr),thread_seq,protocol,pmeinfo->mid); MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_DEBUG,(char*)"kni_judge_ipbmd","action:%d",ipscan_action); if(ipscan_action==KNI_ACTION_WHITELIST) { return ret; } pmeinfo->status_flag=KNI_FLAG_UNKNOW; // pmeinfo->wndsize[pstream->curdir-1]=ntohs(tcphdr->th_win); // if((tcphdr->th_flags&TH_SYN)&&!(tcphdr->th_flags&TH_ACK)) //get wndscale and mss from tcpopt only in syn and syn/ack { data=kni_get_data(pstream,&datalen); kni_get_tcpopt(tcphdr,iplen-4*(ip_hdr->ip_hl)-datalen,&(pmeinfo->mss[pstream->curdir-1]),&(pmeinfo->wnscal[pstream->curdir-1]),&(pmeinfo->sack[pstream->curdir-1]),&(pmeinfo->timestamps[pstream->curdir-1])); } kni_get_tcpinfo(&(pmeinfo->lastpkt_info[pstream->curdir-1]),tcphdr,ntohs(ip_hdr->ip_len)-4*ip_hdr->ip_hl-4*tcphdr->th_off,(struct ip*)ip_hdr); #ifndef KNI_DEBUG_TCPREPAIR if(datalen>0) #endif { ret=kni_first_tcpdata(pstream,ip_hdr,pmeinfo,data,datalen); if((pmeinfo->status_flag==KNI_FLAG_HTTP) ||(pmeinfo->status_flag==KNI_FLAG_SSL)) { ret=tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)ip_hdr,iplen,(struct streaminfo*)pstream); } } #ifndef KNI_DEBUG_TCPREPAIR else { ret=APP_STATE_FAWPKT|APP_STATE_GIVEME; } #endif return ret; } char kni_data_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const struct ip* ip_hdr) { char ret=APP_STATE_DROPPKT|APP_STATE_GIVEME; char* data=NULL; int datalen=0; int iplen=ntohs(ip_hdr->ip_len); // struct kni_pme_info* pmeinfo=(struct kni_pme_info*)*pme; struct kni_tcp_hdr* tcphdr=(struct kni_tcp_hdr*)((char*)ip_hdr+4*(ip_hdr->ip_hl)); data=kni_get_data(pstream,&datalen); if(pmeinfo->status_flag==KNI_FLAG_UNKNOW) { if((tcphdr->th_flags&TH_SYN)&&(tcphdr->th_flags&TH_ACK)) { kni_get_tcpopt(tcphdr,iplen-4*(ip_hdr->ip_hl)-datalen,&(pmeinfo->mss[pstream->curdir-1]),&(pmeinfo->wnscal[pstream->curdir-1]),&(pmeinfo->sack[pstream->curdir-1]),&(pmeinfo->timestamps[pstream->curdir-1])); } kni_get_tcpinfo(&(pmeinfo->lastpkt_info[pstream->curdir-1]),tcphdr,ntohs(ip_hdr->ip_len)-4*ip_hdr->ip_hl-4*tcphdr->th_off,(struct ip*)ip_hdr); if(datalen>0) { ret=kni_first_tcpdata(pstream,ip_hdr,pmeinfo,data,datalen); } else { ret=APP_STATE_FAWPKT|APP_STATE_GIVEME; } } if((pmeinfo->status_flag==KNI_FLAG_HTTP)||(pmeinfo->status_flag==KNI_FLAG_SSL)) { ret=tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)ip_hdr,iplen,(struct streaminfo*)pstream); } return ret; } char kni_close_opstate(const struct streaminfo* pstream,struct kni_pme_info* pmeinfo,int thread_seq,const struct ip* ip_hdr) { char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; if(ip_hdr==NULL) { return ret; } ret=kni_data_opstate(pstream,pmeinfo,thread_seq,ip_hdr); return ret|APP_STATE_DROPME; } extern "C" char kni_tcpall_entry(const struct streaminfo* pstream,void** pme,int thread_seq,const void* ip_hdr) { // return APP_STATE_FAWPKT|APP_STATE_GIVEME; char ret=APP_STATE_FAWPKT|APP_STATE_DROPME; if((g_kni_comminfo.kni_mode_cur==KNI_MODE_BYPASS)||(pstream->addr.addrtype==ADDR_TYPE_IPV6)) { return ret; } switch(pstream->pktstate) { case OP_STATE_PENDING: kni_init_pmeinfo(pme); ret=kni_pending_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,(const struct ip*)ip_hdr,PROTO_TYPE_TCP); break; case OP_STATE_DATA: ret=kni_data_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,(const struct ip*)ip_hdr); break; case OP_STATE_CLOSE: ret=kni_close_opstate(pstream,(struct kni_pme_info*)*pme,thread_seq,(const struct ip*)ip_hdr); break; default: break; } if((ret&APP_STATE_DROPME)&&(*pme!=NULL)) { kni_free_pmeinfo(pme); *pme=NULL; } return ret; } /* long kni_state_htable_cb_v6(void* data,const unsigned char* key,unsigned int size,void* user_arg) { struct ipaddr addr_ipbmd; struct datainfo_to_tun* datainfo=(struct datainfo_to_tun*)data; struct args_to_tun* arg=(struct args_to_tun*)user_arg; struct kni_ipv6_hdr* ipv6_hdr=(struct kni_ipv6_hdr*)(arg->a_packet); if(datainfo==NULL) { datainfo=(struct datainfo_to_tun*)malloc(sizeof(struct datainfo_to_tun)); memset(datainfo,0,sizeof(struct datainfo_to_tun)); MESA_htable_add(g_kni_structinfo.htable_to_tun_v4, key,size,(void*)datainfo); memset(&addr_ipbmd,0,sizeof(struct ipaddr)); addr_ipbmd.addrtype=ADDR_TYPE_IPV6; addr_ipbmd.v4=(struct stream_tuple4_v4*)key; datainfo->state_flag=kni_judge_ipbmd(&addr_ipbmd,arg->thread_seq,ipv6_hdr->ip6_nex_hdr); } return datainfo->state_flag; } char kni_ipv6_entry(struct streaminfo *pstream,unsigned char routedir,int thread_seq,void *a_packet) { int ip_reverse=0; struct kni_ipv6_hdr* ipv6_hdr=(struct kni_ipv6_hdr*)a_packet; long state_flag=0; struct args_to_tun usr_arg; struct stream_tuple4_v6 ipv6_addr; if(ipv6_hdr->ip6_nex_hdr!=PROTO_TYPE_TCP) { return APP_STATE_DROPME; } ip_reverse=kni_get_ipaddr_v6(a_packet,&ipv6_addr); memset(&usr_arg,0,sizeof(struct args_to_tun)); usr_arg.a_packet=(struct ip*)a_packet; usr_arg.thread_seq=thread_seq; if(ip_reverse==0) { usr_arg.routdir=routedir; } else { usr_arg.routdir=routedir^0x80; } MESA_htable_search_cb(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),kni_state_htable_cb_v6,&usr_arg,&state_flag); if(state_flag==KNI_FLAG_IPBMD) { return APP_STATE_DROPPKT; } tun_write_data_v6(g_kni_comminfo.fd_tun[thread_seq],(char*)a_packet,ntohl(ipv6_hdr->ip6_payload_len)); return APP_STATE_DROPPKT; } */ 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 val=1; project_req_add_int(a_stream,g_kni_comminfo.project_id,val); return ret; } int init_profile_info(int* logger_level,char* logger_filepath,int* maat_json_switch,char* table_info_path,char* inc_cfg_dir,char* full_cfg_dir ) { //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*)"default_switch",&(g_kni_switch_info.maat_default_switch),1); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_level",logger_level,RLOG_LV_INFO); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"maat_json_switch",maat_json_switch,0); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_filepath",logger_filepath,KNI_CONF_MAXLEN,"./log/kni.log"); 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*)"full_cfg_dir",full_cfg_dir,KNI_CONF_MAXLEN,KNI_FULLCFG_FILEPATH); 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"); 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 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; } extern "C" char kni_init() { int i=0; int ret=0; // char __tun_symbol[512] = "tun0"; int logger_level; char logger_filepath[KNI_CONF_MAXLEN]={0}; int maat_json_switch=0; char table_info_path[KNI_CONF_MAXLEN]={0}; char full_cfg_dir[KNI_CONF_MAXLEN]={0}; char inc_cfg_dir[KNI_CONF_MAXLEN]={0}; pthread_t pid_read_tun; pthread_t pid_pro_domain; // pthread_t pid_kni_filestat2; inet_aton((const char *)&LOCAL_IP_ADDR,(struct in_addr*)&g_kni_comminfo.local_ip); //init profile init_profile_info(&logger_level,logger_filepath,&maat_json_switch,table_info_path,inc_cfg_dir,full_cfg_dir); //init runtime 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; } //project g_kni_comminfo.project_id=project_producer_register(KNI_PROJECT_NAME,PROJECT_VAL_TYPE_INT,NULL); 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_INT); 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; } //maat 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_json_switch==1) { Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_JSON_FILE_PATH, KNI_MAATJSON_FILEPATH,strlen(KNI_MAATJSON_FILEPATH)); } else { 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)); } 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); if((g_kni_maatinfo.tableid_ip<0)||(g_kni_maatinfo.tableid_domain<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; } //init htable ret=init_kni_stat_htable(); if(ret<0) { return -1; } //init lqueue for send fds g_kni_structinfo.lqueue_for_domain=MESA_lqueue_create(KNI_THREAD_SAFE,KNI_LQUEUE_MAXNUM); if(g_kni_structinfo.lqueue_for_domain==NULL) { printf("MESA_lqueue_create() error!\n"); return -1; } //init tun g_kni_comminfo.thread_num=g_iThreadNum; if(g_kni_comminfo.thread_num<=0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"thread_num:%d,action:%s",g_kni_comminfo.thread_num,KNI_ACTION_EXIT); return -1; } g_kni_comminfo.fd_tun=(int*)malloc(g_kni_comminfo.thread_num*sizeof(int)); memset(g_kni_comminfo.fd_tun,0,sizeof(g_kni_comminfo.thread_num*sizeof(int))); ret=tun_alloc_mq(g_kni_comminfo.tun_name,g_kni_comminfo.thread_num,g_kni_comminfo.fd_tun); if(ret<0) { return -1; } // system("ifconfig tun0 192.168.100.1 up"); // system("route add default dev tun0"); // system("iptables -t mangle -A PREROUTING -p tcp -i tun0 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 50080"); #ifndef KNI_DEBUG_TCPREPAIR //init domain g_kni_comminfo.fd_domain=init_domain_fd(); if(g_kni_comminfo.fd_domain<0) { g_kni_comminfo.kni_mode_cur=KNI_MODE_BYPASS; MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd()error"); } pthread_create(&pid_pro_domain,NULL,kni_process_domain,NULL); // pthread_create(&pid_kni_filestat2,NULL,kni_filestat2,NULL); #endif //test init raw_socket kni_read_cardname(); g_kni_comminfo.ipv4_fd=(int*)malloc(g_kni_comminfo.thread_num*sizeof(int)); for(i=0;i