DNS域名解析C代码
#include <stdio.h>#include <stdlib.h>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32.lib")
//定义DNS数据 ID tag numq numa numa1 numa2
char DNS_DATA[]={0x12,0x34,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x03,0x77,0x77,0x77,0x06,0x30,0x78,0x61,0x61,0x35,0x35,0x03,0x63,0x6F,0x6d,0x00,//03 www 06 0xaa55 03 com 00
0x00,0x01,0x00,0x01};//前两字节为1表示A记录; 后两字节为1表示DNS_HDR+域名+DNS_QER
int main(int argc,char* argv[])
{
WORD socketVersion = MAKEWORD(2,2);
WSADATA wsaData;
if(WSAStartup(socketVersion, &wsaData) != 0)
{
printf("error");
return 0;
}
//创建UDP通信套接字
SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(53);//DNS远程端口固定为53
sin.sin_addr.S_un.S_addr = inet_addr("114.114.114.114");//DNS服务器IP地址,可以填网关地址如(192.168.0.1)
//发送域名数据
sendto(sclient, DNS_DATA, sizeof(DNS_DATA), 0, (SOCKADDR *)&sin, sizeof(sin));
char recvData;
int ret = recv(sclient, recvData, 255, 0);//等待接收数据
if(ret > 0)//收到大于0的数据
{
for(int i=0;i<ret;i++)//以16进制格式打印出来
{
printf("%02X ",(unsigned char)recvData);
}
}
closesocket(sclient);
WSACleanup();
return 0;
}
返回:
12 34 81 80 00 01 00 01 00 00 00 00 03 77 77 77 06 30 78 61 61 35 35 03 63 6F 6D
00 00 01 00 01 C0 0C 00 01 00 01 00 01 42 00 00 04 8B C7 98 76
可以看到,8B C7 98 76就是为www.0xaa55.com的IP地址:139.199.152.118
我还以为你会写一个构建DNS查询报文结构体的函数呢……
例子够简单,但对于新人而言有点太过于“魔法数字”了,各种钦定量。
LPHOSTENT EXPORT gethostbyname(INCONST CHAR FAR* name)
{
enum addr_type
{
GH_INVALID,
GH_IPV6,
GH_IPV4,
GH_RFC1123_DNS
};
typedef enum addr_type addr_type;
addr_type addr;
int ret = 0;
char* found = 0;
DNS_STATUS dns_status = {0};
/* include/WinDNS.h -- look up DNS_RECORD on MSDN */
PDNS_RECORD dp = 0;
PWINSOCK_THREAD_BLOCK p;
LPHOSTENT Hostent;
addr = GH_INVALID;
p = NtCurrentTeb()->WinSockData;
if (!p || !WSAINITIALIZED)
{
WSASetLastError( WSANOTINITIALISED );
return NULL;
}
check_hostent(&p->Hostent); /*XXX alloc_hostent*/
/* Hostname NULL - behave like gethostname */
if(name == NULL)
{
ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
if(ret)
{
WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA??
return NULL;
}
return p->Hostent;
}
/* Is it an IPv6 address? */
found = strstr(name, ":");
if( found != NULL )
{
addr = GH_IPV6;
goto act;
}
/* Is it an IPv4 address? */
if (!isalpha(name))
{
addr = GH_IPV4;
goto act;
}
addr = GH_RFC1123_DNS;
/* Broken out in case we want to get fancy later */
act:
switch(addr)
{
case GH_IPV6:
WSASetLastError(STATUS_NOT_IMPLEMENTED);
return NULL;
break;
case GH_INVALID:
WSASetLastError(WSAEFAULT);
return NULL;
break;
/* Note: If passed an IP address, MSDN says that gethostbyname()
treats it as an unknown host.
This is different from the unix implementation. Use inet_addr()
*/
case GH_IPV4:
case GH_RFC1123_DNS:
/* DNS_TYPE_A: include/WinDNS.h */
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
/* Look for the DNS name in the hosts file */
Hostent = FindEntryInHosts(name);
if (Hostent)
return Hostent;
dns_status = DnsQuery_A(name,
DNS_TYPE_A,
DNS_QUERY_STANDARD,
0,
/* extra dns servers */ &dp,
0);
if(dns_status == 0)
{
//ASSERT(dp->wType == DNS_TYPE_A);
//ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
PDNS_RECORD curr;
for(curr=dp;
curr != NULL && curr->wType != DNS_TYPE_A;
curr = curr->pNext )
{
WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
/*empty */
}
if(curr)
{
WS_DbgPrint(MID_TRACE,("populating hostent\n"));
WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
populate_hostent(p->Hostent,
(PCHAR)curr->pName,
curr->Data.A.IpAddress);
DnsRecordListFree(dp, DnsFreeRecordList);
return p->Hostent;
}
else
{
DnsRecordListFree(dp, DnsFreeRecordList);
}
}
WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
dns_status));
WSASetLastError(WSAHOST_NOT_FOUND);
return NULL;
break;
default:
WSASetLastError(WSANO_RECOVERY);
return NULL;
break;
}
WSASetLastError(WSANO_RECOVERY);
return NULL;
}
页:
[1]