📄 simplednsclient.cpp
字号:
/*===========================================================================
(c) Copyright 2000, Emmanuel KARTMANN, all rights reserved
===========================================================================
File : SimpleDNSClient.cpp
$Header: $
Author : Emmanuel KARTMANN <emmanuel@kartmann.org>
Creation : Monday 1/31/00 3:51:31 PM
Remake :
------------------------------- Description -------------------------------
Implementation of the CSimpleDNSClient
------------------------------ Modifications ------------------------------
$Log: $
===========================================================================
*/
#include "stdafx.h"
#include "SimpleDNSResolver.h"
#include "SimpleDNSClient.h"
#include "WindowsErrorText.h"
#include "InternetStandards.h"
/////////////////////////////////////////////////////////////////////////////
// CSimpleDNSClient: Public (Exported) methods
STDMETHODIMP CSimpleDNSClient::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_ISimpleDNSClient
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (IsEqualGUID((REFGUID)*arr[i],(REFGUID)riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CSimpleDNSClient::Resolve(BSTR BSearchedName, VARIANT *pvFoundNames, BSTR BResourceClass, BSTR BResourceType)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
HRESULT hReturnCode = FALSE; // Failure
DNS_STATUS nStatus = 0;
WORD wType = 0;
PIP4_ARRAY pSrvList = NULL; // pointer to IP4_ARRAY structure
PDNS_RECORD pDnsRecords = NULL;
PVOID pReserved = NULL;
CString szSearchedName;
CString szFoundNames;
// Convert parameters and init output
szSearchedName = BSearchedName;
if (szSearchedName == "") {
SetError("Invalid resource name (empty): ", ERROR_INVALID_PARAMETER);
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
wType = CInternetStandards::GetResourceTypeFromString((LPCTSTR)_bstr_t(BResourceType));
if (wType == DNS_INVALID_RESOURCE_TYPE) {
CString szErrorMessage = "Invalid DNS Resource Type ";
szErrorMessage+= CString((LPCTSTR)_bstr_t(BResourceType));
szErrorMessage+=": ";
SetError(szErrorMessage, ERROR_INVALID_PARAMETER);
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
// TODO: hanlde non-internet type (how? There's no such parameter in MS API...)
int nClass = CInternetStandards::GetResourceClassFromString((LPCTSTR)_bstr_t(BResourceClass));
if (nClass != DNS_CLASS_INTERNET) {
CString szErrorMessage = "Invalid DNS Resource Class (only C_IN is supported): ";
SetError(szErrorMessage, ERROR_INVALID_PARAMETER);
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
// If request is a reverse (address->name) lookup (type PTR), then silently convert
// request to a in-arpa format
if (wType == DNS_TYPE_PTR) {
unsigned long addr = inet_addr(szSearchedName);
if (addr != INADDR_NONE) {
char *p = (char *)&addr;
szSearchedName.Format("%u.%u.%u.%u.in-addr.arpa",
((unsigned)p[3] & 0xff), // CAUTION: reverse byte order (p[3]...p[0])
((unsigned)p[2] & 0xff),
((unsigned)p[1] & 0xff),
((unsigned)p[0] & 0xff));
} else {
// Must be an address for a PTR request: error
SetError("Invalid resource name (empty): ", ERROR_INVALID_PARAMETER);
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
}
LPCTSTR lpstrName = szSearchedName;
// use all known servers (or use method FindAllDNSServers if empty)
if (m_szServerAddresses == "") {
m_szServerAddresses = FindAllDNSServers();
}
BOOL bNoServer = TRUE;
CStringList oServerList;
CString szServerAddress;
BuildListFromString(m_szServerAddresses, oServerList);
POSITION pServer = oServerList.GetHeadPosition();
int i=0;
pSrvList = (PIP4_ARRAY) LocalAlloc(LPTR,sizeof(IP4_ARRAY));
if (!pSrvList) {
DWORD dwLastError = GetLastError();
SetError("Memory Allocation Error:" , dwLastError);
hReturnCode = HRESULT_FROM_WIN32(dwLastError);
} else {
/*
****
WARNING: if the DNS server is non-standard, the option flag fOptions must NOT be
equal to DNS_QUERY_STANDARD, but to DNS_QUERY_BYPASS_CACHE.
Thanks to Thomas Heike (t.heike@lit.lineas.de) for his help on this...
****
*/
DWORD fOptions = DNS_QUERY_STANDARD;
while (pServer != NULL) {
szServerAddress = oServerList.GetNext(pServer);
// Convert dotted notation into address (4 bytes)
// Store it in configuration (memory)
pSrvList->AddrCount = 1;
pSrvList->AddrArray[0] = inet_addr(szServerAddress);
bNoServer = FALSE;
fOptions = DNS_QUERY_BYPASS_CACHE;
// TODO: store all servers in IP4_ARRAY (how??? there's only one element is array!)
// For now, exit loop after 1st server
break;
}
if (bNoServer) {
CString szErrorMessage = "Invalid DNS server addresses \"";
szErrorMessage+=m_szServerAddresses;
szErrorMessage+="\": ";
SetError(szErrorMessage, ERROR_INVALID_PARAMETER);
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
// Send query to DNS Server and fetch reply
nStatus = DnsQuery(lpstrName,
wType,
fOptions,
pSrvList,
&pDnsRecords,
NULL);
if (nStatus) {
DWORD dwLastError = nStatus;
SetError("DNS Resolution failure: ", dwLastError);
hReturnCode = HRESULT_FROM_WIN32(dwLastError);
} else {
switch(wType) {
// A (IP v4 address)
case DNS_TYPE_A:
{
// convert address into string (dotted notation) and add to result
do {
IN_ADDR ipaddr;
ipaddr.S_un.S_addr = (pDnsRecords->Data.A.IpAddress);
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, inet_ntoa(ipaddr), szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// PTR (reverse lookup: address->name)
case DNS_TYPE_PTR:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.PTR.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MX (Mail eXchanger)
case DNS_TYPE_MX:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MX.pNameExchange, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// AFSDB (RFC 1183)
case DNS_TYPE_AFSDB:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.AFSDB.pNameExchange, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// RT (RFC 1183)
case DNS_TYPE_RT:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.RT.pNameExchange, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// CNAME (Canonical Name)
case DNS_TYPE_CNAME:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.NS.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// NS (Name Server)
case DNS_TYPE_NS:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.NS.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// SOA (start of authority)
case DNS_TYPE_SOA:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.SOA.pNamePrimaryServer, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MB
case DNS_TYPE_MB:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MB.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MD
case DNS_TYPE_MD:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MD.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MF
case DNS_TYPE_MF:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MF.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MG
case DNS_TYPE_MG:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MG.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MR
case DNS_TYPE_MR:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MR.pNameHost, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// MINFO (mail information)
case DNS_TYPE_MINFO:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.MINFO.pNameMailbox, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// RP (Responsible Person)
case DNS_TYPE_RP:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.RP.pNameMailbox, szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// HINFO
case DNS_TYPE_HINFO:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.HINFO.pStringArray[1], szFoundNames);
}
pDnsRecords = pDnsRecords->pNext;
} while (pDnsRecords);
}
break;
// ISDN
case DNS_TYPE_ISDN:
{
do {
if (pDnsRecords->Flags.S.Section == DNSREC_ANSWER) {
AppendResult(wType, pDnsRecords->wType, pDnsRecords->Data.ISDN.pStringArray[1], szFoundNames);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -