www.pudn.com > NETINFO.rar > netinfoClass.cpp


///////////////////////////////////////////////////////////////////////////////////////// 
//defines 
#define HASH_TABLE_SIZE 1001 
 
#define SNAPLEN 1800 
#define PACKET_BUFFER_SIZE 1800 
 
#define PCAP_BUFFER_SIZE 4000000 
 
#define PCAP_TIMEOUT_CONTROL 1 
#define PCAP_TIMEOUT_CAPTURE 1 
 
#define CONNECT_CHECK_TIMEOUT_INTERVAL 30 
#define TEMPACL_CHECK_TIMEOUT_INTERVAL 2 
 
//delete connections which haven't a packet for a period  
//to make the memory dons't been exhausted  
void CheckConnectionTimeout(NetInfo* pNi) 
{ 
	//clearup existing CConnection 
	POSITION pos = pNi->m_hashTbl->GetStartPosition();//返回一个position值,该值可以在一个映射遍历中传递给GetNextAssoc调用 
	//与CMap有关,将唯一键映射成值,p195 
	while( pos!=NULL ) 
	{ 
		SOCKET_KEY key; 
		CConnection* pConnect; 
//void GetNextAssoc( POSITION& rNextPosition, KEY& rKey, VALUE& rValue ) const; 
//修改rNextPosition,引用映射中下一个元素,用来遍历映射中的所有元素 
		pNi->m_hashTbl->GetNextAssoc(pos, key, pConnect); 
		if( pConnect->IsTimeOut() ) 
		{ 
			printf("%d (%d) - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d [TempAcl=%d] timeout\n", pNi->m_hashTbl->GetCount()-1, CConnection::m_dwConnectCount-1,   
					pConnect->m_addr[pConnect->m_connecter].ip.b1, pConnect->m_addr[pConnect->m_connecter].ip.b2, pConnect->m_addr[pConnect->m_connecter].ip.b3, pConnect->m_addr[pConnect->m_connecter].ip.b4, pConnect->m_addr[pConnect->m_connecter].port,  
					pConnect->m_addr[pConnect->m_listener].ip.b1, pConnect->m_addr[pConnect->m_listener].ip.b2, pConnect->m_addr[pConnect->m_listener].ip.b3, pConnect->m_addr[pConnect->m_listener].ip.b4, pConnect->m_addr[pConnect->m_listener].port, 
					pNi->m_pTempAcl->GetCount() ); 
			delete pConnect; 
			pNi->m_hashTbl->RemoveKey(key); 
		} 
	} 
} 
 
//delete temp acl items which has been timeout 
//to make the memory dons't been exhausted  
void CheckTempAclTimeout(CPtrList *pTempAcl) 
{ 
	if( !pTempAcl ) 
		return; 
	time_t curTime = time(NULL); 
	POSITION pos1, pos2; 
	for(pos1 = pTempAcl->GetHeadPosition(); (pos2 = pos1) != NULL; ) 
	{ 
		ACL_ITEM *pItem = (ACL_ITEM *)pTempAcl->GetNext( pos1 ); 
		if( curTime > pItem->validUntil ) 
		{ 
			pTempAcl->RemoveAt(pos2); 
			delete pItem; 
		} 
	} 
} 
 
//////////////////////////////////////////////////////////////////////////////////////////// 
//dispatcher function used by pcap 
void NetInfo_handler(u_char *user, const struct pcap_pkthdr *header, const u_char *pkt_data) 
{ 
	NetInfo *pNi =(NetInfo*)user; 
 
	//check if it should exit 
	if( pNi->m_bShouldExit ) 
//netinfoclass.h BOOL m_bShouldExit; 
		ExitThread(0); 
//DWORD m_dwPcapEnterCount 
	pNi->m_dwPcapEnterCount++; 
 
	//copy data to my own buffer for modify 
//#define PACKET_BUFFER_SIZE 1800 
	BYTE buffer[PACKET_BUFFER_SIZE]; 
//assert:Evaluates an expression and when the result is FALSE, 
//prints a diagnostic message and aborts the program 
	assert(PACKET_BUFFER_SIZE >= header->caplen && header->caplen == header->len ); 
	memcpy(buffer, pkt_data, header->caplen); 
 
	//send the packet to the output network adapter 
	if( pNi->m_pOutputPcap ) 
//此为winpcap的函数,暂不考虑研究 
		pcap_sendpacket(pNi->m_pOutputPcap, buffer, header->caplen); 
 
	//save the packet to the dump file 
	if( pNi->m_pDumpFile ) 
		pcap_dump((BYTE*)pNi->m_pDumpFile, header, pkt_data); 
 
	//notity user raw packet data 
	//NETINFO_CALLBACKS m_funcs是netinfo的成员变量 
	if( pNi->m_funcs.OnRawPacket ) 
//void (*OnRawPacket)(HNETINFO hNi, const BYTE* pData, DWORD length); 
		pNi->m_funcs.OnRawPacket(pNi, pkt_data, header->caplen); 
 
	//just return when g_bDoNothing is TRUE 
	if( pNi->m_bDoNothing ) 
	{ 
		pNi->m_dwPcapEnterCount--; 
		return; 
	} 
 
	//check connection timeout 
	time_t curTime = time(NULL); 
	if( (DWORD)(curTime - pNi->m_lastConnectCheckTime) > CONNECT_CHECK_TIMEOUT_INTERVAL ) 
	{ 
		CheckConnectionTimeout(pNi); 
		pNi->m_lastConnectCheckTime = time(NULL); 
	} 
 
	//check temp acl item time out 
	//什么意思??? 
	if( (DWORD)(curTime - pNi->m_lastTempAclCheckTime) > TEMPACL_CHECK_TIMEOUT_INTERVAL ) 
	{ 
		CheckTempAclTimeout(pNi->m_pTempAcl); 
		pNi->m_lastTempAclCheckTime = time(NULL); 
	} 
 
 
	//analyse packet 
	//tcpip.h:struct ETHERNET 
	ETHERNET *ether =(ETHERNET*)buffer; 
	IP *ip = NULL; 
	TCP *tcp = NULL; 
	UDP *udp = NULL; 
	WORD tcpDataLen; 
	BOOL bIsNeatIp = FALSE; 
	//#define ETHER_PROTOCOL_IP 8 
	if( ether->protocol == ETHER_PROTOCOL_IP ) 
	{ 
		ip = (IP*)((BYTE*)ether + sizeof(*ether)); 
		IpNtoh(ip); 
//WORD mf : 1;  //more fragment 
		if( ip->mf ) 
		{ 
			//printf("I have found IP packet with fragments!!!\n"); 
		} 
		if( ip->v == 4 	 
			&& ip->mf == 0 
			&& ip->offset == 0 ) 
		{ 
			bIsNeatIp = TRUE; 
		} 
	} 
 
	//only process non-fragment IP packet 
	if( !bIsNeatIp ) 
	{ 
		pNi->m_dwPcapEnterCount--; 
		return; 
	} 
 
 
	//convert udp from network format to host format 
	if( ip->protocol == IP_PROTOCOL_UDP  ) 
	{ 
		udp = (UDP*)( (BYTE*)ip + 4 * ip->hl ); 
		UdpNtoh(udp); 
//#define PORT_DNS 53 
		if( udp->dstPort == PORT_DNS || udp->srcPort == PORT_DNS ) 
		{ 
			FAKE_DNS_ENTRY *pEntry = NULL; 
            //retVal是shouldfakedns的返回值 
			if( pNi->m_pDns && ShouldFakeDns(ip, udp, (BYTE*)(udp+1), pNi->m_pDns, &pEntry) ) 
			{ 
				BYTE dnsBuffer[65535]; 
				DWORD length;//BOOL m_bInputIsFile 
				if(!pNi->m_bInputIsFile && MakeFakeDnsReply(ether, ip, udp, (BYTE*)(udp+1), pEntry, dnsBuffer, sizeof(dnsBuffer), &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, dnsBuffer, length); 
				//printf("Fake DNS: %d.%d.%d.%d %s--->%d.%d.%d.%d\n",  
				//	ip->src.b1, ip->src.b2, ip->src.b3, ip->src.b4, pEntry->labelList,  
				//	pEntry->addrFake.b1, pEntry->addrFake.b2, pEntry->addrFake.b3, pEntry->addrFake.b4 ); 
			} 
		} 
 
		pNi->m_dwPcapEnterCount--; 
		return; 
	} 
	 
	//convert tcp from network format to host format 
	if( ip->protocol == IP_PROTOCOL_TCP ) 
	{ 
		tcp = (TCP*)( (BYTE*)ip + 4 * ip->hl ); 
		TcpNtoh(tcp); 
		tcpDataLen = ip->len - 4 * (ip->hl + tcp->hl); 
	} 
	else 
	{ 
		pNi->m_dwPcapEnterCount--; 
		return; 
	} 
 
	//control network according to ACL.TXT 
	if( pNi->m_pAcl || pNi->m_pTempAcl )		 
	{ 
		if( TcpShouldDeny(pNi->m_pAcl, ip, tcp) || TcpShouldDeny(pNi->m_pTempAcl, ip, tcp) ) 
		{ 
			BYTE rstBuffer[MAX_TCP_PACKET]; 
			DWORD length; 
			if ( tcp->syn && !tcp->ack )  
			{ 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, TRUE) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//if(!pNi->m_bInputIsFile &&  MakeICMPUnreachablePacket(ether, ip, (BYTE*)pkt_data + sizeof(ETHERNET), ip->hl*4 + 8, rstBuffer, sizeof(rstBuffer), &length) ) 
				//	pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//printf("%d.%d.%d.%d:%d-->%d.%d.%d.%d:%d denied\n",  
				//		ip->src.b1, ip->src.b2, ip->src.b3, ip->src.b4, tcp->srcPort, 
				//		ip->dst.b1, ip->dst.b2, ip->dst.b3, ip->dst.b4, tcp->dstPort); 
				pNi->m_dwPcapEnterCount--; 
				return; 
			} 
			else if( !tcp->syn && !tcp->rst && !tcp->fin ) 
			{ 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
				//	pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, FALSE, TRUE) ) 
				//	pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, FALSE, TRUE) ) 
				//	pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//printf("%d.%d.%d.%d:%d-->%d.%d.%d.%d:%d denied\n",  
				//		ip->src.b1, ip->src.b2, ip->src.b3, ip->src.b4, tcp->srcPort, 
				//		ip->dst.b1, ip->dst.b2, ip->dst.b3, ip->dst.b4, tcp->dstPort); 
				pNi->m_dwPcapEnterCount--; 
				return; 
			} 
			else if( tcp->syn && tcp->ack ) 
			{ 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				if(!pNi->m_bInputIsFile &&  MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(pNi->m_pInputPcap, rstBuffer, length); 
				//printf("%d.%d.%d.%d:%d-->%d.%d.%d.%d:%d denied\n",  
				//		ip->dst.b1, ip->dst.b2, ip->dst.b3, ip->dst.b4, tcp->dstPort, 
				//		ip->src.b1, ip->src.b2, ip->src.b3, ip->src.b4, tcp->srcPort); 
				pNi->m_dwPcapEnterCount--; 
				return; 
			} 
		} 
	} 
 
	//calculate key 
	SOCKET_KEY key; 
	DWORD dwSrc; 
	TcpIp2TcpAddr(ip, tcp, key.addr, &dwSrc); 
	 
	//lookup it in hash table 
	CConnection* pConnect; 
	if( pNi->m_hashTbl->Lookup(key, pConnect) )	//already exist 
	{ 
		if( !pConnect->OnTcpIpPacket(ip) ) //this connection should been closed 
		{ 
			printf("%d (%d) - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d [TempAcl=%d]\n", pNi->m_hashTbl->GetCount()-1,  CConnection::m_dwConnectCount-1,  
					pConnect->m_addr[pConnect->m_connecter].ip.b1, pConnect->m_addr[pConnect->m_connecter].ip.b2, pConnect->m_addr[pConnect->m_connecter].ip.b3, pConnect->m_addr[pConnect->m_connecter].ip.b4, pConnect->m_addr[pConnect->m_connecter].port,  
					pConnect->m_addr[pConnect->m_listener].ip.b1, pConnect->m_addr[pConnect->m_listener].ip.b2, pConnect->m_addr[pConnect->m_listener].ip.b3, pConnect->m_addr[pConnect->m_listener].ip.b4, pConnect->m_addr[pConnect->m_listener].port,  
					pNi->m_pTempAcl->GetCount() ); 
			delete pConnect; 
			pNi->m_hashTbl->RemoveKey(key); 
		} 
	} 
	else //connection not exist before 
	{ 
		//a synchronous and ankownledge packet 
		if( tcp->syn && tcp->ack ) 
		{ 
			pConnect = NULL; 
			enum CONNECT_TYPE connectType = INVALID_CONNECT;	 
			DWORD dwAttachData = 0; 
			CFtpConnection* pFtp = NULL; 
			if( FindMatch(pNi->m_pFtpDataMatchList, ip, tcp, &pFtp) ) 
				pConnect = new CFtpDataConnection(pFtp, ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
			else if( pNi->m_funcs.OnOpenConnect  
				&& pNi->m_funcs.OnOpenConnect(pNi, &key.addr[(dwSrc+1)%2], &key.addr[dwSrc], &connectType, &dwAttachData) ) 
			{ 
				if( connectType == TCP_CONNECT ) 
					pConnect = new CConnection(ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
				else if( connectType == LINE_CONNECT ) 
					pConnect = new CLineConnection(ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
				else if( connectType == FTP_CONNECT ) 
					pConnect = new CFtpConnection(pNi->m_hashTbl, pNi->m_pFtpDataMatchList, 
												ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
				else if( connectType == HTTP_CONNECT ) 
					pConnect = new CHttpConnection(ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
				else if( connectType == SMTP_CONNECT ) 
					pConnect = new CSmtpConnection(ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
				else if( connectType == POP3_CONNECT ) 
					pConnect = new CPop3Connection(ether, ip, pNi, &pNi->m_funcs, dwAttachData); 
			} 
 
			if( pConnect ) 
			{ 
				pNi->m_hashTbl->SetAt(key, pConnect); 
				printf("%d (%d) + %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d [TempAcl=%d]\n", pNi->m_hashTbl->GetCount(), CConnection::m_dwConnectCount, 
						pConnect->m_addr[pConnect->m_connecter].ip.b1, pConnect->m_addr[pConnect->m_connecter].ip.b2, pConnect->m_addr[pConnect->m_connecter].ip.b3, pConnect->m_addr[pConnect->m_connecter].ip.b4, pConnect->m_addr[pConnect->m_connecter].port,  
						pConnect->m_addr[pConnect->m_listener].ip.b1, pConnect->m_addr[pConnect->m_listener].ip.b2, pConnect->m_addr[pConnect->m_listener].ip.b3, pConnect->m_addr[pConnect->m_listener].ip.b4, pConnect->m_addr[pConnect->m_listener].port,  
						pNi->m_pTempAcl->GetCount() ); 
			} 
		} 
	} 
	pNi->m_dwPcapEnterCount--; 
} 
 
//循环线程 
DWORD WINAPI PcapLoopThread( LPVOID lpParameter ) 
{ 
	NetInfo *pNi = (NetInfo*)lpParameter; 
	pcap_loop(pNi->m_pInputPcap, 0, NetInfo_handler, (unsigned char*)lpParameter); 
	return 0; 
} 
 
//打开和关闭网络适配器的调用接口 
 
 
 
//adapterString为从GetAdapterString()得到的返回值, 
//dwAttachData是网络适配器的附加数据 
//funcs是回调函数接口 
HNETINFO OpenAdapter(BOOL bInputIsFile, const void* inputString, 
					 const char* outputFileString, const void* outputAdapterString, 
					 char* szPcapFilter, const char* szAclFile, const char* szDnsFile,  
					 BOOL bDoNothing, const NETINFO_CALLBACKS *funcs) 
{ 
	char error[PCAP_ERRBUF_SIZE]; 
	NetInfo *pNetInfo = new NetInfo; 
	if( !pNetInfo )  
	{ 
		printf("allocate memory for HNETINFO failed!\n"); 
		goto FAIL_POINT; 
	} 
	memset(pNetInfo, 0, sizeof(NetInfo)); 
//将各变量,指针初始化为0 
	 
	if( !inputString ) 
	{ 
		printf("inputString must be specified!\n"); 
		goto FAIL_POINT; 
	} 
 
	//open input pcap device 
	if( bInputIsFile ) 
	{ 
		pNetInfo->m_bInputIsFile = TRUE; 
		pNetInfo->m_pInputPcap = pcap_open_offline((const char*)inputString, NULL); 
		if( !pNetInfo->m_pInputPcap ) 
		{ 
			if( !ExistFile((const char*)inputString) ) 
				printf("%s doesn't exist!\n", inputString); 
			else 
				printf("%s cannot be opened!\n", inputString); 
			goto FAIL_POINT; 
		} 
	} 
	else 
	{ 
		pNetInfo->m_pInputPcap= pcap_open_live((char*)inputString, SNAPLEN, 1, PCAP_TIMEOUT_CAPTURE, error); 
		if( !pNetInfo->m_pInputPcap ) 
		{ 
			printf("%s cannot be opened!\n", inputString); 
			goto FAIL_POINT; 
		} 
		pcap_setbuff(pNetInfo->m_pInputPcap, PCAP_BUFFER_SIZE); 
	} 
 
	//open output pcap device 
	if( outputAdapterString ) 
	{ 
		pNetInfo->m_pOutputPcap= pcap_open_live((char*)outputAdapterString, SNAPLEN, 1, PCAP_TIMEOUT_CAPTURE, error); 
		if( !pNetInfo->m_pOutputPcap ) 
		{ 
			printf("%s cannot be opened!\n", outputAdapterString); 
			goto FAIL_POINT; 
		} 
		pcap_setbuff(pNetInfo->m_pOutputPcap, PCAP_BUFFER_SIZE); 
	} 
 
	//open dump file 
	if( outputFileString ) 
	{ 
		pNetInfo->m_pDumpFile=pcap_dump_open(pNetInfo->m_pInputPcap, outputFileString); 
		if( !pNetInfo->m_pDumpFile ) 
		{ 
			printf("%s cannot be created!\n", outputFileString); 
			goto FAIL_POINT; 
		} 
	} 
 
	//set pcap filter 
	if( szPcapFilter ) 
	{ 
		//obtain the subnet and netmask 
		struct bpf_program fcode; 
		bpf_u_int32 netMask; 
		netMask = 0xffffff;//c class network mask 
		//compile the filter 
		if( pcap_compile(pNetInfo->m_pInputPcap, &fcode, szPcapFilter, 1, netMask) == -1 ) 
		{ 
			printf("pcap fileter systax error: %s\n", szPcapFilter); 
			goto FAIL_POINT; 
		} 
		//set the filter 
		if( pcap_setfilter(pNetInfo->m_pInputPcap, &fcode) == -1 ) 
		{ 
			printf("pcap_setfileter failed: %s\n", szPcapFilter); 
			goto FAIL_POINT; 
		} 
	} 
 
	//set acl list 
	if( szAclFile ) 
	{ 
		if( !ExistFile(szAclFile) ) 
		{ 
			printf("%s doesn't exist!\n", szAclFile); 
			goto FAIL_POINT; 
		} 
		pNetInfo->m_pAcl = new CPtrList; 
		if( !LoadAcl(szAclFile, pNetInfo->m_pAcl) ) 
		{ 
			printf("%s has systax error!\n", szAclFile); 
			goto FAIL_POINT; 
		} 
	} 
 
	//create temp acl list 
	pNetInfo->m_pTempAcl = new CPtrList; 
 
	//set dns list 
	if( szDnsFile ) 
	{ 
		if( !ExistFile(szDnsFile) ) 
		{ 
			printf("%s doesn't exist!\n", szDnsFile);//printf szdnsfile not exist 
			goto FAIL_POINT; 
		} 
		pNetInfo->m_pDns = new CPtrList; 
		if( !LoadDnsFakeList(szDnsFile, pNetInfo->m_pDns) ) 
		{ 
			printf("%s has systax error!\n", szDnsFile); 
			goto FAIL_POINT; 
		} 
	} 
 
	//create hash table to contain tcp connection 
	pNetInfo->m_hashTbl = new CMapKeyToConnect(100); 
	pNetInfo->m_hashTbl->InitHashTable(HASH_TABLE_SIZE); 
 
	//create FTP数据连接检查对象 
	pNetInfo->m_pFtpDataMatchList = new CFtpDataMatchList; 
 
	//other parameter 
	pNetInfo->m_bDoNothing = bDoNothing; 
 
	//用户数据 
	memset(&pNetInfo->m_funcs, 0, sizeof(pNetInfo->m_funcs)); 
	if( funcs ) 
		pNetInfo->m_funcs = *funcs; 
 
	//返回指针 
	return pNetInfo; 
 
	//失败返回点 
FAIL_POINT: 
	if( pNetInfo ) 
		CloseAdapter(pNetInfo); 
	pNetInfo = NULL; 
	return pNetInfo; 
} 
 
      
//会启动监听和解码主循环线程 
void StartAdapter(HNETINFO hNi) 
{ 
	DWORD threadId; 
	hNi->m_hLoopThread = CreateThread(NULL, 0, PcapLoopThread, hNi, 0, &threadId); 
} 
 
//检测监听和解码主循环线程是否已经退出 
BOOL AdapterIsStopped(HNETINFO hNi) 
{ 
	DWORD dwExitCode; 
   	//BOOL GetExitCodeThread(HANDLE hThread,// handle to the thread  LPDWORD lpExitCode // termination status 
    //dwExitCode Pointer to a variable to receive the thread termination status                 
	//The GetExitCodeThread function retrieves the termination status of the specified thread 
	if( !hNi || !(hNi->m_hLoopThread) || (GetExitCodeThread(hNi->m_hLoopThread, &dwExitCode) && dwExitCode != STILL_ACTIVE) )  
		return TRUE; 
	else 
		return FALSE; 
} 
 
//会停止监听和解码主循环线程 
void StopAdapter(HNETINFO hNi) 
{ 
	if( AdapterIsStopped(hNi) )return; 
	hNi->m_bShouldExit = TRUE; 
	while( WaitForSingleObject(hNi->m_hLoopThread, 0)==WAIT_TIMEOUT && hNi->m_dwPcapEnterCount!=0 )NULL; 
	TerminateThread(hNi->m_hLoopThread, 0); 
	CloseHandle(hNi->m_hLoopThread); 
	hNi->m_hLoopThread = NULL; 
} 
 
//关闭hNi所代表的网络适配器资源 
void CloseAdapter(HNETINFO hNi) 
{ 
	//停止线程 
	StopAdapter(hNi); 
 
	//delete objects to release resources 
	if( hNi->m_pInputPcap )  
		pcap_close(hNi->m_pInputPcap); 
 
	if( hNi->m_pOutputPcap )  
		pcap_close(hNi->m_pOutputPcap); 
 
	if( hNi->m_pDumpFile )  
		pcap_dump_close(hNi->m_pDumpFile); 
 
	if( hNi->m_pAcl ) 
	{ 
		ClearAcl( hNi->m_pAcl ); 
		delete hNi->m_pAcl; 
	} 
 
	if( hNi->m_pTempAcl ) 
	{ 
		ClearAcl( hNi->m_pTempAcl ); 
		delete hNi->m_pTempAcl; 
	} 
 
	if( hNi->m_pDns ) 
	{ 
		ClearFakeDnsList( hNi->m_pDns); 
		delete hNi->m_pDns; 
	} 
 
	if( hNi->m_hashTbl ) 
	{ 
		POSITION pos = hNi->m_hashTbl->GetStartPosition(); 
		while( pos!=NULL ) 
		{ 
			SOCKET_KEY key; 
			CConnection* pConnect; 
			hNi->m_hashTbl->GetNextAssoc(pos, key, pConnect); 
			printf("%d (%d) - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d \n", hNi->m_hashTbl->GetCount()-1 ,  CConnection::m_dwConnectCount-1,  
					pConnect->m_addr[pConnect->m_connecter].ip.b1, pConnect->m_addr[pConnect->m_connecter].ip.b2, pConnect->m_addr[pConnect->m_connecter].ip.b3, pConnect->m_addr[pConnect->m_connecter].ip.b4, pConnect->m_addr[pConnect->m_connecter].port,  
					pConnect->m_addr[pConnect->m_listener].ip.b1, pConnect->m_addr[pConnect->m_listener].ip.b2, pConnect->m_addr[pConnect->m_listener].ip.b3, pConnect->m_addr[pConnect->m_listener].ip.b4, pConnect->m_addr[pConnect->m_listener].port ); 
			delete pConnect; 
			hNi->m_hashTbl->RemoveKey(key); 
		} 
		hNi->m_hashTbl->RemoveAll(); 
		delete hNi->m_hashTbl; 
	} 
 
	if( hNi->m_pFtpDataMatchList ) 
		delete hNi->m_pFtpDataMatchList; 
 
	//clear data 
	memset(hNi, 0, sizeof(NetInfo)); 
 
	//release memory 
	delete hNi; 
} 
 
void SetAdapterAttachData(HNETINFO hNi, DWORD dwAttachData) 
{ 
	hNi->m_dwAttachData = dwAttachData; 
} 
 
DWORD GetAdapterAttachData(HNETINFO hNi) 
{ 
	return hNi->m_dwAttachData; 
} 
 
DWORD GetAdapterConnectCount(HNETINFO hNi) 
{ 
	return hNi->m_hashTbl->GetCount(); 
} 
 
void AddTempAclItem(HNETINFO hNi, const ACL_ITEM *pItem) 
{ 
	ACL_ITEM *item = new ACL_ITEM; 
	*item = *pItem; 
	hNi->m_pTempAcl->AddHead(item); 
} 
 
BOOL AdapterSendPacket(HNETINFO hNi, BOOL bInputAdapter, const BYTE*pData, DWORD length) 
{ 
	pcap_t *pPcap = NULL; 
	if( hNi ) 
	{ 
		if( bInputAdapter && !hNi->m_bInputIsFile ) 
			pPcap = hNi->m_pInputPcap; 
		else 
			pPcap = hNi->m_pOutputPcap; 
	} 
	if( pPcap ) 
	{ 
		pcap_sendpacket(pPcap, (BYTE*)pData, length); 
		return TRUE; 
	} 
	else 
		return FALSE; 
}