基于 MFC 的 DNS 查询应用程序






4.42/5 (10投票s)
本文演示了针对特定域名地址的 DNS 查询,并提供了 MFC GUI 界面以便于使用。
引言
当你连接到地址为 'www.codeproject.com' 的服务器时,你的浏览器需要它的数字表示形式 69.10.233.10,它通过 DNS 查询获得。当你的邮件程序需要向特定域名(如 webmaster@codeproject.com)发送电子邮件时,也会发生相同的过程。在这里,它需要知道 codeproject 域的邮件服务器,这通过 DNS 查询获得。DNS 上针对特定域名,你可能还会获得其他类型的查询。 在本文中,我提供了一个具有文档/视图架构的不错的 GUI MFC 应用程序,用于执行所有类型的 DNS 查询。
背景
开始学习 DNS 的好方法是查看 MSDN 或 SDK 帮助中的“域名系统”主题,位于“网络/网络协议”部分。 它描述了基础知识,并为你提供了必要的 RFC 文档进行阅读,例如 RFC 1034(域名-概念和设施-实施和规范-应用和支持)、RFC 1035(域名)等等。
Using the Code
首先确保你已连接到互联网。 按 CTRL+Q 或转到“文件”菜单并单击“DnsQuery”。 你将获得此对话框。

输入要查询的服务器的名称,例如 codeproject.com,选择查询类型、选项,并可以选择使用你自己的默认 DNS 服务器,或通过在底部的编辑框中键入来请求特定的 DNS 服务器。
此示例提供了两种类型的查询,类型为 A 和 NS,以获取 codeproject.com 的数字地址及其名称服务器。

在之前的图像中的 DNS 查询框中,指定了 DNS 服务器 ns.dundas.com 以请求查询类型 ANY
,以获取有关 codeproject.com 服务器的所有信息。

你可以在相应的 RFC 文档或 windns.h 文件中找到其他查询类型的描述
//
// DNS Record Types
//
// _TYPE_ defines are in host byte order.
// _RTYPE_ defines are in net byte order.
//
// Generally always deal with types in host byte order as we index
// resource record functions by type.
//
#define DNS_TYPE_ZERO 0x0000
// RFC 1034/1035
#define DNS_TYPE_A 0x0001 // 1
#define DNS_TYPE_NS 0x0002 // 2
#define DNS_TYPE_MD 0x0003 // 3
#define DNS_TYPE_MF 0x0004 // 4
#define DNS_TYPE_CNAME 0x0005 // 5
#define DNS_TYPE_SOA 0x0006 // 6
#define DNS_TYPE_MB 0x0007 // 7
#define DNS_TYPE_MG 0x0008 // 8
#define DNS_TYPE_MR 0x0009 // 9
#define DNS_TYPE_NULL 0x000a // 10
#define DNS_TYPE_WKS 0x000b // 11
#define DNS_TYPE_PTR 0x000c // 12
#define DNS_TYPE_HINFO 0x000d // 13
#define DNS_TYPE_MINFO 0x000e // 14
#define DNS_TYPE_MX 0x000f // 15
#define DNS_TYPE_TEXT 0x0010 // 16
// RFC 1183
#define DNS_TYPE_RP 0x0011 // 17
#define DNS_TYPE_AFSDB 0x0012 // 18
#define DNS_TYPE_X25 0x0013 // 19
#define DNS_TYPE_ISDN 0x0014 // 20
#define DNS_TYPE_RT 0x0015 // 21
// RFC 1348
#define DNS_TYPE_NSAP 0x0016 // 22
#define DNS_TYPE_NSAPPTR 0x0017 // 23
// RFC 2065 (DNS security)
#define DNS_TYPE_SIG 0x0018 // 24
#define DNS_TYPE_KEY 0x0019 // 25
// RFC 1664 (X.400 mail)
#define DNS_TYPE_PX 0x001a // 26
// RFC 1712 (Geographic position)
#define DNS_TYPE_GPOS 0x001b // 27
// RFC 1886 (IPv6 Address)
#define DNS_TYPE_AAAA 0x001c // 28
// RFC 1876 (Geographic location)
#define DNS_TYPE_LOC 0x001d // 29
// RFC 2065 (Secure negative response)
#define DNS_TYPE_NXT 0x001e // 30
// Patton (Endpoint Identifier)
#define DNS_TYPE_EID 0x001f // 31
// Patton (Nimrod Locator)
#define DNS_TYPE_NIMLOC 0x0020 // 32
// RFC 2052 (Service location)
#define DNS_TYPE_SRV 0x0021 // 33
// ATM Standard something-or-another (ATM Address)
#define DNS_TYPE_ATMA 0x0022 // 34
// RFC 2168 (Naming Authority Pointer)
#define DNS_TYPE_NAPTR 0x0023 // 35
// RFC 2230 (Key Exchanger)
#define DNS_TYPE_KX 0x0024 // 36
// RFC 2538 (CERT)
#define DNS_TYPE_CERT 0x0025 // 37
// A6 Draft (A6)
#define DNS_TYPE_A6 0x0026 // 38
// DNAME Draft (DNAME)
#define DNS_TYPE_DNAME 0x0027 // 39
// Eastlake (Kitchen Sink)
#define DNS_TYPE_SINK 0x0028 // 40
// RFC 2671 (EDNS OPT)
#define DNS_TYPE_OPT 0x0029 // 41
//
// IANA Reserved
//
#define DNS_TYPE_UINFO 0x0064 // 100
#define DNS_TYPE_UID 0x0065 // 101
#define DNS_TYPE_GID 0x0066 // 102
#define DNS_TYPE_UNSPEC 0x0067 // 103
//
// Query only types (1035, 1995)
// - Crawford (ADDRS)
// - TKEY draft (TKEY)
// - TSIG draft (TSIG)
// - RFC 1995 (IXFR)
// - RFC 1035 (AXFR up)
//
#define DNS_TYPE_ADDRS 0x00f8 // 248
#define DNS_TYPE_TKEY 0x00f9 // 249
#define DNS_TYPE_TSIG 0x00fa // 250
#define DNS_TYPE_IXFR 0x00fb // 251
#define DNS_TYPE_AXFR 0x00fc // 252
#define DNS_TYPE_MAILB 0x00fd // 253
#define DNS_TYPE_MAILA 0x00fe // 254
#define DNS_TYPE_ALL 0x00ff // 255
#define DNS_TYPE_ANY 0x00ff // 255
//
// Temp Microsoft types -- use until get IANA approval for real type
//
#define DNS_TYPE_WINS 0xff01 // 64K - 255
#define DNS_TYPE_WINSR 0xff02 // 64K - 254
#define DNS_TYPE_NBSTAT (DNS_TYPE_WINSR)
你还可以在 MSDN 帮助中找到我对 DnsQuery()
函数执行的查询的描述。 我在 CDnsView
类中调用它
void CDnsView::OnFileDnsquery()
{
PDNS_RECORD pdns;
DNS_FREE_TYPE freetype = DnsFreeRecordList;
in_addr inaddr;
char digit[10];
CDnsDialog dns(¶ms);
if (dns.DoModal() == IDOK) {
message.Format("Q? %s %s %s \r\n", dns.m_name,
Type[params.type].title, params.servers);
pEdit->SetSel(pEdit->GetWindowTextLength(),
pEdit->GetWindowTextLength());
pEdit->ReplaceSel(message);
if (res = DnsQuery(dns.m_name, dns.m_type, dns.m_options,
dns.m_ip4array, &pdns, 0)) {
LPVOID lpMsgBuf;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
0, res, MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, 0)) {
message.Format("-ERR: %s \r\n",
(LPCTSTR)lpMsgBuf);
pEdit->SetSel(pEdit->GetWindowTextLength(),
pEdit->GetWindowTextLength());
pEdit->ReplaceSel(message);
LocalFree(lpMsgBuf);
} else {
pEdit->SetSel(pEdit->GetWindowTextLength(),
pEdit->GetWindowTextLength());
pEdit->ReplaceSel
("-ERR FormatMessage failed.?\r\n");
}
return;
}
do {
switch (pdns->wType) {
case DNS_TYPE_A:
inaddr.S_un.S_addr = pdns->Data.A.IpAddress;
message.Format(" A %s [%s]", pdns->pName,
inet_ntoa(inaddr));
break;
case DNS_TYPE_NS:
message.Format(" NS %s %s", pdns->pName,
pdns->Data.NS.pNameHost);
break;
case DNS_TYPE_MD:
message.Format(" MD %s %s", pdns->pName,
pdns->Data.MD.pNameHost);
break;
case DNS_TYPE_MF:
message.Format(" MF %s %s", pdns->pName,
pdns->Data.MF.pNameHost);
break;
case DNS_TYPE_CNAME:
message.Format(" CNAME %s %s", pdns->pName,
pdns->Data.CNAME.pNameHost);
break;
case DNS_TYPE_SOA:
message.Format(" SOA %s nameserv: %s\r\n",
pdns->pName, pdns->Data.SOA.pNamePrimaryServer);
temp.Format(" admin: %s\r\n",
pdns->Data.SOA.pNameAdministrator);
message += temp;
temp.Format(" serial: %u\r\n",
pdns->Data.SOA.dwSerialNo);
message += temp;
temp.Format(" refresh: %u\r\n",
pdns->Data.SOA.dwRefresh);
message += temp;
temp.Format(" ttl: %u\r\n",
pdns->Data.SOA.dwDefaultTtl);
message += temp;
temp.Format(" expire: %u\r\n",
pdns->Data.SOA.dwExpire);
message += temp;
temp.Format(" retry: %u",
pdns->Data.SOA.dwRetry);
message += temp;
break;
case DNS_TYPE_MB:
message.Format(" MB %s %s", pdns->pName,
pdns->Data.MB.pNameHost);
break;
case DNS_TYPE_MG:
message.Format(" MG %s %s", pdns->pName,
pdns->Data.MG.pNameHost);
break;
case DNS_TYPE_MR:
message.Format(" MR %s %s", pdns->pName,
pdns->Data.MR.pNameHost);
break;
//case DNS_TYPE_NULL:
// message.Format(" MB %s %s",pdns->pName,
pdns->Data.Null.MR.pNameHost);
//break;
case DNS_TYPE_WKS:
inaddr.S_un.S_addr = pdns->Data.WKS.IpAddress;
message.Format(" WKS %s [%s] proto:
%d mask: %d", pdns->pName,
inet_ntoa(inaddr),
pdns->Data.WKS.chProtocol,
pdns->Data.WKS.BitMask);
break;
case DNS_TYPE_PTR:
message.Format(" PTR %s %s", pdns->pName,
pdns->Data.PTR.pNameHost);
break;
case DNS_TYPE_HINFO:
message.Format(" HINFO %s", pdns->pName);
for (u_int i = 0; i <
pdns->Data.HINFO.dwStringCount; i++) {
message += "\r\n ";
message += pdns->
Data.HINFO.pStringArray[i];
}
break;
case DNS_TYPE_MINFO:
message.Format(" MINFO %s err: %s name: %s",
pdns->pName, pdns->
Data.MINFO.pNameErrorsMailbox,
pdns->Data.MINFO.pNameMailbox);
break;
case DNS_TYPE_MX:
message.Format(" MX %s %s pref: %d",
pdns->pName, pdns->Data.MX.pNameExchange,
pdns->Data.MX.wPreference);
break;
case DNS_TYPE_TEXT:
message.Format(" TEXT %s", pdns->pName);
for (u_int i = 0; i < pdns->
Data.TXT.dwStringCount; i++) {
message += "\r\n ";
message += pdns->
Data.TXT.pStringArray[i];
}
break;
case DNS_TYPE_RP:
message.Format(" RP %s err: %s name: %s",
pdns->pName,
pdns->Data.RP.pNameErrorsMailbox,
pdns->Data.RP.pNameMailbox);
break;
case DNS_TYPE_AFSDB:
message.Format(" AFSDB %s %s pref: %d",
pdns->pName, pdns->Data.AFSDB.pNameExchange,
pdns->Data.AFSDB.wPreference);
break;
case DNS_TYPE_X25:
message.Format(" X25 %s", pdns->pName);
for (u_int i = 0; i <
pdns->Data.X25.dwStringCount; i++) {
message += "\r\n ";
message += pdns->Data.X25.pStringArray[i];
}
break;
case DNS_TYPE_ISDN:
message.Format(" ISDN %s", pdns->pName);
for (u_int i = 0; i <
pdns->Data.ISDN.dwStringCount; i++) {
message += "\r\n ";
message += pdns->Data.ISDN.pStringArray[i];
}
break;
case DNS_TYPE_RT:
message.Format(" RT %s %s pref: %d",
pdns->pName, pdns->Data.RT.pNameExchange,
pdns->Data.RT.wPreference);
break;
//case DNS_TYPE_SIG:
//break;
//case DNS_TYPE_KEY:
//break;
case DNS_TYPE_AAAA:
message.Format(" AAAA %s %s pref: %d
[", pdns->pName);
for (int i = 0; i < 16; i++) {
sprintf(digit, "%d",
pdns->Data.AAAA.Ip6Address.IP6Byte[i]);
message += digit;
if (i != 15)
message += ".";
}
message += "]";
break;
case DNS_TYPE_SRV:
message.Format(" SRV %s %s port:%d prior:%d
weight:%d", pdns->pName,
pdns->Data.SRV.pNameTarget,
pdns->Data.SRV.wPort,
pdns->Data.SRV.wPriority,
pdns->Data.SRV.wWeight);
break;
//case DNS_TYPE_WINS:
//break;
case DNS_TYPE_WINSR:
message.Format(" NBSTAT %s %s",
pdns->pName, pdns->
Data.WINSR.pNameResultDomain);
break;
default:
message.Format(" unknown: %s type %d",
pdns->pName, pdns->wType);
break;
}
if (pdns->Flags.S.Section == DNSREC_AUTHORITY)
message += " (authority)";
if (pdns->Flags.S.Section == DNSREC_ADDITIONAL)
message += " (additional)";
pEdit->SetSel(pEdit->GetWindowTextLength(),
pEdit->GetWindowTextLength());
pEdit->ReplaceSel(message + "\r\n");
pdns = pdns->pNext;
} while (pdns);
pEdit->SetSel(pEdit->GetWindowTextLength(),
pEdit->GetWindowTextLength());
pEdit->ReplaceSel("\r\n");
DnsRecordListFree(pdns, freetype);
}
}