www.pudn.com > PIPMasq.zip > coutward.cpp


#include "stdafx.h" 
#include "PIPMasq.h" 
 
bool getAdapterInfo( 
	const char* nicIPAddress,	// input 
	char* AdapterName,			// output 
	unsigned char*	macAddr		// output	 
); 
 
////////////////////////// COutward ///////////////////////////////// 
 
COutward::COutward( 
	TableMgr*	tableMgr,  
	PortMgr*	portMgr, 
	ArpMgr*		arpMgr, 
	PseudIF*	pseudIF, 
	ThreadMgr*	threadMgr, 
	FtpMgr*		ftpMgr, 
	const char* lanIPAddr, 
	const char* wanIPAddr,  
	const char* subWanIPAddr,  
	const char* defaultWanGWAddr) 
{ 
	memset(m_message, 0, sizeof(m_message)); 
 
	m_tableMgr = tableMgr; 
	m_portMgr = portMgr; 
	m_pseudIF = pseudIF; 
	m_arpMgr = arpMgr; 
	m_threadMgr = threadMgr; 
	m_ftpMgr = ftpMgr; 
 
	strcpy(m_lanIPAddr, lanIPAddr); 
	strcpy(m_wanIPAddr, wanIPAddr); 
 
	m_lanIPAddr_u32 = htonl(inet_addr(m_lanIPAddr)); 
	m_wanIPAddr_u32 = htonl(inet_addr(m_wanIPAddr)); 
 
	 
	memset(m_lanAdapterName, 0 , sizeof(m_lanAdapterName)); 
 
	if (getAdapterInfo(m_lanIPAddr, m_lanAdapterName, m_lanMacAddr)) 
		m_lanLpAdapter = PacketOpenAdapter(m_lanAdapterName); 
	else 
		return; 
 
	// LAN Side only 
	PacketSetBuff(m_lanLpAdapter, RECV_BUF); 
	PacketSetReadTimeout(m_lanLpAdapter, 10000);	// 10 seconds 
	//PacketSetReadTimeout(m_lanLpAdapter, 0);	// Blocking mode 
 
	PacketSetHwFilter(m_lanLpAdapter,NDIS_PACKET_TYPE_DIRECTED); 
	// PacketSetHwFilter(m_wanLpAdapter,NDIS_PACKET_TYPE_DIRECTED); 
 
	if((m_lanLpPacket = PacketAllocatePacket())==NULL) 
	{ 
		sprintf(m_message,"\nError:failed to allocate the LPPACKET structure.");  
		return; 
	} 
 
	PacketInitPacket(m_lanLpPacket,(char*)m_lanBuffer, sizeof(m_lanBuffer)); 
} 
 
 
COutward::~COutward() 
{ 
	PacketFreePacket(m_lanLpPacket); 
	PacketCloseAdapter(m_lanLpAdapter); 
 
	printf(".....COutward is destructed.\n"); 
//	Sleep(1000);	 
 
} 
 
 
COutward::start() 
{ 
	while(1) 
	{ 
		if(PacketReceivePacket(m_lanLpAdapter,m_lanLpPacket,TRUE) == FALSE) 
		{ 
			sprintf(m_message,"Error: PacketReceivePacket failed"); 
			return false; 
		} 
		 
		packetDelimiter(); 
 
		if (m_threadMgr->m_lifeFlag == true) 
			return false; 
	} 
} 
 
 
bool  
COutward::packetDelimiter() 
{ 
	ULONG	ulBytesReceived; 
	char	*pChar; 
	char	*buf; 
	u_int	off=0; 
	u_int	dataLen; 
	struct	bpf_hdr *hdr; 
	 
	ulBytesReceived = m_lanLpPacket->ulBytesReceived; 
	buf = (char *)m_lanLpPacket->Buffer;	 
	 
	off=0; 
 
	while(offbh_hdrlen; 
			 
		pChar = (char*)(buf+off);  // Top Address of thr Raw Packet 
 
		dataLen =hdr->bh_datalen; 
		off = Packet_WORDALIGN(off+dataLen); // For padding 
 
		analizeRawPacket(pChar, dataLen); 
	} 
 
	return true; 
} 
 
 
bool  
COutward::analizeRawPacket(char* pChar, int dataLen) 
{ 
	char* _pChar = pChar; 
 
	// Step.1  
	// If the packet is not IP packet, stop it. 
	 
	struct ethhdr *_ethhdr; 
	_ethhdr = (struct ethhdr *)_pChar; 
 
	if (_ethhdr->h_proto != htons(ETH_P_IP)) 
	{ 
		return false; 
	} 
 
	// Step.2  
	// If the destination IP address is LAN or WAN NIC IP Address, stop it. 
 
	struct iphdr *_iphdr; 
	_pChar += sizeof(struct ethhdr); 	 
 
	_iphdr = (struct iphdr *)_pChar; 
 
	if ((htonl(_iphdr->daddr) == m_lanIPAddr_u32)  
		||(htonl(_iphdr->daddr) == m_wanIPAddr_u32)) 
	{ 
		return false; 
	} 
 
	// Step.3 
	// Pick out each element of IP Packet 
	__u8 p_Protocol	=	_iphdr->protocol;	// TCP or UDP or ICMP 
	__u32 p_srcIPAddr = _iphdr->saddr;		// Source IP Address 
	__u32 p_destIPAddr = _iphdr->daddr;		// Destination IP Address 
 
	__u16 p_srcPort; 
	__u16 p_destPort; 
 
	struct udphdr *_udphdr; 
	struct tcphdr *_tcphdr; 
	struct icmphdr *_icmphdr; 
 
	// Step.4 
	// Pick up UDP or TCP header 
 
	_pChar += sizeof(struct iphdr);  
	 
	if (_iphdr->protocol == UDP) 
	{ 
		_udphdr = (struct udphdr *)_pChar; 
 
		p_srcPort = _udphdr->source;   // Source Port 
		p_destPort = _udphdr->dest;	// Destination Port 
	} 
	else if (_iphdr->protocol == TCP) 
	{ 
		_tcphdr = (struct tcphdr *)_pChar; 
 
		p_srcPort = _tcphdr->source;   // Source Port 
		p_destPort = _tcphdr->dest;	// Destination Port 
	} 
	else if (_iphdr->protocol == ICMP) 
	{ 
		// You might feel strange about the following lines. 
		// Because ICMP has no concept of the port. 
		// I didn't want to the table entry format in tablemgr.cpp, so  
		// I decided to use srcPort and masqPort in order to identify  
		// the ping reply message. 
		 
		_icmphdr = (struct icmphdr *)_pChar; 
 
		p_srcPort = _icmphdr->un.echo.id; 
		p_destPort = PORT_IGNORED; 
	} 
	else  
	{ 
		return false; 
	} 
 
	// Step.5 
	// Refer to the Entry Table 
 
	TableEntry* pTable; 
 
	RefLevel refLevel = m_tableMgr->refEntry( 
		p_Protocol,					// Protocol 
		p_srcPort,					// Source Port 
		p_srcIPAddr,				// Source IP Address 
		p_destPort,					// Destination Port 
		p_destIPAddr,				// Destination IP Address 
		&pTable						// Return Table pointer 
	); 
 
	// Step.6   
	// Make new packet toward WAN 
 
	// Case L2 (Perfect Matching) 
 
	if (refLevel == L2) 
	{ 
		// FTP in Active mode 
		if ((_iphdr->protocol == TCP) && (_tcphdr->dest == htons(FTP))) 
			m_ftpMgr->activeMode_out(pChar, &dataLen, pTable); 
 
		if (_iphdr->protocol == (UDP)) 
		{ 
			_udphdr->source = pTable->masqPort; 
		} 
		else if (_iphdr->protocol == (TCP)) 
		{ 
			_tcphdr->source = pTable->masqPort; 
		} 
		else if (_iphdr->protocol == ICMP) 
		{ 
			_icmphdr->un.echo.id = pTable->masqPort; 
		} 
		else 
		{ 
			return false; 
		} 
		 
		_iphdr->saddr = htonl(m_pseudIF->m_pseudIPAddr_u32); 
 
		memcpy(_ethhdr->h_source, m_pseudIF->m_pseudMacAddr, ETH_ALEN); 
		memcpy(_ethhdr->h_dest, pTable->destMACAddr, ETH_ALEN); 
	} 
	else if (refLevel == L1) 
	{ 
		// Port Number reservation 
		__u16 _masqPort; 
		if (! m_portMgr->reservPort(_iphdr->protocol, &_masqPort)) 
			return false; 
 
		// Make new table entry 
		TableEntry _entry; 
 
		_entry.diff_ack = 0; 
 
		memcpy(&_entry, pTable, sizeof(TableEntry)); // full copy 
 
		_entry.expireTime = time(NULL) + EXPIRE_PERIOD; 
		_entry.Protocol = _iphdr->protocol; 
		//_entry.socket = _socket; 
		_entry.masqPort = _masqPort; 
 
		if (_iphdr->protocol == (UDP)) 
			_entry.srcPort = _udphdr->source; 
		else if (_iphdr->protocol == (TCP)) 
			_entry.srcPort = _tcphdr->source; 
		else if (_iphdr->protocol == ICMP) 
			_entry.srcPort = _icmphdr->un.echo.id; 
		else 
			return false; 
 
		_entry.srcIPAddr = _iphdr->saddr; 
		memcpy(_entry.srcMACAddr, _ethhdr->h_source, ETH_ALEN); 
 
		// Add Entry 
		if (m_tableMgr->addEntry(&_entry) == false) 
			return false; 
 
		////// 
 
		if (_iphdr->protocol == (UDP)) 
		{ 
			_udphdr->source = _entry.masqPort; 
		} 
		else if (_iphdr->protocol == (TCP)) 
		{ 
			_tcphdr->source = _entry.masqPort; 
		} 
		else if (_iphdr->protocol == ICMP) 
		{ 
			_icmphdr->un.echo.id = _entry.masqPort; 
		} 
		else 
		{ 
			return false; 
		} 
		 
		//_iphdr->saddr = htonl(m_wanIPAddr_u32); 
		_iphdr->saddr = htonl(m_pseudIF->m_pseudIPAddr_u32); 
 
		memcpy(_ethhdr->h_source, m_pseudIF->m_pseudMacAddr, ETH_ALEN); 
		memcpy(_ethhdr->h_dest, _entry.destMACAddr, ETH_ALEN); 
 
	} 
	else if (refLevel == L0) 
	{	 
		char _macAddr[ETH_ALEN]; 
		memset(_macAddr, 0, sizeof(_macAddr)); 
		__u32 hAddr = ntohl(_iphdr->daddr); 
 
		if (m_arpMgr->arpSendRecv(hAddr,_macAddr) == false) 
			return false; 
 
		// Port Number reservation 
		__u16 _masqPort; 
		if (! m_portMgr->reservPort(_iphdr->protocol, &_masqPort)) 
			return false; 
 
		// Make new table entry 
		TableEntry _entry; 
 
		_entry.diff_ack = 0; 
 
		_entry.expireTime = time(NULL) + EXPIRE_PERIOD; 
		_entry.Protocol = _iphdr->protocol; 
		//_entry.socket = _socket; 
		_entry.masqPort = _masqPort; 
		 
		if (_iphdr->protocol == (UDP)) 
			_entry.srcPort = _udphdr->source; 
		else if (_iphdr->protocol == (TCP)) 
			_entry.srcPort = _tcphdr->source; 
		else if (_iphdr->protocol == ICMP) 
			_entry.srcPort = _icmphdr->un.echo.id; 
		else 
			return false; 
 
		_entry.srcIPAddr = _iphdr->saddr; 
		memcpy(_entry.srcMACAddr, _ethhdr->h_source, ETH_ALEN); 
 
		if (_iphdr->protocol == (UDP)) 
			_entry.destPort = _udphdr->dest; 
		else if (_iphdr->protocol == (TCP)) 
			_entry.destPort = _tcphdr->dest; 
		else if (_iphdr->protocol == ICMP) 
			_entry.destPort = _icmphdr->un.echo.id; 
		else 
			return false; 
 
		_entry.destIPAddr =	_iphdr->daddr; 
 
		memcpy(_entry.destMACAddr, _macAddr, ETH_ALEN); 
 
		// Add Entry 
		if (m_tableMgr->addEntry(&_entry) == false) 
			return false; 
 
		////// 
 
		if (_iphdr->protocol == (UDP)) 
		{ 
			_udphdr->source = _entry.masqPort; 
		} 
		else if (_iphdr->protocol == (TCP)) 
		{ 
			_tcphdr->source = _entry.masqPort; 
		} 
		else if (_iphdr->protocol == ICMP) 
		{ 
			_icmphdr->un.echo.id =  _entry.masqPort; 
		} 
		else 
		{ 
			return false; 
		} 
		 
		_iphdr->saddr = htonl(m_pseudIF->m_pseudIPAddr_u32); 
		 
		memcpy(_ethhdr->h_source, m_pseudIF->m_pseudMacAddr, ETH_ALEN); 
		memcpy(_ethhdr->h_dest, _entry.destMACAddr, ETH_ALEN); 
 
	} 
	else  
		return false; 
 
 
	///// Checksum calculation ///// 
 
	// IP checksum 
	_iphdr->check = 0; 
	_iphdr->check = in_cksum((unsigned short *)_iphdr, sizeof(struct iphdr)); 
 
 
	if (_iphdr->protocol == (UDP)) 
	{ 
		int udpDataLenInPacket =  
			ntohs(_iphdr->tot_len) - sizeof(struct iphdr) - sizeof(struct udphdr); 
 
		_udphdr->check = 0;  // Checksum should be set "0" first. 
		_udphdr->check =  
			udpchecksum(_udphdr, _iphdr, udpDataLenInPacket); 
	} 
	else if (_iphdr->protocol == (TCP)) 
	{ 
		int tcpDataLenInPacket =  
			ntohs(_iphdr->tot_len) - sizeof(struct iphdr) - sizeof(struct tcphdr); 
 
		_tcphdr->check = 0;	  // Checksum should be set "0" first. 
		_tcphdr->check =  
			tcpchecksum(_tcphdr, _iphdr, tcpDataLenInPacket); 
	} 
	else if (_iphdr->protocol == ICMP) 
	{ 
		int icmpDataLenInPacket =  
			ntohs(_iphdr->tot_len) - sizeof(struct iphdr); 
		 
		_icmphdr->checksum = 0; // should be 0 
		_icmphdr->checksum =  
			in_cksum((unsigned short *)_icmphdr, icmpDataLenInPacket);	 
	} 
	else 
	{ 
		return false; 
	} 
	 
	///// Packet Release ///// 
//	printf("\n\n\nAfter\n"); 
//	DumpPacket(pChar, dataLen); 
 
 
	m_pseudIF->releasePacket((void *)pChar, dataLen); 
 
 
	return true; 
}