乘简 发表于 2018-7-27 13:00:04

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

0xAA55 发表于 2018-7-29 00:19:40

我还以为你会写一个构建DNS查询报文结构体的函数呢……
例子够简单,但对于新人而言有点太过于“魔法数字”了,各种钦定量。

元始天尊 发表于 2018-7-31 17:07:12


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]
查看完整版本: DNS域名解析C代码