📄 dns.h
字号:
{
NS = Buffer.GetName(0);
}
virtual CString ToString()
{
CString Text;
Text += "NS Record:\n";
Text += CDnsRR::ToString();
Text += "NS=" + NS + "\n";
return Text;
}
virtual void CopyRData(CDnsRR* pRR){
CDnsRRNS * pRRNS = (CDnsRRNS*) pRR;
NS = pRRNS->NS;
}
};
/************************************************************************
Name : CDnsQueryType
Type : Class
------------------------------------------------------------------------
Author : Akash Kava
Purpose: Returns int type number from string representation of type
Also returns new Resource Record Class Pointer
This static function makes new object of specified type
and also copies contents of CDnsRR to type dependent
resource record object
************************************************************************/
class CDnsQueryType{
public:
static int GetType( CString Name )
{
Name.MakeUpper();
if(Name == "A")
return 1;
if(Name == "NS")
return 2;
if(Name == "MD")
return 3;
if(Name == "MF")
return 4;
if(Name == "CNAME")
return 5;
if(Name == "SOA")
return 6;
if(Name == "MB")
return 7;
if(Name == "MG")
return 8;
if(Name == "MR")
return 9;
if(Name == "NULL")
return 10;
if(Name == "WKS")
return 11;
if(Name == "PTR")
return 12;
if(Name == "HINFO")
return 13;
if(Name == "MINFO")
return 14;
if(Name == "MX")
return 15;
if(Name == "TXT")
return 16;
return -1;
}
static CDnsRR * GetNewRecord(CDnsRR * pRR)
{
switch(pRR->Type)
{
case 1:
return new CDnsRRA(pRR);
case 2:
return new CDnsRRNS(pRR);
case 5:
return new CDnsRRCNAME(pRR);
case 15:
return new CDnsRRMX(pRR);
// Rest you implement if you need it !! he he
default:
return new CDnsRRDefault(pRR);
}
}
};
/************************************************************************
Name : CDnsQuery
Type : Class
------------------------------------------------------------------------
Author : Akash Kava
Purpose: Dns Query Class
************************************************************************/
class CDnsQuery{
public:
CStringList Names;
unsigned __int16 Type;
unsigned __int16 Class;
CDnsQuery( LPCTSTR lpszHost , LPCTSTR lpszType )
{
CString host(lpszHost);
int i;
do
{
i = host.Find('.');
if(i != -1)
{
Names.AddTail(host.Mid(0,i));
host = host.Mid(i+1);
}
else
{
Names.AddTail(host);
break;
}
}while(true);
Type = CDnsQueryType::GetType(lpszType);
Class = 1;
}
CDnsBuffer Pack()
{
CDnsBuffer Buffer;
POSITION Pos = Names.GetHeadPosition();
while(Pos)
{
CString Name = Names.GetNext(Pos);
unsigned __int8 Len = Name.GetLength();
Buffer << Len;
Buffer.Append((unsigned char *)(LPCTSTR)Name,Len);
}
unsigned __int8 n = 0;
Buffer << n;
Buffer << Type;
Buffer << Class;
return Buffer;
}
void Unpack( CDnsBuffer & Buffer )
{
CString Name = Buffer.GetName(0);
Buffer >> Type;
Buffer >> Class;
}
};
/************************************************************************
Name : CDnsRRPtrList
Type : Class
------------------------------------------------------------------------
Author : Akash Kava
Purpose: All Resource Records are hold in a CList class which holds
pointers of all objects. And also implements CHostSearch
and returns IP address found in A records if any
Users who use the record pointer are requested to keep
copy of Resource Record according to type because when
This clas gets destroys it deletes its pointers !!
************************************************************************/
class CDnsRRPtrList :public CList<CDnsRR*,CDnsRR*>{
public:
~CDnsRRPtrList ()
{
while(!IsEmpty())
{
CDnsRR * pRR = RemoveHead();
delete pRR;
}
}
};
/************************************************************************
Name : CDnsClient
Type : Class
------------------------------------------------------------------------
Author : Akash Kava
Purpose: The final DnsClient class
It can be used in 2 ways.
1) Directly Query MX records and CStringList by calling
static member function. No hastle of pointer management.
2) Call another static function Get to get result of type
requested The CDnsRRPtrList supplied gets all required
resource records. It searches recursivly of found names
servers so you dont need to worry about nameservers
returned in query. What you will get is the final result
after 10 tries. Or else domain does not exist.
The list returned has pointers to CDnsRR derived class
depending upon type. While using it, please copy the
relevant content and then processing because everything
will get destroyed as soon as CDnsRRPtrList goes out of
scope.
2) Create Object of class and query, you will need to do all
recursive nameserver processing etc so just forget it.
************************************************************************/
class CDnsClient{
public:
CString Log;
CSocketClient Client;
CDnsBuffer Buffer;
int QueryType;
CDnsHeader Header;
CDnsRRPtrList Questions;
CDnsRRPtrList Answers;
CDnsRRPtrList Authorities;
CDnsRRPtrList Additionals;
BOOL Query(LPCTSTR lpszServer, LPCTSTR lpszHost, LPCTSTR lpszType)
{
try
{
unsigned __int16 size;
// Build The query
CDnsQuery Query(lpszHost,lpszType);
// Make the Buffer
Buffer += Header.Pack();
Buffer += Query.Pack();
// Try to connect to server, if failed, will give an exception
Client.ConnectTo(lpszServer,53);
// Write Buffer to end client
size = Buffer.GetSize();
Client.WriteInt16(size);
Client.WriteBytes(Buffer.GetBuffer(),Buffer.GetSize());
// Dns Response send buffer length first, read it
// then read buffer
size = Client.ReadInt16();
Client.ReadBytes(Buffer.GetBufferSetLength(size),size);
// Cool now Socket is not needed, close it
Client.Close();
// Put Buffer's pointer to 0 and start reading things now.
Buffer.Reset(0);
// First Extract Header from buffer
Header.Unpack(Buffer);
// Dns Query is sent again by server, uselessly..
// Extract it, what else we an do...
Query.Unpack(Buffer);
QueryType = Query.Type;
// Read rest of Records
GetRecords(Answers,Header.ANCount);
GetRecords(Authorities,Header.NSCount);
GetRecords(Additionals,Header.ARCount);
return true;
}
catch(CSocketException * pE)
{
Log += pE->m_strError + "\n";
return false;
}
}
void GetRecords( CDnsRRPtrList & List , int Total )
{
if(Total==0)
return;
for(int i=0;i<Total;i++)
{
CDnsRR RR;
RR.Unpack(Buffer);
CDnsRR * pRR = CDnsQueryType::GetNewRecord(&RR);
pRR->Unpack(Buffer);
List.AddTail(pRR);
TRACE0(pRR->ToString());
}
}
/************************************************************************
FUNCTION
Name : Get
Author : Akash Kava
Purpose: Call this function to retrive answers of query, this function
does recursive processing upto specified number of trials
While calling this function, please pass the Reference parameters
as explained
========================================================================
Params : Server : Name of the name server to connect
Name : Domain name to query
Type : Type of query, case insensitive, MX or mx
Answers : Resource Record Object List , please pass empty
List here, it will return all answers
Additional: Resource Record Object List, please pass empty
List here , it will pass additional A record entries
NSTried : Please pass empty CStringList here
Log : Please pass empty CString here
nTries : Make sure you pass atleast 5 trials
------------------------------------------------------------------------
Returns: True if successful , false if failed
************************************************************************/
static BOOL Get(
LPCTSTR lpszServer,
LPCTSTR lpszName,
LPCTSTR lpszType,
CDnsRRPtrList& Answers,
CDnsRRPtrList& Additionals,
CStringList& NSTried,
CString& Log,
int& nTries
)
{
if(lpszServer==NULL)
{
// If you dont specify servers then try root servers.. too costly!!!
if(Get("A.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("B.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("C.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("D.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("E.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("F.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("G.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("H.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
nTries = 10;
if(Get("I.GTLD-SERVERS.net",lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
return true;
if(nTries==0)
return false;
return false;
}
// Tries over, fine, return true to indicate end of process
if(nTries<=0)
{
Log += lpszName;
Log += " Domain Does not exist Probably\n";
return true;
}
nTries--;
// Resolve DNS
CDnsClient Client;
if(!Client.Query(lpszServer,lpszName,lpszType))
return false;
// Found Answers, cool, Make a copy and return
if(Client.Answers.GetCount()!=0)
{
POSITION Pos = Client.Answers.GetHeadPosition();
while(Pos)
{
CDnsRR * pRR = (CDnsRR*) Client.Answers.GetNext(Pos);
// Allocate new Record from CDnsQueryType and also copy initial content
// that is without RData
CDnsRR * pNewRR = CDnsQueryType::GetNewRecord(pRR);
// Copy RData to new object
pNewRR->CopyRData(pRR);
// Add it to Answer List
Answers.AddTail(pNewRR);
}
// Add additional entries from here of all A records only
Pos = Client.Additionals.GetHeadPosition();
while(Pos)
{
CDnsRR * pRR = Client.Additionals.GetNext(Pos);
if(pRR->Type == 1)
{
// Allocate new record from CDnsQueryType and also copy
// initiail conent without RData
CDnsRR * pNewRR = CDnsQueryType::GetNewRecord(pRR);
// Copy RData to new object
pNewRR->CopyRData(pRR);
Additionals.AddTail(pNewRR);
}
}
return true;
}
// If the Name Server we queried is already authorized
// return true, may be domain expired !!
if(Client.Header.Flags.Flags.AA == 1)
return true;
// Recursive Query , The DNS client returns NS records
// which contains name server information, get it and
// query them to find answer
POSITION Pos = Client.Authorities.GetHeadPosition();
while(Pos)
{
CDnsRRNS * pRRNS = (CDnsRRNS *)Client.Authorities.GetNext(Pos);
// Choose only Name Servers , or else goto next
if(pRRNS->Type != 2)
continue;
// Get IP , put less load on System DNS Resolver, forget it now..
//CString NS = Client.Additionals.GetHostIP(pRRNS->NS);
CString NS = pRRNS->NS;
// Make sure you visit Name server only once
// if you have already tried then leave, goto next
if(NSTried.Find(NS)!=NULL)
continue;
// Add this name server into Tried List
NSTried.AddTail(NS);
// If recursive query returns true then return true,
// either it was successful
// or it gave empty result and domain expired
if(Get(NS,lpszName,lpszType,Answers,Additionals,NSTried,Log,nTries))
{
return true;
}
// In case there are any resource records in answer
// go and return true
if(!Answers.IsEmpty())
return true;
}
// Even if you didnt find anything in Name servers
// might be cilent couldnt connect to name server
// try next, just return false
return false;
}
// whooooooo baby, the most important , MX search
// Just searches the MX of domain, returns IP address only,
// however you can use Get function to get detailed MX records
// CStringList receives all host addresses for MX
static CString GetMX(LPCTSTR lpszServer,LPCTSTR lpszHost,CStringList & List)
{
List.RemoveAll();
CString Log;
CStringList NSTried;
int nTries=10;
CDnsRRPtrList Answers;
CDnsRRPtrList Additionals;
if(Get(lpszServer,lpszHost,"MX",Answers,Additionals,NSTried,Log,nTries))
{
Log.Empty();
while(!Answers.IsEmpty())
{
CDnsRRMX * pRR = (CDnsRRMX*)Answers.RemoveHead();
SearchARecords(pRR->Exchange,Additionals,List);
Log += pRR->ToString();
delete pRR;
}
}
return Log;
}
static void SearchARecords( CString & Domain , CDnsRRPtrList & Additionals, CStringList & IPList)
{
BOOL bFound = false;
POSITION Pos = Additionals.GetHeadPosition();
while(Pos)
{
CDnsRR * pRR = (CDnsRR*) Additionals.GetNext(Pos);
if(pRR->Type!=1)
continue;
CDnsRRA * pRRA = (CDnsRRA*) pRR;
if(pRRA->Name.CompareNoCase(Domain)==0)
{
IPList.AddTail(pRRA->A);
bFound = true;
}
}
if(!bFound)
IPList.AddTail(Domain);
}
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -