509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
ê@éWy¨  ã            
   @   sœ  d Z ddlmZ ddlmZ ddlZddlZddlZddl	Zddl
ZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZmZ G dd„ dejjƒZG d	d
„ d
ejjƒZG dd„ dejjƒZG dd„ dejjƒZ G dd„ dejjƒZ!G dd„ dejjƒZ"G dd„ de#ƒZ$G dd„ de#ƒZ%d(dd„Z&G dd„ de#ƒZ'dd„ Z(d d!„ Z)ej*j+ddddddfd"d#„Z,d)d&d'„Z-dS )*zDNS Messagesé    )Úabsolute_import)ÚStringIONé   )ÚlongÚxrangeÚstring_typesc               @   s   e Zd ZdZdS )ÚShortHeaderz2The DNS packet passed to from_wire() is too short.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú/usr/lib/python3.6/message.pyr   *   s   r   c               @   s   e Zd ZdZdS )ÚTrailingJunkzEThe DNS packet passed to from_wire() has extra junk at the end of it.N)r	   r
   r   r   r   r   r   r   r   /   s   r   c               @   s   e Zd ZdZdS )ÚUnknownHeaderFieldzVThe header field name was not recognized when converting from text
    into a message.N)r	   r
   r   r   r   r   r   r   r   4   s   r   c               @   s   e Zd ZdZdS )ÚBadEDNSzVOPT record occurred somewhere other than the start of
    the additional data section.N)r	   r
   r   r   r   r   r   r   r   :   s   r   c               @   s   e Zd ZdZdS )ÚBadTSIGzWA TSIG record occurred somewhere other than the end of
    the additional data section.N)r	   r
   r   r   r   r   r   r   r   @   s   r   c               @   s   e Zd ZdZdS )ÚUnknownTSIGKeyz(A TSIG with an unknown key was received.N)r	   r
   r   r   r   r   r   r   r   F   s   r   c               @   sØ   e Zd ZdZd-dd„Zdd„ Zdd„ Zd.d
d„Zdd„ Zdd„ Z	dd„ Z
dd„ Zejjdddfdd„Zejjdddfdd„Zd/dd„Zdddddejjfdd„Zd0d!d"„Zd1d#d$„Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ ZdS )2ÚMessagea,  A DNS message.

    @ivar id: The query id; the default is a randomly chosen id.
    @type id: int
    @ivar flags: The DNS flags of the message.  @see: RFC 1035 for an
    explanation of these flags.
    @type flags: int
    @ivar question: The question section.
    @type question: list of dns.rrset.RRset objects
    @ivar answer: The answer section.
    @type answer: list of dns.rrset.RRset objects
    @ivar authority: The authority section.
    @type authority: list of dns.rrset.RRset objects
    @ivar additional: The additional data section.
    @type additional: list of dns.rrset.RRset objects
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: long
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar options: The EDNS options
    @type options: list of dns.edns.Option objects
    @ivar request_payload: The associated request's EDNS payload size.
    @type request_payload: int
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
    in dns.tsig, and the currently implemented algorithms are
    HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
    HMAC_SHA512.
    @type keyalgorithm: string
    @ivar request_mac: The TSIG MAC of the request message associated with
    this message; used when validating TSIG signatures.   @see: RFC 2845 for
    more information on TSIG fields.
    @type request_mac: string
    @ivar fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @ivar original_id: TSIG original id; defaults to the message's id
    @type original_id: int
    @ivar tsig_error: TSIG error code; default is 0.
    @type tsig_error: int
    @ivar other_data: TSIG other data.
    @type other_data: string
    @ivar mac: The TSIG MAC for this message.
    @type mac: string
    @ivar xfr: Is the message being used to contain the results of a DNS
    zone transfer?  The default is False.
    @type xfr: bool
    @ivar origin: The origin of the zone in messages which are used for
    zone transfers or for DNS dynamic updates.  The default is None.
    @type origin: dns.name.Name object
    @ivar tsig_ctx: The TSIG signature context associated with this
    message.  The default is None.
    @type tsig_ctx: hmac.HMAC object
    @ivar had_tsig: Did the message decoded from wire format have a TSIG
    signature?
    @type had_tsig: bool
    @ivar multi: Is this message part of a multi-message sequence?  The
    default is false.  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type multi: bool
    @ivar first: Is this message standalone, or the first of a multi
    message sequence?  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type first: bool
    @ivar index: An index of rrsets in the message.  The index key is
    (section, name, rdclass, rdtype, covers, deleting).  Indexing can be
    disabled by setting the index to None.
    @type index: dict
    Nc             C   sÂ   |d krt jjƒ | _n|| _d| _g | _g | _g | _g | _d| _	d| _
d| _g | _d| _d | _d | _t jj| _d| _d| _d| _d| _| j| _d| _d| _d | _d | _d| _d| _d| _i | _d S )Nr   r   Ú i,  FTéÿÿÿÿ) ÚdnsZentropyZ	random_16ÚidÚflagsÚquestionÚanswerÚ	authorityÚ
additionalÚednsÚ	ednsflagsÚpayloadÚoptionsÚrequest_payloadÚkeyringÚkeynameÚtsigÚdefault_algorithmÚkeyalgorithmÚrequest_macÚ
other_dataÚ
tsig_errorÚfudgeÚoriginal_idÚmacÚxfrÚoriginÚtsig_ctxÚhad_tsigÚmultiÚfirstÚindex)Úselfr   r   r   r   Ú__init__˜   s:    
zMessage.__init__c             C   s   dt | jƒ d S )Nz<DNS message, ID ú>)Úreprr   )r5   r   r   r   Ú__repr__¸   s    zMessage.__repr__c             C   s   | j ƒ S )N)Úto_text)r5   r   r   r   Ú__str__»   s    zMessage.__str__Tc             K   s  t ƒ }|jd| j ƒ |jdtjjtjj| jƒƒ ƒ tjj| j| j	ƒ}|jdtjj|ƒ ƒ |jdtjj| jƒ ƒ | j
dkrÂ|jd| j
 ƒ | j	dkr²|jdtjj| j	ƒ ƒ |jd| j ƒ tjj| jƒ}|rà|jd	ƒ n
|jd
ƒ x.| jD ]$}|j|j||f|Žƒ |jdƒ qòW |�r,|jdƒ n
|jdƒ x0| jD ]&}|j|j||f|Žƒ |jdƒ �q>W |�rz|jdƒ n
|jdƒ x0| jD ]&}|j|j||f|Žƒ |jdƒ �qŒW |jdƒ x0| jD ]&}|j|j||f|Žƒ |jdƒ �qÈW |jƒ dd… S )z¶Convert the message to text.

        The I{origin}, I{relativize}, and any other keyword
        arguments are passed to the rrset to_wire() method.

        @rtype: string
        zid %d
z
opcode %s
z	rcode %s
z	flags %s
r   zedns %s
z
eflags %s
zpayload %d
z;ZONE
z
;QUESTION
Ú
z;PREREQ
z;ANSWER
z;UPDATE
z;AUTHORITY
z;ADDITIONAL
Nr   r   )r   Úwriter   r   Úopcoder:   Ú
from_flagsr   Úrcoder   r   Zedns_to_textr    Ú	is_updater   r   r   r   Úgetvalue)r5   r/   Ú
relativizeÚkwÚsZrcrA   Úrrsetr   r   r   r:   ¾   sJ    	





zMessage.to_textc             C   sæ   t |tƒsdS | j|jkrdS | j|jkr.dS x| jD ]}||jkr6dS q6W x|jD ]}|| jkrTdS qTW x| jD ]}||jkrrdS qrW x|jD ]}|| jkr�dS q�W x| jD ]}||jkr®dS q®W x|jD ]}|| jkrÌdS qÌW dS )zŠTwo messages are equal if they have the same content in the
        header, question, answer, and authority sections.
        @rtype: boolFT)Ú
isinstancer   r   r   r   r   r   )r5   ÚotherÚnr   r   r   Ú__eq__õ   s2    






zMessage.__eq__c             C   s   | j |ƒ S )z0Are two messages not equal?
        @rtype: bool)rJ   )r5   rH   r   r   r   Ú__ne__  s    zMessage.__ne__c             C   s®   |j tj j@ dks:| j|jks:tjj| j ƒtjj|j ƒkr>dS tjj|j |jƒtjjkr\dS tjj	| j ƒrndS x| j
D ]}||j
krvdS qvW x|j
D ]}|| j
kr”dS q”W dS )z1Is other a response to self?
        @rtype: boolr   FT)r   r   ÚQRr   r>   r?   r@   r   ZNOERRORrA   r   )r5   rH   rI   r   r   r   Úis_response  s"    


zMessage.is_responsec             C   sD   || j krdS || jkrdS || jkr*dS || jkr8dS tdƒ‚d S )Nr   r   é   é   zunknown section)r   r   r   r   Ú
ValueError)r5   Úsectionr   r   r   Úsection_number-  s    



zMessage.section_numberFc	             C   s    | j |ƒ|||||f}	|sb| jdk	r>| jj|	ƒ}
|
dk	rb|
S n$x"|D ]}
|
j|||||ƒrD|
S qDW |sjt‚tjj|||||ƒ}
|j|
ƒ | jdk	rœ|
| j|	< |
S )a  Find the RRset with the given attributes in the specified section.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @raises KeyError: the RRset was not found and create was False
        @rtype: dns.rrset.RRset objectN)	rR   r4   ÚgetÚmatchÚKeyErrorr   rF   ZRRsetÚappend)r5   rQ   ÚnameÚrdclassÚrdtypeÚcoversÚdeletingÚcreateÚforce_uniqueÚkeyrF   r   r   r   Ú
find_rrset9  s"    




zMessage.find_rrsetc	       
      C   s:   y| j ||||||||ƒ}	W n tk
r4   d}	Y nX |	S )a  Get the RRset with the given attributes in the specified section.

        If the RRset is not found, None is returned.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @rtype: dns.rrset.RRset object or NoneN)r_   rU   )
r5   rQ   rW   rX   rY   rZ   r[   r\   r]   rF   r   r   r   Ú	get_rrsetg  s    
zMessage.get_rrsetr   c          	   K   sR  |dkr| j dkr| j }nd}|dk r,d}n|dkr8d}tjj| j| j||ƒ}x"| jD ]}|j|j|j	|j
ƒ qVW x"| jD ]}|jtjj|f|Ž qzW x"| jD ]}|jtjj|f|Ž qžW | jdkrÜ|j| j| j| j| jƒ x"| jD ]}|jtjj|f|Ž qäW |jƒ  | jdk	�rJ|j| j| j| j | j| j| j| j| j| j ƒ |j!| _!|j"ƒ S )a7  Return a string containing the message in DNS compressed wire
        format.

        Additional keyword arguments are passed to the rrset to_wire()
        method.

        @param origin: The origin to be appended to any relative names.
        @type origin: dns.name.Name object
        @param max_size: The maximum size of the wire format output; default
        is 0, which means 'the message's request payload, if nonzero, or
        65536'.
        @type max_size: int
        @raises dns.exception.TooBig: max_size was exceeded
        @rtype: string
        r   iÿÿ  i   N)#r"   r   ZrendererZRendererr   r   r   Zadd_questionrW   rY   rX   r   Z	add_rrsetÚANSWERr   Ú	AUTHORITYr   Zadd_ednsr   r    r!   r   Ú
ADDITIONALZwrite_headerr$   Zadd_tsigr#   r+   r,   r*   r)   r(   r'   r-   Zget_wire)r5   r/   Zmax_sizerD   ÚrrF   r   r   r   Úto_wireŠ  s6    

zMessage.to_wirei,  r   c             C   st   || _ |dkr$t| j jƒ ƒd | _nt|tƒr:tjj|ƒ}|| _|| _	|| _
|dkr^| j| _n|| _|| _|| _dS )aw  When sending, a TSIG signature using the specified keyring
        and keyname should be added.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param fudge: TSIG time fudge; default is 300 seconds.
        @type fudge: int
        @param original_id: TSIG original id; defaults to the message's id
        @type original_id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param algorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm
        Nr   )r#   ÚlistÚkeysr$   rG   r   r   rW   Ú	from_textr'   r+   r   r,   r*   r)   )r5   r#   r$   r+   r,   r*   r)   Ú	algorithmr   r   r   Úuse_tsig¸  s    

zMessage.use_tsigé   c             C   sŒ   |dks|dkrd}|dkr d}|dkr,|}|dk rFd}d}d}g }n$|t dƒM }||d> O }|dkrjg }|| _|| _|| _|| _|| _dS )	a_  Configure EDNS behavior.
        @param edns: The EDNS level to use.  Specifying None, False, or -1
        means 'do not use EDNS', and in this case the other parameters are
        ignored.  Specifying True is equivalent to specifying 0, i.e. 'use
        EDNS0'.
        @type edns: int or bool or None
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param request_payload: The EDNS payload size to use when sending
        this message.  If not specified, defaults to the value of payload.
        @type request_payload: int or None
        @param options: The EDNS options
        @type options: None or list of dns.edns.Option objects
        @see: RFC 2671
        NFr   Tr   l   ÿ~ é   r   )r   r   r   r    r!   r"   )r5   r   r   r    r"   r!   r   r   r   Úuse_ednsã  s(    zMessage.use_ednsc             C   sL   |r*| j dk r| jƒ  |  jtjjO  _n| j dkrH|  jtjj M  _dS )a
  Enable or disable 'DNSSEC desired' flag in requests.
        @param wanted: Is DNSSEC desired?  If True, EDNS is enabled if
        required, and then the DO bit is set.  If False, the DO bit is
        cleared if EDNS is enabled.
        @type wanted: bool
        r   N)r   rm   r   r   r   ZDO)r5   Zwantedr   r   r   Úwant_dnssec  s    

zMessage.want_dnssecc             C   s   t jj| j| jƒS )z.Return the rcode.
        @rtype: int
        )r   r@   r?   r   r   )r5   r   r   r   r@     s    zMessage.rcodec             C   sj   t jj|ƒ\}}|  jdM  _|  j|O  _|  jtdƒM  _|  j|O  _| jdkrf| jdk rfd| _dS )zPSet the rcode.
        @param rcode: the rcode
        @type rcode: int
        iðÿ  iÿÿÿ r   N)r   r@   Úto_flagsr   r   r   r   )r5   r@   ÚvalueZevaluer   r   r   Ú	set_rcode"  s    zMessage.set_rcodec             C   s   t jj| jƒS )z/Return the opcode.
        @rtype: int
        )r   r>   r?   r   )r5   r   r   r   r>   /  s    zMessage.opcodec             C   s(   |  j dM  _ |  j tjj|ƒO  _ dS )zTSet the opcode.
        @param opcode: the opcode
        @type opcode: int
        iÿ‡  N)r   r   r>   ro   )r5   r>   r   r   r   Ú
set_opcode5  s    zMessage.set_opcode)N)NT)Nr   )r   r   rk   NN)T)r	   r
   r   r   r6   r9   r;   r:   rJ   rK   rM   rR   r   Ú	rdatatypeÚNONEr_   r`   re   r%   r&   rj   rm   rn   r@   rq   r>   rr   r   r   r   r   r   K   s0   K
 
7
-
!
.) 
*
r   c               @   s2   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdS )Ú_WireReaderaþ  Wire format reader.

    @ivar wire: the wire-format message.
    @type wire: string
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar current: When building a message object from wire format, this
    variable contains the offset from the beginning of wire of the next octet
    to be read.
    @type current: int
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar one_rr_per_rrset: Put each RR into its own RRset?
    @type one_rr_per_rrset: bool
    @ivar ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    Fc             C   s@   t jj|ƒ| _|| _d| _d| _t jj| _	|| _
|| _|| _d S )Nr   F)r   ZwiredataZ
maybe_wrapÚwireÚmessageÚcurrentÚupdatingÚ
rdataclassÚINÚzone_rdclassÚquestion_onlyÚone_rr_per_rrsetÚignore_trailing)r5   rv   rw   r}   r~   r   r   r   r   r6   U  s    
z_WireReader.__init__c          	   C   sÀ   | j r|dkrtjj‚x¤td|ƒD ]–}tjj| j| jƒ\}}| j	j
dk	rV|j| j	j
ƒ}| j| | _tjd| j| j| jd … ƒ\}}| jd | _| j	j| j	j|||ddd� | j r"|| _q"W dS )z¸Read the next I{qcount} records from the wire data and add them to
        the question section.
        @param qcount: the number of questions in the message
        @type qcount: intr   r   Nz!HHé   T)r\   r]   )ry   r   Ú	exceptionÚ	FormErrorr   rW   Ú	from_wirerv   rx   rw   r/   rC   ÚstructÚunpackr_   r   r|   )r5   ÚqcountÚiÚqnameÚusedrY   rX   r   r   r   Ú_get_question`  s    z_WireReader._get_questionc             C   sH  | j s| jrd}nd}d}�x&td|ƒD �]}| j}tjj| j| jƒ\}}|}	| jj	dk	rh|j
| jj	ƒ}| j| | _tjd| j| j| jd … ƒ\}
}}}| jd | _|
tjjk�rn|| jjk	sÄ|rÈt‚|| j_|| j_|d@ d? | j_g | j_| j}|}xj|dk�rdtjd	| j||d
 … ƒ\}}|d
 }tjj|| j||ƒ}| jjj|ƒ || }|d
 | }qüW d}�nÆ|
tjjk�rH|| jjk�o”||d k�sœt‚| jjdk�r²tdƒ‚| jjj|	ƒ}|dk�rÖtd| ƒ‚|	| j_tjj| j| j|ƒ\| j_| j_ tjj!| j|	|t"t#j#ƒ ƒ| jj$|| j|| jj%| jj&| jj'ƒ| j_%d| j_(nì|dk �rVd}| j �r†|tj)j*k�sz|tj)j+k�r†|}| j,}nd}|tj)j*k�s´|tj)j+k�rÂ|| jj-k�rÂtjj+}d}n&tj.j||
| j| j|| jj	ƒ}|j/ƒ }| jj0�r|
tjj1k�rd}| jj2||||
||d|ƒ}|dk	�r4|j3||ƒ | j| | _q(W dS )a/  Read the next I{count} records from the wire data and add them to
        the specified section.
        @param section: the section of the message to which to add records
        @type section: list of dns.rrset.RRset objects
        @param count: the number of records to read
        @type count: intTFr   Nz!HHIHé
   i  ÿ rl   z!HHr€   r   z"got signed message without keyringzkey '%s' unknown)4ry   r~   r   rx   r   rW   rƒ   rv   rw   r/   rC   r„   r…   rs   ÚOPTr   r   r    r   r   r!   Zoption_from_wirerV   ZTSIGr   r#   r   rS   r$   r%   Zget_algorithm_and_macr'   r-   ZvalidateÚintÚtimer(   r0   r2   r3   r1   rz   ÚANYrt   r|   r   ÚrdatarZ   r.   ZSOAr_   Úadd)r5   rQ   Úcountr]   Zseen_optr‡   Zrr_startrW   r‰   Zabsolute_namerY   rX   ÚttlZrdlenrx   ZoptslenZotypeZolenÚoptZsecretr[   rZ   ÚrdrF   r   r   r   Ú_get_sectionx  s¤     








z_WireReader._get_sectionc             C   sä   t | jƒ}|dk rt‚tjd| jdd… ƒ\| j_| j_}}}}d| _t	j
j| jjƒr\d| _| j|ƒ | jrpdS | j| jj|ƒ | j| jj|ƒ | j| jj|ƒ | j r¶| j|kr¶t‚| jjrà| jjrà| jj rà| jjj| jƒ dS )zNRead a wire format DNS message and build a dns.message.Message
        object.é   z!HHHHHHNT)Úlenrv   r   r„   r…   rw   r   r   rx   r   r>   rA   ry   rŠ   r}   r–   r   r   r   r   r   r2   r0   r1   Úupdate)r5   Úlr†   ZancountZaucountZadcountr   r   r   ÚreadÛ  s$    
*

z_WireReader.readN)FFF)r	   r
   r   r   r6   rŠ   r–   r›   r   r   r   r   ru   >  s    

cru   r   FTc             C   sP   t dd�}||_||_||_||_||_||_||_t| |||	|
ƒ}|j	ƒ  |S )a)  Convert a DNS wire format message into a message
    object.

    @param keyring: The keyring to use if the message is signed.
    @type keyring: dict
    @param request_mac: If the message is a response to a TSIG-signed request,
    I{request_mac} should be set to the MAC of that request.
    @type request_mac: string
    @param xfr: Is this message part of a zone transfer?
    @type xfr: bool
    @param origin: If the message is part of a zone transfer, I{origin}
    should be the origin name of the zone.
    @type origin: dns.name.Name object
    @param tsig_ctx: The ongoing TSIG context, used when validating zone
    transfers.
    @type tsig_ctx: hmac.HMAC object
    @param multi: Is this message part of a multiple message sequence?
    @type multi: bool
    @param first: Is this message standalone, or the first of a multi
    message sequence?
    @type first: bool
    @param question_only: Read only up to the end of the question section?
    @type question_only: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    @param ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @raises ShortHeader: The message is less than 12 octets long.
    @raises TrailingJunk: There were octets in the message past the end
    of the proper DNS message.
    @raises BadEDNS: An OPT record was in the wrong section, or occurred more
    than once.
    @raises BadTSIG: A TSIG record was not the last record of the additional
    data section.
    @rtype: dns.message.Message objectr   )r   )
r   r#   r(   r.   r/   r0   r2   r3   ru   r›   )rv   r#   r(   r.   r/   r0   r2   r3   r}   r~   r   ÚmÚreaderr   r   r   rƒ   ô  s    (

rƒ   c               @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú_TextReadera  Text format reader.

    @ivar tok: the tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    @ivar last_name: The most recently read name when building a message object
    from text format.
    @type last_name: dns.name.Name object
    c             C   s.   || _ tjj|ƒ| _d | _tjj| _d| _	d S )NF)
rw   r   Z	tokenizerÚ	TokenizerÚtokÚ	last_namerz   r{   r|   ry   )r5   Útextrw   r   r   r   r6   >  s
    
z_TextReader.__init__c             C   sÀ  | j jƒ }|j}|dkr*| j jƒ | j_�nˆ|dkrŒx>| j jƒ }|jƒ sT| j j|ƒ P | jjt	jj
|jƒB | j_q4W t	jj| jjƒrˆd| _�n&|dkr¼| j jƒ | j_| jj| jjd> B | j_nö|dk�r| jjdk rÚd| j_xÖ| j jƒ }|jƒ � sþ| j j|ƒ P | jjt	jj|jƒB | j_qÜW n”|dk�rN| j jƒ | j_| jjdk �r²d| j_nd|d	k�r„| j jƒ }| jjt	jjt	jj
|ƒƒB | j_n.|d
k�r®| j jƒ }| jjt	jj
|ƒƒ nt‚| j jƒ  dS )z5Process one line from the text format header section.r   r   Tr   rl   Zeflagsr   r    r>   r@   N)r    rS   rp   Zget_intrw   r   Úis_identifierÚungetr   r   rh   r>   rA   ry   r   r   Zedns_from_textr    Z
get_stringro   rq   r@   r   Úget_eol)r5   rQ   ÚtokenZwhatr¢   r   r   r   Ú_header_lineE  sR    











z_TextReader._header_linec             C   sô   | j jdd�}|jƒ s(tjj|jdƒ| _| j}| j jƒ }|jƒ sHtj	j
‚y,tjj|jƒ}| j jƒ }|jƒ srtj	j
‚W n: tj	j
k
r”   tj	j
‚Y n tk
r®   tjj}Y nX tjj|jƒ}| jj| jj|||ddd� | jræ|| _| j jƒ  dS )z7Process one line from the text format question section.T)Úwant_leadingN)r\   r]   )r    rS   Úis_whitespacer   rW   rh   rp   r¡   r£   r�   ÚSyntaxErrorrz   Ú	Exceptionr{   rs   rw   r_   r   ry   r|   r¥   )r5   rQ   r¦   rW   rX   rY   r   r   r   Ú_question_lines  s.    

z_TextReader._question_linec             C   sÌ  d}| j jdd�}|jƒ s,tjj|jdƒ| _| j}| j jƒ }|jƒ sLtj	j
‚y*t|jdƒ}| j jƒ }|jƒ sttj	j
‚W n6 tj	j
k
r–   tj	j
‚Y n tk
r¬   d}Y nX yPtjj|jƒ}| j jƒ }|jƒ sØtj	j
‚|tjjksò|tjjk� rü|}| j}W n> tj	j
k
�r    tj	j
‚Y n tk
�r<   tjj}Y nX tjj|jƒ}| j jƒ }|jƒ �sŠ| j j|ƒ tjj||| j dƒ}|jƒ }	nd}tjj}	| jj|||||	|d| jƒ}
|dk	�rÈ|
j||ƒ dS )zfProcess one line from the text format answer, authority, or
        additional data sections.
        NT)r¨   r   )r    rS   r©   r   rW   rh   rp   r¡   r£   r�   rª   r�   r«   rz   r�   rt   r|   r{   rs   Úis_eol_or_eofr¤   r�   rZ   rw   r_   ry   r‘   )r5   rQ   r[   r¦   rW   r“   rX   rY   r•   rZ   rF   r   r   r   Ú_rr_line�  sT    









z_TextReader._rr_linec             C   sä   | j }d}xÔ| jjddƒ}|jƒ r$P |jƒ rÈ|jjƒ }|dkrF| j }nv|dksV|dkrf| j}| jj	}nV|dksv|dkr†| j
}| jj}n6|dks–|d	kr¦| j
}| jj}n|d
kr¼| j
}| jj}| jjƒ  q| jj|ƒ ||ƒ qW dS )zNRead a text format DNS message and build a dns.message.Message
        object.NTZHEADERZQUESTIONZZONEra   ZPREREQrb   ZUPDATErc   )r§   r    rS   r­   Z
is_commentrp   Úupperr¬   rw   r   r®   r   r   r   r¥   r¤   )r5   Zline_methodrQ   r¦   Úur   r   r   r›   Å  s4    




z_TextReader.readN)	r	   r
   r   r   r6   r§   r¬   r®   r›   r   r   r   r   rž   ,  s   .5rž   c             C   s   t ƒ }t| |ƒ}|jƒ  |S )zæConvert the text format message into a message object.

    @param text: The text format message.
    @type text: string
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message object)r   rž   r›   )r¢   rœ   r�   r   r   r   rh   å  s    
rh   c          
   C   sF   t }d}t| |ƒr"t| |ƒ} d}nd}zt| ƒ}W d|r@| jƒ  X |S )a  Read the next text format message from the specified file.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message objectZrUTFN)r   rG   Úopenrh   Úclose)ÚfZstr_typeZoptsZ
want_closerœ   r   r   r   Ú	from_fileú  s    	


r´   c	             C   s  t | tƒrtjj| ƒ} t |tƒr,tjj|ƒ}t |tƒrBtjj|ƒ}tƒ }	|	 jtjj	O  _|	j
|	j| ||ddd� i }
|dk	r’||
d< |dkr’d}|dk	r®||
d< |dkr®d}|dk	rÊ||
d< |dkrÊd}|dk	ræ||
d< |dkræd}||
d	< |	jf |
Ž |	j|ƒ |	S )
aV  Make a query message.

    The query name, type, and class may all be specified either
    as objects of the appropriate type, or as strings.

    The query will have a randomly chosen query id, and its DNS flags
    will be set to dns.flags.RD.

    @param qname: The query name.
    @type qname: dns.name.Name object or string
    @param rdtype: The desired rdata type.
    @type rdtype: int
    @param rdclass: The desired rdata class; the default is class IN.
    @type rdclass: int
    @param use_edns: The EDNS level to use; the default is None (no EDNS).
    See the description of dns.message.Message.use_edns() for the possible
    values for use_edns and their meanings.
    @type use_edns: int or bool or None
    @param want_dnssec: Should the query indicate that DNSSEC is desired?
    @type want_dnssec: bool
    @param ednsflags: EDNS flag values.
    @type ednsflags: int
    @param payload: The EDNS sender's payload field, which is the maximum
    size of UDP datagram the sender can handle.
    @type payload: int
    @param request_payload: The EDNS payload size to use when sending
    this message.  If not specified, defaults to the value of payload.
    @type request_payload: int or None
    @param options: The EDNS options
    @type options: None or list of dns.edns.Option objects
    @see: RFC 2671
    @rtype: dns.message.Message objectT)r\   r]   Nr   r   r    r"   r!   r   )rG   r   r   rW   rh   rs   rz   r   r   ÚRDr_   r   rm   rn   )rˆ   rY   rX   rm   rn   r   r    r"   r!   rœ   Úkwargsr   r   r   Ú
make_query  s>    $



r·   é    é,  c             C   sº   | j tj j@ rtjjdƒ‚tjj| jƒ}tj j| j tj j@ B |_ |rV| j tj j	O  _ |j
| jƒ ƒ t| jƒ|_| jdkrŒ|jdd|| jƒ | jr¶|j| j| j|ddd| jƒ | j|_|S )a  Make a message which is a response for the specified query.
    The message returned is really a response skeleton; it has all
    of the infrastructure required of a response, but none of the
    content.

    The response's question section is a shallow copy of the query's
    question section, so the query's question RRsets should not be
    changed.

    @param query: the query to respond to
    @type query: dns.message.Message object
    @param recursion_available: should RA be set in the response?
    @type recursion_available: bool
    @param our_payload: payload size to advertise in EDNS responses; default
    is 8192.
    @type our_payload: int
    @param fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @rtype: dns.message.Message objectz&specified query message is not a queryr   Nr   )r   r   rL   r�   r‚   rw   r   r   rµ   ZRArr   r>   rf   r   r   rm   r    r1   rj   r#   r$   r'   r-   r(   )ZqueryZrecursion_availableZour_payloadr+   Zresponser   r   r   Úmake_response\  s    
rº   )
Nr   FNNFTFFF)Fr¸   r¹   ).r   Z
__future__r   Úior   r„   rŽ   Zdns.ednsr   Zdns.exceptionZ	dns.flagsZdns.nameZ
dns.opcodeZdns.entropyZ	dns.rcodeZ	dns.rdataZdns.rdataclassZdns.rdatatypeZ	dns.rrsetZdns.rendererZdns.tsigZdns.wiredataZ_compatr   r   r   r�   r‚   r   r   ZDNSExceptionr   r   r   r   Úobjectr   ru   rƒ   rž   rh   r´   rz   r{   r·   rº   r   r   r   r   Ú<module>   sX      v 7   
5 :F 