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


#include  
#include  
#include  
#include  
#include 
#include  
#include  
#include  
#include "tools.h" 
#include "commonDefine.h" 
#include "collectLine.h" 
#include "adapList.h" 
#include "pcap.h"
#include "tcpip.h" 
#include "udp.h" 
#include "connect.h" 
#include "lineConnect.h" 
#include "ToolConnect.h" 
#include "EmailAnalyse.h" 
#include "pop3_new.h" 
#include "smtp_new.h" 
#include "ftp.h" 
#include "http.h" 
#include "acl.h" 
#include "dns.h" 
 
///////////////////////////////////////////////////////////////////////////////////////// 
//defines 
#define HASH_TABLE_SIZE 1001 
#define SNAPLEN 1800 
#define PCAP_BUFFER_SIZE 4000000 
#define PCAP_TIMEOUT_CONTROL 1 
#define PCAP_TIMEOUT_CAPTURE 20 
#define CHECK_TIMEOUT_INTERVAL 30 
///////////////////////////////////////////////////////////////////////////////////////// 
//global variables 
 
//directory for each protocols 
char g_szWorkDir[MAX_PATH]; 
char g_szPop3Dir[MAX_PATH]; 
char g_szSmtpDir[MAX_PATH]; 
char g_szFtpDir[MAX_PATH]; 
char g_szTempDir[MAX_PATH]; 
char g_szTxtPrintDir[MAX_PATH]; 
char g_szUdpDir[MAX_PATH]; 
char g_szHttpDir[MAX_PATH]; 
char g_szLogFile[MAX_PATH]; 
 
//argvs determined variables 
BOOL g_bControlLAN = FALSE; 
BOOL g_bFakeDns = FALSE; 
BOOL g_bUseInputFile = FALSE; 
BOOL g_bSaveRawContent = FALSE; 
WORD g_wTcpListenPort = 0; 
BOOL g_bCaptureUdp = FALSE; 
WORD g_wUdpListenPort = 0; 
BOOL g_bOnlyShow = FALSE; 
BOOL g_bDoNothing = FALSE; 
BOOL g_bAllConnectionSaved = FALSE; 
BOOL g_bWriteLogFile = FALSE; 
 
//objects 
pcap_t *g_pInputPcap = NULL; 
pcap_t *g_pOutputPcap = NULL; 
pcap_dumper_t *g_pDumpFile = NULL; 
CMapKeyToConnect* g_hashTbl = NULL; 
CFtpDataMatchList* g_pFtpDataMatchList = NULL; 
CPtrList *g_pAcl = NULL; 
CPtrList *g_pFakeDns = NULL; 
 
//synchronous variables 
BOOL g_bShouldExit = FALSE; 
DWORD g_dwPcapEnterCount = 0; 
 
//check timeout variables 
time_t g_lastCheckTime = 0; 
 
 
////////////////////////////////////////////////////////////////////////////////////////// 
//delete connections that has timeout 
void CheckConnectionTimeout() 
{ 
	//clearup existing CConnection 
	POSITION pos = g_hashTbl->GetStartPosition(); 
	while( pos!=NULL ) 
	{ 
		SOCKET_KEY key; 
		CConnection* pConnect; 
		g_hashTbl->GetNextAssoc(pos, key, pConnect); 
		if( pConnect->IsTimeOut() ) 
		{ 
			printf("%d - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d timeout\n", g_hashTbl->GetCount()-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; 
			g_hashTbl->RemoveKey(key); 
		} 
	} 
} 
 
 
//////////////////////////////////////////////////////////////////////////////////////////// 
//dispatcher function used by pcap
void another_handler(u_char *user, const struct pcap_pkthdr *header, const u_char *pkt_data) 
{ 
	//check if it's time to exit 
	if( g_bShouldExit ) 
		ExitThread(0); 
	g_dwPcapEnterCount++; 
 
	//copy data to my own buffer for modify 
	BYTE buffer[BUFFER_SIZE]; 
	assert(BUFFER_SIZE >= header->caplen && header->caplen == header->len ); 
	memcpy(buffer, pkt_data, header->caplen); 
 
	//send the packet to the output network adapter 
	if( g_pOutputPcap ) 
		pcap_sendpacket(g_pOutputPcap, buffer, header->caplen); 
 
	//save the packet to the dump file 
	if( g_pDumpFile ) 
		pcap_dump((BYTE*)g_pDumpFile, header, pkt_data); 
 
	//just return when g_bDoNothing is TRUE 
	if( g_bDoNothing ) 
	{ 
		g_dwPcapEnterCount--; 
		return; 
	} 
 
	//analyse packet 
	ETHERNET *ether =(ETHERNET*)buffer; 
	IP *ip = NULL; 
	TCP *tcp = NULL; 
	UDP *udp = NULL; 
	WORD tcpDataLen; 
	BOOL bIsNeatIp = FALSE; 
	if( ether->protocol == ETHER_PROTOCOL_IP ) 
	{ 
		ip = (IP*)((BYTE*)ether + sizeof(*ether)); 
		IpNtoh(ip); 
		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 ) 
	{ 
		g_dwPcapEnterCount--; 
		return; 
	} 
 
	//check connection timeout 
	time_t curTime = time(NULL); 
	if( (DWORD)(curTime - g_lastCheckTime) > CHECK_TIMEOUT_INTERVAL ) 
	{ 
		CheckConnectionTimeout(); 
		g_lastCheckTime = time(NULL); 
	} 
 
	//convert udp from network format to host format 
	if( ip->protocol == IP_PROTOCOL_UDP  ) 
	{ 
		udp = (UDP*)( (BYTE*)ip + 4 * ip->hl ); 
		UdpNtoh(udp); 
		if( udp->dstPort == PORT_DNS || udp->srcPort == PORT_DNS ) 
		{ 
			FAKE_DNS_ENTRY *pEntry = NULL; 
			if( g_bFakeDns && g_pFakeDns  
				&& ShouldFakeDns(ip, udp, (BYTE*)(udp+1), g_pFakeDns, &pEntry) ) 
			{ 
				BYTE dnsBuffer[65535]; 
				DWORD length; 
				if( MakeFakeDnsReply(ether, ip, udp, (BYTE*)(udp+1), pEntry, dnsBuffer, sizeof(dnsBuffer), &length) ) 
					pcap_sendpacket(g_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 ); 
			} 
		} 
 
		if( g_bControlLAN ) 
		{ 
			//if( UdpShouldDeny(g_pAcl, ip, udp) ) 
			//{ 
			//	BYTE icmpBuffer[MAX_TCP_PACKET]; 
			//	DWORD length; 
			//	if( MakeICMPUnreachablePacket(ether, ip, (BYTE*)pkt_data + sizeof(ETHERNET), ip->hl*4 + 8, icmpBuffer, sizeof(icmpBuffer), &length) ) 
			//		pcap_sendpacket(g_pInputPcap, icmpBuffer, length); 
			//} 
		} 
		else if( g_bCaptureUdp ) 
		{ 
			if( g_wUdpListenPort == 0 || ( udp->dstPort == g_wUdpListenPort || udp->srcPort == g_wUdpListenPort ) ) 
				ProcessUDP(ip, udp); 
		} 
		g_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 
	{ 
		g_dwPcapEnterCount--; 
		return; 
	} 
 
	//control network according to ACL.TXT 
	if(g_bControlLAN )		 
	{ 
		if( TcpShouldDeny(g_pAcl, ip, tcp) ) 
		{ 
			BYTE rstBuffer[MAX_TCP_PACKET]; 
			DWORD length; 
			if ( tcp->syn && !tcp->ack )  
			{ 
				if( MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, TRUE) ) 
					pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				if( MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				if( MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				//if( MakeICMPUnreachablePacket(ether, ip, (BYTE*)pkt_data + sizeof(ETHERNET), ip->hl*4 + 8, rstBuffer, sizeof(rstBuffer), &length) ) 
				//	pcap_sendpacket(g_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); 
				g_dwPcapEnterCount--; 
				return; 
			} 
			else if( !tcp->syn && !tcp->rst && !tcp->fin ) 
			{ 
				if( MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
					pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				//if( MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
				//	pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				//if( MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, FALSE, TRUE) ) 
				//	pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
				//if( MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length, FALSE, TRUE) ) 
				//	pcap_sendpacket(g_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); 
				g_dwPcapEnterCount--; 
				return; 
			} 
		} 
	} 
 
	//calculate key 
	SOCKET_KEY key; 
	TcpIp2TcpAddr(ip, tcp, key.addr); 
	 
	//lookup it in hash table 
	CConnection* pConnect; 
	if( g_hashTbl->Lookup(key, pConnect) )	//already exist 
	{ 
		if( !pConnect->OnTcpIpPacket(ip) ) //this connection has been closed 
		{ 
			printf("%d - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d\n", g_hashTbl->GetCount()-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; 
			g_hashTbl->RemoveKey(key); 
		} 
	} 
	else //connection not exist before 
	{ 
		//a synchronous and ankownledge packet 
		if( tcp->syn && tcp->ack ) 
		{ 
			pConnect = NULL; 
			if( g_bControlLAN ) 
			{ 
				if( TcpShouldDeny(g_pAcl, ip, tcp) ) 
				{ 
					BYTE rstBuffer[MAX_TCP_PACKET]; 
					DWORD length; 
					if( MakeRstTcpPacket(ether, ip, tcp, FALSE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
						pcap_sendpacket(g_pInputPcap, rstBuffer, length); 
					if( MakeRstTcpPacket(ether, ip, tcp, TRUE, tcpDataLen, rstBuffer, MAX_TCP_PACKET, &length) ) 
						pcap_sendpacket(g_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); 
				} 
			} 
			else if( g_bSaveRawContent ) 
			{ 
				if( g_wTcpListenPort == 0 ) 
					pConnect = new CTxtPrintConnection(g_szTxtPrintDir, ip); 
				else 
				{ 
					if( tcp->srcPort == g_wTcpListenPort ) 
						pConnect = new CTxtPrintConnection(g_szTxtPrintDir, ip); 
					else 
						pConnect = new CConnection(ip); 
				} 
			} 
			else if( g_bOnlyShow ) 
			{ 
				pConnect = new CConnection(ip); 
			} 
			else 
			{ 
				CFtpConnection* pFtp = NULL; 
				if( FindMatch(g_pFtpDataMatchList, ip, tcp, &pFtp) ) 
					pConnect = new CFtpDataConnection(pFtp, ip); 
				else if( tcp->srcPort == TCP_PORT_HTTP || tcp->srcPort == 8080 || tcp->srcPort == 3128 ) 
					pConnect = new CHttpConnection(g_szHttpDir, g_szTempDir, ip); 
				else if( tcp->srcPort == TCP_PORT_POP3 ) 
					pConnect = new CPop3Connection(g_szPop3Dir, g_szTempDir, ip); 
				else if( tcp->srcPort == TCP_PORT_SMTP ) 
					pConnect = new CSmtpConnection(g_szSmtpDir, g_szTempDir, ip); 
				else if( tcp->srcPort == TCP_PORT_FTP ) 
					pConnect = new CFtpConnection(g_hashTbl, g_pFtpDataMatchList, g_szFtpDir, ip); 
				else if( g_bAllConnectionSaved ) 
					pConnect = new CTxtPrintConnection(g_szTxtPrintDir, ip); 
				else 
					pConnect = new CConnection(ip); 
			} 
 
			if( pConnect ) 
			{ 
				g_hashTbl->SetAt(key, pConnect); 
				printf("%d + %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d\n", g_hashTbl->GetCount(),   
						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 ); 
			} 
		} 
	} 
	g_dwPcapEnterCount--; 
} 
 
 
//////////////////////////////////////////////////////////////////////////////////////////// 
//another dispatcher function used by pcap 
void dispatcher_handler(u_char *user, const struct pcap_pkthdr *header, const u_char *pkt_data)
{ 
	DWORD i; 
 
	//copy data to my own buffer for modify
	BYTE buffer[BUFFER_SIZE]; 
	assert(BUFFER_SIZE >= header->caplen && header->caplen == header->len ); 
	memcpy(buffer, pkt_data, header->caplen); 
 
	ETHERNET *ether =(ETHERNET*)buffer; 
	IP *ip = NULL; 
	TCP *tcp = NULL; 
	BOOL bIsNeatIpTcp = FALSE; 
	if( ether->protocol == ETHER_PROTOCOL_IP ) 
	{ 
		ip = (IP*)((BYTE*)ether + sizeof(*ether)); 
		if( ip->v = 4 && ip->protocol == IP_PROTOCOL_TCP ) 
		{ 
			tcp = (TCP*)( (BYTE*)ip + 4 * ip->hl ); 
			bIsNeatIpTcp = TRUE; 
		} 
	} 
 
	//only process TCP packet 
	if( !bIsNeatIpTcp ) 
		return; 
 
	//print pkt timestamp and pkt len 
	printf("\n\n\n\n%ld:%ld (%ld:%ld)\n", header->ts.tv_sec, header->ts.tv_usec, header->caplen, header->len);			 
 
	//print ethernet header 
	printf("\n[Ethernet header]"); 
	PrintHexByte(stdout, (const BYTE*)ether, sizeof(*ether), MAX_LINE); 
	printf("\nsource address = "); 
	for(i=0; isrc[i])); 
 
	printf("\ndestin address = "); 
	for(i=0; idst[i])); 
 
	printf("\nprotocol = %hu", ether->protocol); 
 
	//process ip header 
	if( ether->protocol == ETHER_PROTOCOL_IP ) 
	{ 
		printf("\n\n[ip header]"); 
		printf("\nsizeof(ip)=%d", sizeof(IP) ); 
		PrintHexByte(stdout, (const BYTE*)ip, sizeof(*ip), MAX_LINE); 
 
		//convert net int and short to local machine 
		IP *ip = (IP*)((BYTE*)ether + sizeof(*ether)); 
		IpNtoh(ip); 
 
		//print ip header 
		printf("\nVersion = %u, headerlen = %u", (DWORD)(ip->v), (DWORD)(ip->hl) ); 
		printf("\ntos = %02X, len = %u, id = %u", (DWORD)(ip->tos), (DWORD)(ip->len), (DWORD)(ip->id) ); 
		printf("\ndf = %u, mf = %u, offset = %u", (DWORD)(ip->df), (DWORD)(ip->mf), (DWORD)(ip->offset) ); 
		printf("\nttl = %u, protocol = %u, checksum = %u(%04X)", (DWORD)(ip->ttl), (DWORD)(ip->protocol), (DWORD)(ip->checksum), (DWORD)(ip->checksum)); 
		printf("\n%u.%u.%u.%u --> %u.%u.%u.%u",  
				ip->src.b1, ip->src.b2, ip->src.b3, ip->src.b4,  
				ip->dst.b1, ip->dst.b2, ip->dst.b3, ip->dst.b4 ); 
 
		if( ip->protocol == IP_PROTOCOL_TCP ) 
		{ 
			printf("\n\n[tcp header]"); 
			printf("\nsizeof(tcp)=%d", sizeof(TCP) ); 
			PrintHexByte(stdout, (const BYTE*)tcp, sizeof(*tcp), MAX_LINE); 
 
			//convert net int and short to local machine  
			TCP *tcp = (TCP*)( (BYTE*)ip + 4 * ip->hl ); 
			TcpNtoh(tcp); 
 
			//print tcp header 
			printf("\nsrcPort = %u, dstPort = %u", tcp->srcPort, tcp->dstPort); 
			printf("\nseqNum = %u,  ackNum = %u", tcp->seqNum,  tcp->ackNum); 
			printf("\nheadLen = %u, urg = %u, ack = %u, psh = %u, rst = %u, syn = %u, fin = %u", 
					tcp->hl, tcp->urg, tcp->ack, tcp->psh, tcp->rst, tcp->syn, tcp->fin); 
			printf("\nwindow = %u, checksum = %u, urgPointer = %u", tcp->window, tcp->checksum, tcp->urgPoint); 
 
			//print tcp data 
			printf("\n\n[tcp data]"); 
			if( ip->mf == 0 && ip->offset == 0 ) 
			{ 
				DWORD headLen = ip->hl * 4 + tcp->hl * 4; 
				DWORD dataLen = ip->len - headLen; 
				BYTE *pData = (BYTE*)ip + headLen; 
				if( dataLen ) 
				{ 
					printf("\ndataLen = %lu", dataLen); 
					PrintHexByte(stdout, pData, dataLen, MAX_LINE); 
					for(i = 0; !iscntrl(pData[i]) && i=0; i--)NULL; 
	i++; 
	memcpy(g_szWorkDir, argv[0], i); 
	g_szWorkDir[i] = 0; 
	sprintf(g_szPop3Dir, "%sPOP3\\", g_szWorkDir); 
	CreateDirectory(g_szPop3Dir, NULL); 
	sprintf(g_szSmtpDir, "%sSMTP\\", g_szWorkDir); 
	CreateDirectory(g_szSmtpDir, NULL); 
	sprintf(g_szFtpDir, "%sFTP\\", g_szWorkDir); 
	CreateDirectory(g_szFtpDir, NULL); 
	sprintf(g_szTempDir, "%sTEMP\\", g_szWorkDir); 
	CreateDirectory(g_szTempDir, NULL); 
	sprintf(g_szTxtPrintDir, "%sTEXT\\", g_szWorkDir); 
	CreateDirectory(g_szTxtPrintDir, NULL); 
	sprintf(g_szUdpDir, "%sUDP\\", g_szWorkDir); 
	CreateDirectory(g_szUdpDir, NULL); 
	sprintf(g_szHttpDir, "%sHTTP\\", g_szWorkDir); 
	CreateDirectory(g_szHttpDir, NULL); 
	sprintf(g_szLogFile, "%sfilelist.txt", g_szWorkDir); 
} 
 
 
DWORD WINAPI PcapLoopThread( LPVOID lpParameter ) 
{ 
	pcap_loop((struct pcap*)lpParameter, 0, another_handler, NULL); 
	return 0; 
} 

void PrintUsage()
{ 
	char error[PCAP_ERRBUF_SIZE]; 
	printf("\nUsage:\n");
	printf("    c.exe [-c [aclFile]] | [-t [TCPport]] [-u [UDPPort]] | [-s] [-i] [-a]\n"); 
	printf("          [-d fakeDnsListFile] [-L]\n"); 
	printf("          <-n input_adapter | -r input_filename>\n"); 
	printf("          [-o output_adapter] [-w output_file] [-p packet_filter_string]\n\n"); 
	printf("-c option means control this LAN by using ACL.TXT or aclFile if aclFile \n"); 
	printf("   parameter exists, and only can be combined with -n\n"); 
	printf("-t option means write raw TCP content to file in text(dir) for learn or debug,\n"); 
	printf("   if TCPport is specified, only the content of connection of port \n"); 
	printf("   will be wrote\n"); 
	printf("-u option means capture all UDP datagrams, writing to files in udp(dir)\n"); 
	printf("   if UDPPort is specified, only UDP of UDPport will be captured\n"); 
	printf("-s option means only show connections, not write to file\n"); 
	printf("-i option means idle( do nothing ), it's used with -r -o -w -p option\n"); 
	printf("-a option means all connections not treated are saved to file in text(dir) \n"); 
	printf("-d means sending fake dns replies as dns server\n"); 
	printf("-L option means write to log file filelist.txt when a file is completely received\n"); 
	printf("-n means get packet from a network adapter\n"); 
	printf("-r means get packet from a file created by a pcap program\n"); 
	printf("-o means write packet to a network adapter\n"); 
	printf("-w means write packet to output_filename\n"); 
	printf("-p applies packet_fileter to winpcap, it must be a quoted string\n\n");	 
	printf("installed adapters:"); 
	PrintAdapter( pcap_lookupdev(error) );
} 
 
 
void main(int argc, char **argv)  
{ 
	DWORD dwInputAdapter = -1; 
	DWORD dwOutputAdapter = -1; 
	char *szInputFile = NULL; 
	char *szOutputFile = NULL; 
	char *szFilter = NULL; 
	char *szAclFile = "acl.txt"; 
	char *szDnsFile = NULL; 
	char error[PCAP_ERRBUF_SIZE]; 
 
	int i=1; 
	while(i= GetAdapterCount(pcap_lookupdev(error)) ) 
		{ 
			printf("adapter is out of range\n"); 
			PrintUsage(); 
			return; 
		} 
		else if ( (g_pInputPcap= pcap_open_live((char*)GetAdapter(pcap_lookupdev(error), dwInputAdapter), SNAPLEN, 1, timeout, error) ) == NULL) 
		{ 
			fprintf(stderr,"\nError opening adapter\n"); 
			return; 
		} 
		pcap_setbuff(g_pInputPcap, PCAP_BUFFER_SIZE); 
	} 
	else if( szInputFile ) //input is pcap dump file 
	{ 
		if( g_bControlLAN ) 
		{ 
			printf("-f parameter cannot be combined with -c option\n"); 
			PrintUsage(); 
			return; 
		} 
		if( !ExistFile(szInputFile) ) 
		{ 
			fprintf(stderr,"\ndump file %s doesn't exist\n", szInputFile); 
			return; 
		} 
		if( (g_pInputPcap = pcap_open_offline(szInputFile, NULL)) == NULL) 
		{ 
			fprintf(stderr,"\nError opening dump file %s\n", szInputFile); 
			return; 
		} 
		g_bUseInputFile = TRUE; 
	} 
	else 
	{ 
		PrintUsage(); 
		return; 
	} 
 
	//open output network 
	if( dwOutputAdapter != -1 )  
	{ 
		if( dwOutputAdapter >= GetAdapterCount(pcap_lookupdev(error)) ) 
		{ 
			printf("output adapter is out of range\n"); 
			PrintUsage(); 
			return; 
		} 
		else if ( (g_pOutputPcap= pcap_open_live((char*)GetAdapter(pcap_lookupdev(error), dwOutputAdapter), SNAPLEN, 1, PCAP_TIMEOUT_CAPTURE, error) ) == NULL) 
		{ 
			fprintf(stderr,"\nError opening output adapter\n"); 
			return; 
		} 
		pcap_setbuff(g_pOutputPcap, PCAP_BUFFER_SIZE); 
	} 
 
	//set input pcap filter 
	struct bpf_program fcode; 
	if(szFilter!=NULL) 
	{ 
		//obtain the subnet and netmask 
		bpf_u_int32 subNet,netMask; 
		if( dwInputAdapter!=-1 ) 
		{ 
			char deviceName[MAX_PATH]; 
			strcpy(deviceName, (char*)GetAdapter(pcap_lookupdev(error), dwInputAdapter)); 
			char *device = deviceName; 
			if(pcap_lookupnet(device, &subNet, &netMask, error)==-1) 
			{ 
				//fprintf(stderr,"\nUnable to obtain the netmask because:\n  %s\n", error); 
				netMask = 0xffffff; //c class network mask 
			} 
		} 
		else 
			netMask = 0xffffff;//c class network mask 
	 
		//compile the filter 
		if(pcap_compile(g_pInputPcap, &fcode, szFilter, 1, netMask)<0) 
		{ 
			fprintf(stderr,"\nError compiling filter: wrong syntax.\n"); 
			return; 
		} 
		 
		//set the filter 
		if(pcap_setfilter(g_pInputPcap, &fcode)<0) 
		{ 
			fprintf(stderr,"\nError setting the filter\n"); 
			return; 
		} 
	} 
     
	//open the dump file 
	if (szOutputFile != NULL) 
	{ 
		g_pDumpFile=pcap_dump_open(g_pInputPcap, szOutputFile); 
		if(g_pDumpFile==NULL) 
		{ 
			fprintf(stderr,"\nError opening output file\n"); 
			return; 
		} 
	} 
 
	//initialize 
	SetConsoleTitle("powerful content capture,  press  to quit"); 
	PrepareDirectory(argc, argv); 
	g_hashTbl = new CMapKeyToConnect(100); 
	g_hashTbl->InitHashTable(HASH_TABLE_SIZE); 
	g_pFtpDataMatchList = new CFtpDataMatchList; 
	if( g_bControlLAN ) 
	{ 
		//load acl  
		char aclFile[MAX_PATH]; 
		sprintf(aclFile, "%s%s", g_szWorkDir, szAclFile); 
		g_pAcl = new CPtrList(); 
		LoadAcl(aclFile, g_pAcl); 
	} 
	if( g_bFakeDns )  
	{ 
		char dnsFile[MAX_PATH]; 
		sprintf(dnsFile, "%s%s", g_szWorkDir, szDnsFile); 
		g_pFakeDns = new CPtrList(); 
		LoadDnsFakeList(dnsFile, g_pFakeDns); 
	} 
	srand(time(NULL)); 
 
	//start pcap thread 
	DWORD threadId; 
	HANDLE hThread = CreateThread(NULL, 0, PcapLoopThread, g_pInputPcap, 0, &threadId); 
 
	//loop run to check quit key 'Q' 
	while( 1 ) 
	{ 
		DWORD dwExitCode; 
		if( GetExitCodeThread(hThread, &dwExitCode) && dwExitCode != STILL_ACTIVE ) 
		{ 
			break; 
		} 
		else if( kbhit() ) 
		{ 
			if( toupper( getch() )== 'Q' ) 
				break;				 
		} 
		else 
			Sleep(100); 
	} 
 
	//quit 
	printf("Exiting......\n"); 
	g_bShouldExit = TRUE; 
	while( WaitForSingleObject(hThread, 0)==WAIT_TIMEOUT && g_dwPcapEnterCount!=0 )NULL; 
	TerminateThread(hThread, 0); 
	CloseHandle(hThread); 
 
	//close pcap handle and pcap_dump handle 
	if( g_pInputPcap ) 
	{ 
		pcap_close(g_pInputPcap); 
		g_pInputPcap = NULL; 
	} 
	if( g_pOutputPcap ) 
	{ 
		pcap_close(g_pOutputPcap); 
		g_pOutputPcap = NULL; 
	} 
	if( g_pDumpFile ) 
	{ 
		pcap_dump_close(g_pDumpFile); 
		g_pDumpFile = NULL; 
	} 
 
	//clearup acl list 
	if( g_pAcl ) 
	{ 
		ClearAcl(g_pAcl); 
		delete g_pAcl; 
	} 
 
	//clearup dns list 
	if( g_pFakeDns ) 
	{ 
		ClearFakeDnsList(g_pFakeDns); 
		delete g_pFakeDns; 
	} 
 
	//clearup existing CConnection 
	POSITION pos = g_hashTbl->GetStartPosition(); 
	while( pos!=NULL ) 
	{ 
		SOCKET_KEY key; 
		CConnection* pConnect; 
		g_hashTbl->GetNextAssoc(pos, key, pConnect); 
		printf("%d - %d.%d.%d.%d:%d-->%d.%d.%d.%d:%d\n", g_hashTbl->GetCount()-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; 
		g_hashTbl->RemoveKey(key); 
	} 
	g_hashTbl->RemoveAll(); 
	delete g_hashTbl; 
	delete g_pFtpDataMatchList; 
}