Do the actual DNS query.
| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzDNS::Query | (const char*,DnsType,) |
Declared in file: hzDNS.h
Defined in file : hzDNS.cpp
Function Logic:
Function body:
hzEcode hzDNS::Query (const char* dom)DnsType eType,
{
// Do the actual DNS query.
//
// Arguments: 1) eType Query type Either MX or A
// 2) dom Domain name
//
// Returns: E_ARGUMENT If the domain name is not supplied
// E_INITFAIL If res_init() has not been called before and now returns an error
// E_OVERFLOW If the res_search function owverfills the buffer
// E_DNS_NOHOST If the host does not exist
// E_DNS_NODATA If the domain exists but there is no host for the applicable service
// E_DNS_RETRY If the DNS could not provide data at this time
// E_DNS_FAILED If the DNS failed
// E_OK If the DNS query was successful
_hzfunc("hzDNS::Query") ;
hzChain errCh ; // In the event of error, shows progress so far
DnsRec dr ; // DNS record
hzLogger* pLog ; // For debug mode
uchar* ix ; // DNS record iterator
uchar* jx ; // DNS record forward marker
uint32_t nQus ; // Questions
uint32_t nAns ; // Questions
uint32_t nAut ; // Questions
uint32_t nAdd ; // Questions
uint32_t nCount ; // Interator res_search response
int32_t nSize ; // Bytes returned by res_search
// Clear m_Error
m_Error.Clear() ;
// Check args
if (!dom || !dom[0])
return hzerr(E_ARGUMENT, "No domain name supplied") ;
// Check buffer
if (!m_cpDns)
m_cpDns = new uchar[2048];
ix = m_cpDns ;
if (!ix)
hzexit(E_MEMORY, "Could not allocate buffers for DNS query") ;
// Chekck res_init() has been called (only once)
if (!s_bInitResolver)
{
if (res_init() == -1)
return hzerr(E_INITFAIL, "Could not init DNS resolver") ;
s_bInitResolver = true ;
}
_clear() ;
pLog = GetThreadLogger() ;
/*
** ** Query the DNS
** */
nSize = res_search(dom, C_IN, eType, m_cpDns, 2047);
if (nSize >&eq; 2000)
return hzerr(E_OVERFLOW, "DNS buffer overflow for %s", dom) ;
if (nSize == -1)
{
switch (h_errno)
{
case HOST_NOT_FOUND: return E_DNS_NOHOST ; // The specified host is unknown.
case NO_DATA: return E_DNS_NODATA ; // The requested name is valid but does not have an IP address.
case NO_RECOVERY: return E_DNS_FAILED ; // A non-recoverable name server error occurred.
case TRY_AGAIN: return E_DNS_RETRY ; // A temporary error occurred on an authoritative name server. Try again later.
}
return hzerr(E_DNS_FAILED, "Unspecified error (%s) for domain %s", hstrerror(h_errno), dom) ;
}
m_cpDns[nSize] = 0;
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
{
errCh.Printf("DNS BUFFER (%d bytes) =\n[\n", nSize) ;
for (nCount = 0; nCount < (uint32_t) nSize ;)
{
if (nCount < 240&&m_cpDns[nCount]> 32&&m_cpDns[nCount] < 128)
errCh.Printf(" %c", m_cpDns[nCount]) ;
else
errCh.Printf(" %02x", m_cpDns[nCount]) ;
nCount++ ;
if (!(nCount % 40))
errCh.AddByte(CHAR_NL) ;
else
errCh.AddByte(CHAR_SPACE) ;
}
if (nCount % 40)
errCh.AddByte(CHAR_NL) ;
errCh.Printf("]\n") ;
}
// Get result params
m_qID = (m_cpDns[0] << 8)+ m_cpDns[1];
m_DNA = (m_cpDns[2] << 8)+ m_cpDns[3];
nQus = (m_cpDns[4] << 8)+ m_cpDns[5];
nAns = (m_cpDns[6] << 8)+ m_cpDns[7];
nAut = (m_cpDns[8] << 8)+ m_cpDns[9];
nAdd = (m_cpDns[10]<<8)+ m_cpDns[11];
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
{
errCh.Printf("Query id: %d\n", m_qID) ;
errCh.Printf("DNA code: %d\n", m_DNA) ;
errCh.Printf("No questions: %d\n", nQus) ;
errCh.Printf("No answers: %d\n", nAns) ;
errCh.Printf("No authority: %d\n", nAut) ;
errCh.Printf("No additional: %d\n", nAdd) ;
}
/*
** ** Bypass the 'pre-defined' strings to get the answers
** */
for (ix = m_cpDns + 12;*ix ; ix++) ;
ix += 5;
// Now have answers
for (nCount = 0; nCount < nAns ; nCount++)
{
dr.Clear() ;
dr.m_Domain = _procraw(&ix) ;
if (!dr.m_Domain)
{
pLog->Out(errCh) ;
return hzerr(E_DNS_FAILED, "Answer record without domain") ;
}
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf("Answ: %s:", *dr.m_Domain) ;
dr.m_nType = (ix[0]<< 8)+ ix[1];
dr.m_nClass = (ix[2]<< 8)+ ix[3];
dr.m_nTTL = (ix[4]<< 24)+(ix[5]<< 16)+(ix[6]<< 8)+ ix[7];
dr.m_nLen = (ix[8]<< 8)+ ix[9];
dr.m_nValue = 0;
ix += 10;
jx = ix + dr.m_nLen ;
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf(" -> Type %u Class %u TTL %u Len %u", dr.m_nType, dr.m_nClass, dr.m_nTTL, dr.m_nLen) ;
if (dr.m_nType == DNSTYPE_MX)
{
dr.m_nValue = (ix[0]<< 8)+ ix[1];
ix += 2;
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf(" Val %u", dr.m_nValue) ;
}
if (dr.m_nType == DNSTYPE_A)
{
dr.m_Ipa.SetValue(ix[0],ix[1],ix[2],ix[3]);
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf(" IPv4 (%u.%u.%u.%u)\n", ix[0],ix[1],ix[2],ix[3]);
}
else if (dr.m_nType == DNSTYPE_AAAA)
{
dr.m_anorakA = (ix[0] << 24)+(ix[1] << 16)+(ix[2] << 8)+ (ix[3]);
dr.m_anorakB = (ix[4] << 24)+(ix[5] << 16)+(ix[6] << 8)+ (ix[7]);
dr.m_anorakC = (ix[8] << 24)+(ix[9] << 16)+(ix[10]<<8)+ (ix[11]);
dr.m_anorakD = (ix[12]<<24)+(ix[13]<<16)+(ix[14]<<8)+ (ix[15]);
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf(" IPv6 (%u.%u.%u.%u)\n", dr.m_anorakA, dr.m_anorakB, dr.m_anorakC, dr.m_anorakD) ;
}
else
{
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.AddByte(CHAR_NL) ;
dr.m_Server = _procraw(&ix) ;
if (!dr.m_Server)
{
pLog->Out(errCh) ;
return hzerr(E_DNS_FAILED, "Answer record without server") ;
}
}
m_arAns.Add(dr) ;
ix = jx ;
}
// Get authority records
for (nCount = 0; nCount < nAut ; nCount++)
{
dr.Clear() ;
// Get the domain name
dr.m_Domain = _procraw(&ix) ;
if (!dr.m_Domain)
{
pLog->Out(errCh) ;
return hzerr(E_DNS_FAILED, "Authority record without domain") ;
}
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf("Auth: %s:", *dr.m_Domain) ;
dr.m_nType = (ix[0]<< 8)+ ix[1];
dr.m_nClass = (ix[2]<< 8)+ ix[3];
dr.m_nTTL = (ix[4]<< 24)+(ix[5]<< 16)+(ix[6]<< 8)+ ix[7];
dr.m_nLen = (ix[8]<< 8)+ ix[9];
dr.m_nValue = 0;
ix += 10;
jx = ix + dr.m_nLen ;
if (_hzGlobal_Debug & HZ_DEBUG_DNS)
errCh.Printf(" -> Type %u Class %u TTL %u Len %u\n", dr.m_nType, dr.m_nClass, dr.m_nTTL, dr.m_nLen) ;
if (dr.m_nType == DNSTYPE_MX)
{ dr.m_nValue = (ix[0]<< 8)+ ix[1]; ix += 2; }
if (dr.m_nType == DNSTYPE_A)
dr.m_Ipa.SetValue(ix[0],ix[1],ix[2],ix[3]);
else if (dr.m_nType == DNSTYPE_AAAA)
{
dr.m_anorakA = (ix[0] << 24)+(ix[1] << 16)+(ix[2] << 8)+ (ix[3]);
dr.m_anorakA = (ix[4] << 24)+(ix[5] << 16)+(ix[6] << 8)+ (ix[7]);
dr.m_anorakA = (ix[8] << 24)+(ix[9] << 16)+(ix[10]<<8)+ (ix[11]);
dr.m_anorakA = (ix[12]<<24)+(ix[13]<<16)+(ix[14]<<8)+ (ix[15]);
ix += 16;
}
else
{
dr.m_Server = _procraw(&ix) ;
if (!dr.m_Server)
{
pLog->Out(errCh) ;
return hzerr(E_DNS_FAILED, "Authority record without server") ;
}
}
m_arAut.Add(dr) ;
ix = jx ;
}
return E_OK ;
}