Dns解析(下)

Dns解析()

上篇讲述了Dns的查询包和发送,本文将分析Dns的返回包。

下面这段程序是从Dns服务器上得到dns的返回包:

ID_Packet=new DatagramPacket(new byte[Constant.DNSUDPLEN],

Constant.DNSUDPLEN);

ID_Socket.receive(ID_Packet);

这里的变量已在上篇中定义了,Constant.DNSUDPLEN512

接下来就只要将这数据解压缩就可以了。这里就涉及了RR的格式了(Resource Record Format)。

     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                                               /
    /                      NAME                     /
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     CLASS                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TTL                      |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   RDLENGTH                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
    /                     RDATA                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

这是在rfc文档中定义的RR格式。

NAME:就是在question中的QNAME

TYPEquestion中的QTYPE

CLASSquestion中的QCLASS

RDLENGTHRDATA的长度;

RDATA:返回的数据,这才是真正有用的数据,也是我们要解析的东西。

 

因为其数据是被压缩的,所以得想知道他的压缩格式:

0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 1  1|                OFFSET                   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

他的压缩方式是将在数据中重复出现的字符放在一起,然后再字符出现的地方加上一个偏移位置,即如上图所示,16位的数据以11开头,后跟偏移量。偏移量是从信息的头部开始算得。下面是一个rfc文档中的例子:

0  1   2   3   4  5  6  7   8  9  A   B  C  D  E  F

       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    20 |           1           |           F           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    22 |           3           |           I           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    24 |           S           |           I           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    26 |           4           |           A           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    28 |           R           |           P           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    30 |           A           |           0           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

  
  
   
    
  
  
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    40 |           3           |           F           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    42 |           O           |           O           |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    44 | 1  1|                20                       |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   

这个结果是:在40位置的域名是FOO.F.ISI.ARPA

了解了他的压缩方式,解析就简单了。

上篇中在Header中我们已提到ANCOUNT这个字段,他表示的是回复中结果的数目,我们相见他解析出来:

public int getAnswerCount()

    {

        int INDEX=6;

        byte[] AnCountArray=new byte[2];

       

        System.arraycopy(message,INDEX,AnCountArray,0,2);

        return DnsTool.BytesToInt(AnCountArray);//byte[]变为int

    }

得到了ANCOUNT,就可以解释结果了:

public Vector parseAnswer()

    {

        int theOffset=8;

        int pos=thePosOfAnswer;(thePosOfAnswer是你发得dns包的长度)

        int i=0,p;

        int RDlength;

        byte[] tmp;

        String Name="";

Vector IV_ Answer=new Vector();

       

        //get return name from message

        while(i<getAnswerCount())

        {

            Name="";

            //get type

            pos+=2;

            tmp=new byte[2];

            System.arraycopy(message,pos,tmp,0,2);

           

            if(DnsTool.BytesToInt(tmp)==Constant.TYPE_MX)//check the type

            {

                pos+=theOffset;

                //get RDlength

                tmp=new byte[2];

                System.arraycopy(message,pos,tmp,0,2);

                RDlength=DnsTool.BytesToInt(tmp);

               

                pos+=4;

                p=pos;

                while((pos-p)<RDlength-2)

                {

                    if((message[pos]&0xC0)==0xC0)

                    {

                        //this is a offset

                        Name+=getPrior((message[pos]&0x3F)

|(message[pos+1]&0xFF));

                        pos+=2;

                    }

                    else

                    {

                        //not offset

                        tmp=new byte[message[pos]];

                        System.arraycopy(message,pos+1,tmp,0,tmp.length);

                        pos+=message[pos]+1;

                       

                        if(message[pos]!=0)

                            Name+=new String(tmp)+".";

                        else

                            Name+=new String(tmp);

                    }

                }

            }

         IV_Answer.addElement(Name);  

         i++;  

        }

    }

函数Stirng getPrior(int)是根据其偏移量等到所要的字符串,这是一个递归函数:

private String getPrior(int j)

    {

        byte[] tmp;

        String Name="";

       

        while(message[j]!=0)

        {

            if((message[j]&0xC0)==0xC0)

            {

                String mid=getPrior((message[j]&0x3F)|(message[j+1]&0xFF));

                Name+=mid;

                j+=mid.length()+1;

            }

            else

            {

                tmp=new byte[message[j]];

                System.arraycopy(message,j+1,tmp,0,tmp.length);

                j+=message[j]+1;

                if(message[j]!=0)

                    Name+=new String(tmp)+".";

                else

                    Name+=new String(tmp);

            }

        }

        return Name;

    }

我们只介绍了mail地址的dns解析,其他几类都大同小异,如需要可参考rfc1035

文章不免有错,请各位多指点craks@263.net

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值