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


#include "dns.h" 
 
struct DNS_HEADER_SECTION 
{ 
	WORD id; 
	WORD flags; 
	WORD queryCount; 
	WORD answerCount; 
	WORD serverCount; 
	WORD addCount; 
}; 
 
struct DNS_ANSWER_SECTION 
{ 
	WORD dnPtr; //must be 0xc00c 
	WORD rrType; //must be 1 
	WORD rrClass; //must be 1 
	DWORD rrTtl; //might be 86400 
	WORD rrDataLen; //must be 4  
	IP_ADDR rrHost;  
}; 
 
 
void DomainNameToLabelList(char*name, char*list) 
{ 
	char *p1, *p2, *p3; 
	p1 = list; 
	*p1 = 0; 
	p2 = list+1; 
	p3 = name; 
	for(; *p3!=0; p2++, p3++) 
	{ 
		if( *p3 == '.' || *p3 == 0 ) 
		{ 
			p1 = p2; 
			*p1 = 0; 
		} 
		else 
		{ 
			*p2 = *p3; 
			(*p1)++; 
		} 
	} 
	*p2 = 0; 
} 
 
int LabelListCompare(const char*list1, const char*list2) 
{ 
	int retVal = 0; 
	for(const char*p1=list1, *p2=list2; *p1!=0 && *p2!=0; ) 
	{ 
		if( (*p1==2 && memcmp(p1+1, "**", 2)==0) || (*p2==2 && memcmp(p2+1, "**", 2)==0) ) 
		{ 
			break; 
		} 
		else if( (*p1==1 && p1[1]=='*') || (*p2==1 && p2[1]=='*') ) 
		{ 
			p1 = p1 + *p1 + 1; 
			p2 = p2 + *p2 + 1; 
		} 
		else if( *p1 != *p2 ) 
		{ 
			retVal = *p1 - *p2; 
			break; 
		} 
		else 
		{ 
			retVal = memicmp(p1+1, p2+1, *p1); 
			if( retVal ) 
				break; 
			else 
			{ 
				p1 = p1 + *p1 + 1; 
				p2 = p2 + *p2 + 1; 
			} 
		} 
	} 
	return retVal; 
} 
 
BOOL LoadDnsFakeList(const char*filename, CPtrList *pList) 
{ 
	FILE *fp = fopen(filename, "rt"); 
	if(!fp) 
		return FALSE; 
 
	BOOL retVal = TRUE; 
	char line[1000], mode[256], range[256], name[256], ipAddr[256]; 
	strcpy(line,""); 
	while( fgets(line, sizeof(line), fp) ) 
	{ 
		char* p = line; 
		while( isspace(*p) ) p++; //skip white space 
		if( strcmp(p,"")==0 || memcmp(p, "//", 2) == 0 ) //empty line or comment line, just skip this line 
			continue; 
 
		strcpy(mode, ""); 
		strcpy(range, ""); 
		strcpy(name, ""); 
		strcpy(ipAddr, ""); 
		sscanf(line, "%s %s %s %s", mode, range, name, ipAddr); 
 
		FAKE_DNS_ENTRY item, *pItem; 
		//get mode 
		if( stricmp(mode, "allow")==0 ) 
			item.mode = DNS_ALLOW; 
		else if( stricmp(mode, "deny")==0 ) 
			item.mode = DNS_DENY; 
		else 
		{ 
			retVal = FALSE; 
			break; 
		} 
 
		//get range 
		if( stricmp(range, "") == 0 ) 
		{ 
			retVal = FALSE; 
			break; 
		} 
		 
		p = range; 
		p = GetByteRange(p, &item.addrLow.b1, &item.addrHigh.b1); 
		p = SkipChar(p, '.'); 
		p = GetByteRange(p, &item.addrLow.b2, &item.addrHigh.b2); 
		p = SkipChar(p, '.'); 
		p = GetByteRange(p, &item.addrLow.b3, &item.addrHigh.b3); 
		p = SkipChar(p, '.'); 
		p = GetByteRange(p, &item.addrLow.b4, &item.addrHigh.b4); 
		if( !p ) 
		{ 
			retVal = FALSE; 
			break; 
		} 
 
		//get name 
		if( strcmp(name, "")==0 ) 
		{ 
			retVal = FALSE; 
			break; 
		} 
		DomainNameToLabelList(name, item.labelList); 
 
		//get ip address coresponsind to dns 
		if( item.mode == DNS_DENY ) 
		{ 
			if( strcmp(ipAddr, "")==0 ) 
			{ 
				retVal = FALSE; 
				break; 
			} 
 
			int b1, b2, b3, b4; 
			if( sscanf(ipAddr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4)!=4 ) 
			{ 
				retVal = FALSE; 
				break; 
			} 
 
			item.addrFake.b1 = b1; 
			item.addrFake.b2 = b2; 
			item.addrFake.b3 = b3; 
			item.addrFake.b4 = b4; 
		} 
 
		//add to list 
		pItem = new FAKE_DNS_ENTRY; 
		*pItem = item; 
		pList->AddTail(pItem); 
	} 
	if( !retVal ) 
	{ 
		printf("DNS function systax error: %s", line); 
	} 
	fclose(fp); 
	return retVal; 
} 
 
void ClearFakeDnsList(CPtrList *pList) 
{ 
	if( !pList ) 
		return; 
	for(POSITION pos = pList->GetHeadPosition(); pos != NULL; ) 
	{ 
		FAKE_DNS_ENTRY *pItem = (FAKE_DNS_ENTRY *)pList->GetNext( pos ); 
		delete pItem; 
	} 
	pList->RemoveAll(); 
} 
 
BOOL ShouldFakeDns(const IP *ip, const UDP *pUdp, const BYTE *pDns,  
				   CPtrList *list, FAKE_DNS_ENTRY **ppItem) 
{ 
	BOOL retVal = FALSE; 
	if( pUdp->dstPort != PORT_DNS ) return retVal; 
 
	for(POSITION pos = list->GetHeadPosition(); pos != NULL; ) 
	{ 
		FAKE_DNS_ENTRY *pItem = (FAKE_DNS_ENTRY *)list->GetNext( pos ); 
		if( (pItem->addrLow.b1 <= ip->src.b1 && ip->src.b1 <= pItem->addrHigh.b1) 
			&& (pItem->addrLow.b2 <= ip->src.b2 && ip->src.b2 <= pItem->addrHigh.b2) 
			&& (pItem->addrLow.b3 <= ip->src.b3 && ip->src.b3 <= pItem->addrHigh.b3) 
			&& (pItem->addrLow.b4 <= ip->src.b4 && ip->src.b4 <= pItem->addrHigh.b4) ) 
		{ 
			const DNS_HEADER_SECTION *header = (const DNS_HEADER_SECTION *) pDns; 
			if( header->queryCount == htons(1) ) 
			{ 
				const char* pLabelList = (const char*)(header+1); 
				if( LabelListCompare(pLabelList, pItem->labelList)==0 ) 
				{ 
					if( pItem->mode == DNS_ALLOW ) 
						retVal = FALSE; 
					else 
						retVal = TRUE; 
					*ppItem = pItem; 
					break; 
				} 
					 
			} 
		} 
	} 
	return retVal; 
} 
 
BOOL MakeFakeDnsReply(const ETHERNET* ether, const IP* ip, const UDP *udp, const BYTE *dns,  
					  const FAKE_DNS_ENTRY* pEntry,  
					  BYTE* buffer, DWORD bufferSize, DWORD *packetLength ) 
{ 
	ETHERNET *pEther = (ETHERNET*)buffer; 
	IP *pIp = (IP*)(pEther+1); 
	UDP *pUdp = (UDP*)(pIp+1); 
	DNS_HEADER_SECTION *pHeader = (DNS_HEADER_SECTION *)(pUdp+1); 
	const DNS_HEADER_SECTION *header = (const DNS_HEADER_SECTION*)dns; 
 
	//set ether layer 
	memcpy(pEther->dst, ether->src, ETHERNET_ADDR_LEN); 
	memcpy(pEther->src, ether->dst, ETHERNET_ADDR_LEN); 
	pEther->protocol = ether->protocol; 
 
	//set ip layer 
	pIp->hl = 5; 
	pIp->v = 4; 
	pIp->tos = 0; 
	//pIp->len = ? unable to determinate now 
	pIp->id = htons(rand()); 
	pIp->offset = 0; 
	pIp->mf = 0; 
	pIp->rv = 0; 
	pIp->df = 1; 
	*(WORD*)( (BYTE*)pIp + 6 ) = htons( *(WORD*)( (BYTE*)pIp + 6 ) ); 
	pIp->ttl = 0x80; 
	pIp->protocol = IP_PROTOCOL_UDP; 
	pIp->checksum = htons(0); 
	pIp->src = ip->dst; 
	pIp->dst = ip->src; 
	//pIp->checksum = ?  unable to determinate now 
 
	//set udp layer 
	pUdp->srcPort = htons(udp->dstPort); 
	pUdp->dstPort = htons(udp->srcPort); 
	pUdp->checksum = 0; 
	//pUdp->length = ?  unable to determinate now 
	//pUdp->checksum = ?  unable to determinate now 
 
	//set dns layer 
	pHeader->id = header->id; 
	pHeader->flags = 0x8081; 
	pHeader->queryCount = htons(1); 
	pHeader->answerCount = htons(1); 
	pHeader->serverCount = htons(0); 
	pHeader->addCount = htons(0); 
 
	//copy question section 
	int nLabelLen = strlen((const char*)(header+1)) + 1; 
	memcpy(pHeader+1, header+1, nLabelLen + 4); 
 
	//make answer section 
	DNS_ANSWER_SECTION *pAnswer = (DNS_ANSWER_SECTION*)( (BYTE*)pHeader + sizeof(*pHeader) + nLabelLen+4); 
	pAnswer->dnPtr = htons(0xc00c); 
	pAnswer->rrType = htons(1); 
	pAnswer->rrClass = htons(1); 
	pAnswer->rrTtl = htonl(86400); 
	pAnswer->rrDataLen = htons(4); 
	pAnswer->rrHost = pEntry->addrFake; 
 
	//set length and checksum of udp 
	pUdp->length = htons( (BYTE*)(pAnswer+1) - (BYTE*)pUdp ); 
	pUdp->checksum = GetUdpCheckSum(pUdp, pIp, ntohs(pUdp->length) ); 
 
	//set length and checksum of ip 
	pIp->len = htons( (BYTE*)(pAnswer+1) - (BYTE*)pIp ); 
	pIp->checksum = GetCheckSum((const WORD*)pIp, 20); 
 
	//set length of full packet 
	*packetLength = (BYTE*)(pAnswer+1) - (BYTE*)pEther; 
 
	return TRUE; 
}