请问:dns报文怎么填写啊? 还有该如何发送呢? 
有源码更好
谢谢!

解决方案 »

  1.   

    /*
    * DNSCore.h
    * Function: 
    * ◎1,input domain, output IP
          eg,  input("www.163.com") output("202.108.42.72")
    * Author: wim
    * Data: 2005-1-18
    */
    #pragma  once
    #include <winsock2.h>
    class CDNSCore
    {
    public:
    //构造函数
    CDNSCore(const DWORD dwDNSServerIP);
    //析够函数
    ~CDNSCore();

    //公共接口
    //根据输入的Domain,返回IP,失败就返回false,【同步返回】
    bool getDomainIP(const CString &strDomain, CString &strOutIP); protected:
    private:
    //目标DNS的地址
    SOCKADDR_IN m_saDNSServer;
    //本地的Socket
    SOCKET m_sockLocal; //初始化本地socket,并开启新线程接收数据
    bool initLocalSocket(); //接收数据,缓冲区
    static const int RecvBufSize = 4086;
    char m_szRecvBuf[RecvBufSize];
    int m_iRecvDataLen; //用来在析够的时候,终止Recv线程
    CWinThread* m_pThreadRecvData; //接收数据的线程
    static UINT ThreadRecvData(LPVOID pParam); //收到数据,就产生一个事件
    CEvent m_eventRecvData; struct SEND_PACKAGE
    {
    //new ,must be delete
    PBYTE pData;
    int  iDataLen;
    SEND_PACKAGE()
    {
    memset(this,0,sizeof(SEND_PACKAGE));
    }
    }; static const USHORT DNS_FLAG_QR = 0x8000;
    static const USHORT DNS_FLAG_AA = 0x0400;
    static const USHORT DNS_FLAG_TC = 0x0200;
    static const USHORT DNS_FLAG_RD = 0x0100;
    static const USHORT DNS_FLAG_RA = 0x0080;
    static const USHORT DNS_HEAD_SIZE = 12; static const USHORT DNS_RRTYPE_A = 1;
    static const USHORT DNS_RRTYPE_NS = 2;
    static const USHORT DNS_RRTYPE_CNAME = 5;
    static const USHORT DNS_RRTYPE_SOA = 6;
    static const USHORT DNS_RRTYPE_WKS = 11;
    static const USHORT DNS_RRTYPE_PTR = 12;
    static const USHORT DNS_RRTYPE_HINFO = 13;
    static const USHORT DNS_RRTYPE_MX = 15;
    static const USHORT DNS_TAIL_SIZE = 4; struct DNS_REQUEST_HEAD
    {
    /* client query ID number */
    USHORT usSessionID;
    /* qualify contents <see below> */
    USHORT usFlag;
      /* number of questions */
    USHORT usQuestions;
      /* number of answer RRs */
    USHORT usAnswer;
      /* number of authority RRs */
    USHORT usAuthority;
      /* number of additional RRs */
    USHORT usAdditional;

                DNS_REQUEST_HEAD()
    {
    memset(this,0,DNS_HEAD_SIZE);
    }
    };
    struct DNS_REQUEST_TAIL
    {
    //Request Type
    USHORT usRequestType;
    //Request Class
    USHORT usRequestClass; DNS_REQUEST_TAIL()
    {
    memset(this,0,DNS_TAIL_SIZE);
    }
    }; //根据输入的DomainStr 得到一个StrArray
    void getArrayByDomainStr(const CString &strDomain,CStringArray &arrayStr); //组织一个请求Domain IP的包包
    void getPackageRequestIP(SEND_PACKAGE &sendPkg,const CString &strDomain); //解析一个RequestReply的包包
    void processRequestReply(CString &strOutIP); //发送一个包包,删除包包的内容
    bool sendDestPackage(
    const SOCKET sockLocal,
    const SOCKADDR_IN saDest,
    SEND_PACKAGE &sendPackage,
    const USHORT usSendTimes = 1
    );
    //sigh,show
    void HexDump(const unsigned char *buf,int nBufLen);

    };
      

  2.   

    /*
    * DNSCore.cpp
    * Function: 
    * ◎1,input domain, output IP
    eg,  input("www.163.com") output("202.108.42.72")
    * Author: wim
    * Data: 2005-1-18
    */
    #include "stdafx.h"
    #include "DNSCorer.h"
    //构造函数
    CDNSCore::CDNSCore(const DWORD dwDNSServerIP)
    {
    //建立DNSServer的sa
    m_saDNSServer.sin_family = AF_INET;
    m_saDNSServer.sin_addr.s_addr = htonl(dwDNSServerIP); 
    m_saDNSServer.sin_port = htons(53);
    //53  DNSService
    //7   Echo
    //赋初值
    m_sockLocal = INVALID_SOCKET;
    m_pThreadRecvData = NULL;
    memset(m_szRecvBuf,0,RecvBufSize);
    m_iRecvDataLen = 0;
    //初始化本地socket,并开启新线程接收数据
    initLocalSocket();
    }
    //析够函数
    CDNSCore::~CDNSCore()
    {
    if(m_pThreadRecvData)
    {
    TerminateThread(m_pThreadRecvData->m_hThread,519);
    }
    }
    //初始化本地socket,并开启新线程接收数据
    bool CDNSCore::initLocalSocket()
    {
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2),&wsaData); //Init
    m_sockLocal = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(INVALID_SOCKET == m_sockLocal)
    {
    TRACE("WSASocket Error\n");
    return false;
    } //SetTimeOut
    /*
    long lTimeOut = 1000;
    if( SOCKET_ERROR == setsockopt(m_sockToQQServer,SOL_SOCKET, SO_RCVTIMEO, (char*)&lTimeOut, sizeof(long)))
    {
    //TRACE("Set Timeout Error\n");
    return false;
    }*/
    //bind localport
    SOCKADDR_IN saLocal;
    saLocal.sin_family = AF_INET;
    saLocal.sin_port = htons(0X0305);
    saLocal.sin_addr.s_addr = INADDR_ANY;
    if(SOCKET_ERROR == bind(m_sockLocal,(sockaddr *)&saLocal,sizeof(saLocal) ) )
    {
    TRACE("bind Error\n");
    //return false;
    } //create new thread
    m_pThreadRecvData = AfxBeginThread(ThreadRecvData,this); return true;
    }
    //根据输入的Domain,返回IP,失败就返回false,【同步返回】
    bool CDNSCore::getDomainIP(const CString &strDomain, CString &strOutIP)
    {
    //clean out param
    strOutIP.Empty();
    //temp
    //strOutIP.Format("202.108.42.72"); SEND_PACKAGE sendPkg;
    //get a package
    getPackageRequestIP(sendPkg,strDomain);
    //send a package
    sendDestPackage(m_sockLocal,m_saDNSServer,sendPkg); //wait for event
    //如果超时了
    if(WAIT_TIMEOUT == WaitForSingleObject(m_eventRecvData.m_hObject,5000))
    {
    strOutIP.Format("DNSServer超时没有响应");
    return false;
    }
    //得到数据
    else
    {
    //show
    HexDump((const unsigned char*)m_szRecvBuf,m_iRecvDataLen);
    //解析一个RequestReply的包包
    processRequestReply(strOutIP);
    } return true;
    }
      

  3.   

    //解析一个RequestReply的包包
    void CDNSCore::processRequestReply(CString &strOutIP)
    {
    //clean Out Param
    strOutIP.Empty();
    //strOutIP.Format("域名或许是非法的"); PBYTE pData = PBYTE(m_szRecvBuf);
    int pDataPtr = 0;
    //head
    DNS_REQUEST_HEAD dnsHead;
    memcpy((void*)&dnsHead,pData+pDataPtr,DNS_HEAD_SIZE);
    pDataPtr = pDataPtr + DNS_HEAD_SIZE;
    //body,temporary jump to End '\0'
    while(
    pDataPtr < m_iRecvDataLen &&
    0X00 != *(pData+pDataPtr)
    )
    {
    ++pDataPtr;
    }
    ++pDataPtr;
    //Tail
    DNS_REQUEST_TAIL dnsTail;
    memcpy((void*)&dnsTail,pData+pDataPtr,DNS_TAIL_SIZE);
    pDataPtr = pDataPtr + DNS_TAIL_SIZE;
    //RR记录
    USHORT usRedirectPtr = 0;
    USHORT usRecordType = 0;
    USHORT usRecordClass = 0;
    USHORT usTrueDataLen = 0;
    UINT iTrueIP = 0;
    in_addr userIP;
    int iTempIndex = 0;
    CString strElement;
    TRACE("\n\n");
    while(pDataPtr < m_iRecvDataLen)
    {
    // DomainStr 重定向 (2)
    //C0 0C 
    //最首2Bit为11 , 剩下的Bit构成一个指针,指向DomainStr 
    memcpy(&usRedirectPtr,pData+pDataPtr,2);
    pDataPtr = pDataPtr + 2;
    usRedirectPtr = ntohs(usRedirectPtr);
    if(0X00 == usRedirectPtr)
    {
    strOutIP.Format("域名未得到IP,可能是非法域名");
    return ;
    }
    //类型(2)
    memcpy(&usRecordType,pData+pDataPtr,2);
    pDataPtr = pDataPtr + 2;
    usRecordType = ntohs(usRecordType);
    //类(2)
    memcpy(&usRecordClass,pData+pDataPtr,2);
    pDataPtr = pDataPtr + 2;
    usRecordClass = ntohs(usRecordClass);
    //TTL (4)
    pDataPtr = pDataPtr + 4;
    //后续数据长度(2)
    memcpy(&usTrueDataLen,pData+pDataPtr,2);
    pDataPtr = pDataPtr + 2;
    usTrueDataLen = ntohs(usTrueDataLen);
    //一般来说,就是IP地址
    if(DNS_RRTYPE_A == usRecordType)
    {
    memcpy(&iTrueIP,pData+pDataPtr,4);
    userIP.S_un.S_addr = iTrueIP;
    TRACE("Index %d IP [%s]\n",iTempIndex++,inet_ntoa(userIP));
    strElement.Format("%s\r\n",inet_ntoa(userIP));
    strOutIP += strElement;
    }
    pDataPtr = pDataPtr + usTrueDataLen;
    }}
    //组织一个请求Domain IP的包包
    void CDNSCore::getPackageRequestIP(SEND_PACKAGE &sendPkg,const CString &strDomain)
    {
    BYTE byBuf[526] = { 
    /*//www.baidu.com
    0X28, 0X30, 0X01, 0X00, 0X00, 0X01, 0X00, 0X00, 
    0X00, 0X00, 0X00, 0X00, 0X03, 0X77, 0X77, 0X77, 
    0X05, 0X62, 0X61, 0X69, 0X64, 0X75, 0X03, 0X63, 
    0X6F, 0X6D, 0X00, 0X00, 0X01, 0X00, 0X01
    */
    0
    };

    BYTE byTemp = 0;
    int pDataPtr = 0;
    //head(12)
    DNS_REQUEST_HEAD dnsHead;
    dnsHead.usSessionID = htons(0X0305);
    dnsHead.usFlag = htons(DNS_FLAG_RD /*| DNS_FLAG_AA*/);
    dnsHead.usQuestions = htons(0X0001);
    dnsHead.usAnswer = 0X0000;
    dnsHead.usAuthority = 0X0000;
    dnsHead.usAdditional = 0X0000;
    memcpy(byBuf+pDataPtr,&dnsHead,DNS_HEAD_SIZE);
    pDataPtr = pDataPtr + DNS_HEAD_SIZE;
    //body(?)
    {
    CStringArray arrayStr;
    CString strElement;
    //get array
    getArrayByDomainStr(strDomain,arrayStr);
    //loop
    for(int i = 0 ; i < arrayStr.GetCount() ; ++i)
    {
    strElement = arrayStr.GetAt(i);
    //写长度
    byTemp = strElement.GetLength();
    byBuf[pDataPtr] = byTemp; 
    ++pDataPtr;
    //写内容
    memcpy(byBuf+pDataPtr,strElement.GetBuffer(),byTemp);
    pDataPtr = pDataPtr + byTemp;
    }
    //标识DomainStr已经完了
    byBuf[pDataPtr] = 0X00; ++pDataPtr;
    }
    //DNS_REQUEST_TAIL
    DNS_REQUEST_TAIL dnsTail;
    //根据域名查找IP
    dnsTail.usRequestType = htons(DNS_RRTYPE_A);
    //根据IP查找域名
    //dnsTail.usRequestType = htons(DNS_RRTYPE_PTR); //都是一样的
    dnsTail.usRequestClass = htons(DNS_RRTYPE_A);
    memcpy(byBuf+pDataPtr,&dnsTail,DNS_TAIL_SIZE);
    pDataPtr = pDataPtr + 4;
    int iLastLen = pDataPtr;
    //return
    sendPkg.pData = new BYTE[iLastLen];
    memcpy(sendPkg.pData,byBuf,iLastLen);
    sendPkg.iDataLen = iLastLen;
    }
    //根据输入的DomainStr 得到一个StrArray
    void CDNSCore::getArrayByDomainStr(const CString &strDomain,CStringArray &arrayStr)
    {
    //temp
    //218.6.168.225 => www.konlink.net
    //CString strDomain;
    //strDomain.Format("225.6.168.218.in-addr.arpa");
    ////clean out param
    //arrayStr.RemoveAll();
    //local
    BYTE byChar = 0;
    CString strTemp; 
    for(int i = 0 ; i < strDomain.GetLength() ; ++i)
    {
    byChar = strDomain.GetAt(i);
    if('.' == byChar)
    {
    arrayStr.Add(strTemp);
    //reset
    strTemp.Empty();
    }
    else
    {
    strTemp += byChar;
    }
    }
    //heihei, 差点忘了
    if(!(strTemp.IsEmpty()))
    {
    arrayStr.Add(strTemp);
    }}
    //发送一个包包,删除包包的内容
    bool CDNSCore::sendDestPackage(
    const SOCKET sockLocal,
    const SOCKADDR_IN saDest,
    SEND_PACKAGE &sendPackage,
    const USHORT usSendTimes /* = 1 */
    )
    {
    if (
    INVALID_SOCKET == m_sockLocal ||
    sendPackage.iDataLen < 1 || 
    NULL == sendPackage.pData
    )
    {
    return false;
    } bool bRet = true;
    for(USHORT i = 0 ; i < usSendTimes; ++i)
    {
    if(SOCKET_ERROR  == 
    sendto(
    sockLocal,
    (const char*)sendPackage.pData,
    sendPackage.iDataLen,
    0,
    (sockaddr* )&(saDest),
    sizeof(saDest))
    )
    {
    TRACE("sendPackage Fail::::::::%d\n",WSAGetLastError());
    bRet = false;
    }
    else
    {
    bRet = true;
    TRACE("sendPackage IP %s Port %d DataLength %d Success\n",
    inet_ntoa(saDest.sin_addr),
    ntohs(saDest.sin_port),
    sendPackage.iDataLen
    );
    //show
    HexDump(sendPackage.pData,sendPackage.iDataLen);
    //idle
    Sleep(13);
    }
    } delete[] sendPackage.pData;
    sendPackage.pData = NULL;
    return bRet;
    }
    //sigh,show
    void CDNSCore::HexDump(const unsigned char *buf,int nBufLen)
    {
    int i ;
    for(i = 0; i < nBufLen; i++)
    {
    TRACE("%02X ",buf[i]);
    if(i%16 == 15)
    {
    TRACE("\n");

    }
    TRACE("\n");}
    //接收数据的线程
    UINT CDNSCore::ThreadRecvData(LPVOID pParam)
    {
    CDNSCore* pThis = (CDNSCore*)(pParam);

    SOCKADDR_IN saTemp;
    int iFromLen = sizeof(saTemp);
    while(true)
    {
    pThis->m_iRecvDataLen = 
    recvfrom(
    pThis->m_sockLocal,
    pThis->m_szRecvBuf,
    RecvBufSize,
    0,
    (sockaddr* )&(saTemp),
    &iFromLen
    );
    if(pThis->m_iRecvDataLen > 0)
    {
    TRACE("\n\nRecv Something from DNSServer::::::::::%d\n",pThis->m_iRecvDataLen);
    pThis->m_eventRecvData.SetEvent();
    }
    //Idle
    Sleep(1024);
    } return 322;
    }
      

  4.   

    http://www.vckbase.com/document/viewdoc/?id=753
      

  5.   

    熟悉DNS数据包的格式,然后对应的结构体构造