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;
}