a
    sd_                  
   @   s  d 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ZddlZddlZddl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jjZG dd dej j!Z"e# $e"j% G dd dZ&G dd de&Z'dd Z(dd Z)G dd dZ*d.dd Z+G d!d" d"Z,d/d$d%Z-d0d&d'Z.ej/j0dddddddfd(d)Z1d1d,d-Z2dS )2zDNS Messages    Nc                   @   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/dist-packages/dns/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.Nr   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.Nr   r   r   r   r	   r   3   s   r   c                   @   s   e Zd ZdZdS )BadEDNSzLAn OPT record occurred somewhere other than
    the additional data section.Nr   r   r   r   r	   r   8   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.Nr   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.Nr   r   r   r   r	   r   B   s   r   c                   @   s   e Zd ZdZdhZdd ZdS )	TruncatedzThe truncated flag is set.messagec                 C   s
   | j d S )zbAs much of the message as could be processed.

        Returns a ``dns.message.Message``.
        r   )kwargsselfr   r   r	   r   K   s    zTruncated.messageN)r   r   r   r   Zsupp_kwargsr   r   r   r   r	   r   F   s   r   c                   @   s,   e Zd ZdZdZdZdZdZedd Z	dS )	MessageSectionzMessage sectionsr            c                 C   s   dS Nr   r   )clsr   r   r	   _maximumZ   s    zMessageSection._maximumN)
r   r   r   r   QUESTIONANSWER	AUTHORITY
ADDITIONALclassmethodr   r   r   r   r	   r   S   s   r   c                   @   s  e Zd ZdZeZdXddZedd Zej	dd Zedd	 Z
e
j	d
d	 Z
edd Zej	dd Zedd Zej	dd Zdd Zdd ZdYddZ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dZd(d)Zed*d+ Zdd,dd'd-ejjfd.d/Zed0d1 Z ed2d3 Z!ed4d5 Z"ed6d7 Z#ed8d9 Z$ed[d;d<Z%d\d=d>Z&ed?d@ Z'edAdB Z(e(j	dCdB Z(edDdE Z)edFdG Z*d]dHdIZ+dJdK Z,dLdM Z-dNdO Z.dPdQ Z/dRdS Z0dTdU Z1dVdW Z2dS )^MessagezA DNS message.Nc                 C   sj   |d u rt j | _n|| _d| _g g g g g| _d | _d| _d | _d | _	d| _
d| _d | _d | _i | _d S )Nr       F)dnsZentropyZ	random_16idflagssectionsoptrequest_payloadkeyringtsigrequest_macxfrorigintsig_ctxindex)r   r#   r   r   r	   __init__f   s    zMessage.__init__c                 C   s
   | j d S )z The question section.r   r%   r   r   r   r	   questionw   s    zMessage.questionc                 C   s   || j d< d S Nr   r0   r   vr   r   r	   r1   |   s    c                 C   s
   | j d S )z The answer section.r   r0   r   r   r   r	   answer   s    zMessage.answerc                 C   s   || j d< d S )Nr   r0   r3   r   r   r	   r5      s    c                 C   s
   | j d S )z The authority section.r   r0   r   r   r   r	   	authority   s    zMessage.authorityc                 C   s   || j d< d S )Nr   r0   r3   r   r   r	   r6      s    c                 C   s
   | j d S )z The additional data section.r   r0   r   r   r   r	   
additional   s    zMessage.additionalc                 C   s   || j d< d S r   r0   r3   r   r   r	   r7      s    c                 C   s   dt | j d S )Nz<DNS message, ID >)reprr#   r   r   r   r	   __repr__   s    zMessage.__repr__c                 C   s   |   S N)to_textr   r   r   r	   __str__   s    zMessage.__str__Tc           
      K   sP  t  }|d| j  |dtjtj| j  tj	| j| j
}|dtj	|  |dtj| j  | jdkr|d| j  | j
dkr|dtj| j
  |d| j  | jD ]}|d	|   q| jj D ]P\}}|d
| d | |D ]*}	||	j||fi | |d qq| dd S )zConvert the message to text.

        The *origin*, *relativize*, and any other keyword
        arguments are passed to the RRset ``to_wire()`` method.

        Returns a ``str``.
        zid %d
z
opcode %s
z	rcode %s
z	flags %s
r   zedns %s
z
eflags %s
zpayload %d
z
option %s
;
N)ioStringIOwriter#   r"   opcoder<   
from_flagsr$   rcode	ednsflagsednsZedns_to_textpayloadoptions_section_enum__members__itemssection_from_numbergetvalue)
r   r,   
relativizekwsZrcr&   nameZwhichrrsetr   r   r	   r<      s.    	


zMessage.to_textc                 C   s   t |tsdS | j|jkrdS | j|jkr.dS t| jD ]F\}}|j| }|D ]}||vrN  dS qN|D ]}||vrh  dS qhq8dS )zTwo messages are equal if they have the same content in the
        header, question, answer, and authority sections.

        Returns a ``bool``.
        FT)
isinstancer    r#   r$   	enumerater%   )r   otherisectionZother_sectionnr   r   r	   __eq__   s    


zMessage.__eq__c                 C   s   |  | S r;   )r[   )r   rW   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 tj|j kr>dS tj|j |jtjjkr\dS tj	| j rndS | j
D ]}||j
vrt dS qt|j
D ]}|| j
vr dS qdS )zIIs *other* a response this message?

        Returns a ``bool``.
        r   FT)r$   r"   QRr#   rD   rE   rF   rG   ZNOERRORZ	is_updater1   )r   rW   rZ   r   r   r	   is_response   s*    




zMessage.is_responsec                 C   s6   t | jD ]\}}||u r
| |  S q
tddS )zReturn the "section number" of the specified section for use
        in indexing.

        *section* is one of the section attributes of this message.

        Raises ``ValueError`` if the section isn't known.

        Returns an ``int``.
        zunknown sectionN)rV   r%   rK   
ValueError)r   rY   rX   Zour_sectionr   r   r	   section_number   s    zMessage.section_numberc                 C   s   | j |}| j| S )a  Return the section list associated with the specified section
        number.

        *number* is a section number `int` or the text form of a section
        name.

        Raises ``ValueError`` if the section isn't known.

        Returns a ``list``.
        )rK   maker%   )r   ZnumberrY   r   r   r	   rN     s    zMessage.section_from_numberFc	                 C   s   t |tr|}	| |	}n
| |}	|	|||||f}
|s| jdur\| j|
}|dur|S n$|D ]}||||||r`|  S q`|sttj	
|||||}|| | jdur|| j|
< |S )aP  Find the RRset with the given attributes in the specified section.

        *section*, an ``int`` section number, or one of the section
        attributes of this message.  This specifies the
        the section of the message to search.  For example::

            my_message.find_rrset(my_message.answer, name, rdclass, rdtype)
            my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype)

        *name*, a ``dns.name.Name``, the name of the RRset.

        *rdclass*, an ``int``, the class of the RRset.

        *rdtype*, an ``int``, the type of the RRset.

        *covers*, an ``int`` or ``None``, the covers value of the RRset.
        The default is ``None``.

        *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
        The default is ``None``.

        *create*, a ``bool``.  If ``True``, create the RRset if it is not found.
        The created RRset is appended to *section*.

        *force_unique*, a ``bool``.  If ``True`` and *create* is also ``True``,
        create a new RRset regardless of whether a matching RRset exists
        already.  The default is ``False``.  This is useful when creating
        DDNS Update messages, as order matters for them.

        Raises ``KeyError`` if the RRset was not found and create was
        ``False``.

        Returns a ``dns.rrset.RRset object``.
        N)rU   intrN   r`   r.   getmatchKeyErrorr"   rT   ZRRsetappend)r   rY   rS   rdclassrdtypecoversdeletingcreateforce_uniquer`   keyrT   r   r   r	   
find_rrset  s(    &






zMessage.find_rrsetc	           
   
   C   s8   z|  ||||||||}	W n ty2   d}	Y n0 |	S )a5  Get the RRset with the given attributes in the specified section.

        If the RRset is not found, None is returned.

        *section*, an ``int`` section number, or one of the section
        attributes of this message.  This specifies the
        the section of the message to search.  For example::

            my_message.get_rrset(my_message.answer, name, rdclass, rdtype)
            my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype)

        *name*, a ``dns.name.Name``, the name of the RRset.

        *rdclass*, an ``int``, the class of the RRset.

        *rdtype*, an ``int``, the type of the RRset.

        *covers*, an ``int`` or ``None``, the covers value of the RRset.
        The default is ``None``.

        *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
        The default is ``None``.

        *create*, a ``bool``.  If ``True``, create the RRset if it is not found.
        The created RRset is appended to *section*.

        *force_unique*, a ``bool``.  If ``True`` and *create* is also ``True``,
        create a new RRset regardless of whether a matching RRset exists
        already.  The default is ``False``.  This is useful when creating
        DDNS Update messages, as order matters for them.

        Returns a ``dns.rrset.RRset object`` or ``None``.
        N)rn   re   )
r   rY   rS   rg   rh   ri   rj   rk   rl   rT   r   r   r	   	get_rrsetW  s    %
zMessage.get_rrsetr   c           
   	   K   s  |du r| j dur| j }|dkr6| jdkr2| j}nd}|dk rDd}n|dkrPd}tj| j| j||}| jD ]}||j	|j
|j ql| jD ]}|jtjj|fi | q| jD ]}|jtjj|fi | q| jdur|tjj| j | jD ]}|jtjj|fi | q|  | jdurtj| | j| jd tt | j||\}}	| j  | j| |tjj| j |  |r|	| _| S )a  Return a string containing the message in DNS compressed wire
        format.

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

        *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended
        to any relative names.  If ``None``, and the message has an origin
        attribute that is not ``None``, then it will be used.

        *max_size*, an ``int``, the maximum size of the wire format
        output; default is 0, which means "the message's request
        payload, if nonzero, or 65535".

        *multi*, a ``bool``, should be set to ``True`` if this message is
        part of a multiple message sequence.

        *tsig_ctx*, a ``hmac.HMAC`` object, the ongoing TSIG context, used
        when signing zone transfers.

        Raises ``dns.exception.TooBig`` if *max_size* was exceeded.

        Returns a ``bytes``.
        Nr   i  i   )r,   r'   r"   ZrendererZRendererr#   r$   r1   Zadd_questionrS   rh   rg   r5   Z	add_rrsetr   r6   r   r&   r   r7   Zwrite_headerr)   ZsignZget_wirer(   rb   timer*   clearaddr-   )
r   r,   Zmax_sizemultir-   rQ   rrT   Znew_tsigctxr   r   r	   to_wire  sL    







zMessage.to_wirec           	      C   s8   t jjjt jjt jj|||||||	}t j| d|S r2   )r"   rdtypesANYTSIG
rdataclass	rdatatyperT   
from_rdata)	keyname	algorithmZtime_signedfudgemacoriginal_iderrorrW   r)   r   r   r	   
_make_tsig  s
    zMessage._make_tsig,  r!   c           	   
   C   s   t |tjjr|| _nRt |tr,tj|}|du r@tt	|}|| }t |t
rbtj|||}|| _|du rv| j}| || jjd|d|||| _dS )a  When sending, a TSIG signature using the specified key
        should be added.

        *key*, a ``dns.tsig.Key`` is the key to use.  If a key is specified,
        the *keyring* and *algorithm* fields are not used.

        *keyring*, a ``dict`` or ``dns.tsig.Key``, is either the TSIG
        keyring or key to use.

        The format of a keyring dict is a mapping from TSIG key name, as
        ``dns.name.Name`` to ``dns.tsig.Key`` or a TSIG secret, a ``bytes``.
        If a ``dict`` *keyring* is specified but a *keyname* is not, 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 ``dict`` keyring is used, unless they know the keyring
        contains only one key.

        *keyname*, a ``dns.name.Name``, ``str`` or ``None``, the name of
        thes TSIG key to use; defaults to ``None``.  If *keyring* is a
        ``dict``, the key must be defined in it.  If *keyring* is a
        ``dns.tsig.Key``, this is ignored.

        *fudge*, an ``int``, the TSIG time fudge.

        *original_id*, an ``int``, the TSIG original id.  If ``None``,
        the message's id is used.

        *tsig_error*, an ``int``, the TSIG error code.

        *other_data*, a ``bytes``, the TSIG other data.

        *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use.  This is
        only used if *keyring* is a ``dict``, and the key entry is a ``bytes``.
        Nr   r!   )rU   r"   r)   Keyr(   strrS   	from_textnextiterbytesr#   r   r~   )	r   r(   r}   r   r   
tsig_errorZ
other_datar~   rm   r   r   r	   use_tsig  s    &

zMessage.use_tsigc                 C   s   | j r| j jS d S d S r;   )r)   rS   r   r   r   r	   r}     s    zMessage.keynamec                 C   s   | j r| j d jS d S d S r2   )r)   r~   r   r   r   r	   keyalgorithm
  s    zMessage.keyalgorithmc                 C   s   | j r| j d jS d S d S r2   )r)   r   r   r   r   r	   r     s    zMessage.macc                 C   s   | j r| j d jS d S d S r2   )r)   r   r   r   r   r	   r     s    zMessage.tsig_errorc                 C   s
   t | jS r;   )boolr)   r   r   r   r	   had_tsig  s    zMessage.had_tsig   c                 C   s4   t jjj|t jj|pd}t jt jjt	| |S )Nr   )
r"   rw   rx   OPTr{   rT   r|   rS   rootrb   )r$   rI   rJ   r&   r   r   r	   	_make_opt#  s    zMessage._make_optc                 C   s   |du s|du rd}|du r d}|du r,|}|dk rFd}d}d}g }n |dM }||d> O }|du rfg }|dkr|  |||| _nd| _|| _dS )a6  Configure EDNS behavior.

        *edns*, an ``int``, is 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".

        *ednsflags*, an ``int``, the EDNS flag values.

        *payload*, an ``int``, is the EDNS sender's payload field, which is the
        maximum size of UDP datagram the sender can handle.  I.e. how big
        a response to this message can be.

        *request_payload*, an ``int``, is the EDNS payload size to use when
        sending this message.  If not specified, defaults to the value of
        *payload*.

        *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
        options.
        NFr@   Tr   l   ~    )r   r&   r'   )r   rH   rG   rI   r'   rJ   r   r   r	   use_edns)  s&    zMessage.use_ednsc                 C   s   | j r| jd@ d? S dS d S )Ni   r   r@   )r&   rG   r   r   r   r	   rH   W  s    zMessage.ednsc                 C   s   | j r| j jS dS d S r2   )r&   ttlr   r   r   r	   rG   ^  s    zMessage.ednsflagsc                 C   s$   | j r|| j _n|r | || _ d S r;   )r&   r   r   r3   r   r   r	   rG   e  s    
c                 C   s   | j r| j d jS dS d S r2   )r&   rI   r   r   r   r	   rI   l  s    zMessage.payloadc                 C   s   | j r| j d jS dS d S )Nr   r   )r&   rJ   r   r   r   r	   rJ   s  s    zMessage.optionsc                 C   s6   |r|  j tjjO  _ n| jr2|  j tjj M  _ dS )a!  Enable or disable 'DNSSEC desired' flag in requests.

        *wanted*, a ``bool``.  If ``True``, then DNSSEC data is
        desired in the response, EDNS is enabled if required, and then
        the DO bit is set.  If ``False``, the DO bit is cleared if
        EDNS is enabled.
        N)rG   r"   r$   ZDOr&   )r   Zwantedr   r   r	   want_dnssecz  s    	zMessage.want_dnssecc                 C   s   t j| j| jS )z7Return the rcode.

        Returns an ``int``.
        )r"   rF   rE   r$   rG   r   r   r   r	   rF     s    zMessage.rcodec                 C   sL   t j|\}}|  jdM  _|  j|O  _|  jdM  _|  j|O  _dS )zJSet the rcode.

        *rcode*, an ``int``, is the rcode to set.
        i  i N)r"   rF   to_flagsr$   rG   )r   rF   valueZevaluer   r   r	   	set_rcode  s
    zMessage.set_rcodec                 C   s   t j| jS )z8Return the opcode.

        Returns an ``int``.
        )r"   rD   rE   r$   r   r   r   r	   rD     s    zMessage.opcodec                 C   s(   |  j dM  _ |  j tj|O  _ dS )zMSet the opcode.

        *opcode*, an ``int``, is the opcode to set.
        i  N)r$   r"   rD   r   )r   rD   r   r   r	   
set_opcode  s    zMessage.set_opcodec                 C   s   |S r;   r   )r   r   r   r   r	   _get_one_rr_per_rrset  s    zMessage._get_one_rr_per_rrsetc                 C   s   ||d dfS )NFr   )r   rY   rS   rg   rh   r   r   r	   _parse_rr_header  s    zMessage._parse_rr_headerc                 C   sl   |t jjkr.|tjks(| js(|t jjkr`tn2|t jj	kr`|tjks\|t jj
ks\||d kr`t||d dfS )Nr   F)r"   r{   r   r   r   r&   rS   r   r   ry   rx   r   )r   rY   countZpositionrS   rg   rh   r   r   r	   _parse_special_rr_header  s    



z Message._parse_special_rr_header)N)NT)Nr   FN)r   r   N)r   r   r   NN)T)3r   r   r   r   r   rK   r/   propertyr1   setterr5   r6   r7   r:   r=   r<   r[   r\   r^   r`   rN   r"   r{   NONErn   ro   rv   staticmethodr   r)   Zdefault_algorithmr   r}   r   r   r   r   r   r   rH   rG   rI   rJ   r   rF   r   rD   r   r   r   r   r   r   r   r	   r    a   s   









$

>

,
B

6




  
.





r    c                   @   s   e Zd ZdS )QueryMessageN)r   r   r   r   r   r   r	   r     s   r   c                  C   s   dd l } d S r2   )Z
dns.update)r"   r   r   r	   _maybe_import_update  s    r   c                 C   s2   | t jjkrtS | t jjkr*t  t jjS tS d S r;   )	r"   rD   QUERYr   ZUPDATEr   updateZUpdateMessager    )rD   r   r   r	   _message_factory_from_opcode  s    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.

    parser: the binary parser
    message: The message object being built
    initialize_message: Callback to set message parsing options
    question_only: Are we only reading the question?
    one_rr_per_rrset: Put each RR into its own RRset?
    keyring: TSIG keyring
    ignore_trailing: Ignore trailing junk at end of request?
    multi: Is this message part of a multi-message sequence?
    DNS dynamic updates.
    FNc                 C   s<   t j|| _d | _|| _|| _|| _|| _|| _	|| _
d S r;   )r"   wireZParserparserr   initialize_messagequestion_onlyone_rr_per_rrsetignore_trailingr(   rs   )r   r   r   r   r   r   r(   rs   r   r   r	   r/     s    z_WireReader.__init__c           	   	   C   sp   | j j| }t|D ]V}| j| j j}| jd\}}| j ||||\}}}}| j j||||ddd qdS )zhRead the next *qcount* records from the wire data and add them to
        the question section.
        z!HHTrk   rl   N)	r   r%   ranger   get_namer,   
get_structr   rn   )	r   r`   qcountrY   rX   qnamerh   rg   _r   r   r	   _get_question  s    
z_WireReader._get_questionc                 C   sr  | j j| }| j}t|D ]P}| jj}| j }| j jdurN|| j j}n|}| j	d\}	}
}}|	t
jjt
jjfv r| j |||||
|	\}
}	}}n| j |||
|	\}
}	}}|r|dkrt
jjd}t
jj}nN| j|( t
j|
|	| j| j j}W d   n1 s0    Y  | }| j jr@|	t
jjkr@d}|	t
jjkrdt
j|||| j _q|	t
jjkr0| jdu rtdt| jtr| j |}t|t!rt
j"#|||j$}n| j}|du rtd| || j _t
j"%| jj&|||t't(( | j j)|| j j*| j+	| j _*t
j|d|| j _"q| j ,|||
|	||d|}|dur|dkr`d}|-|| qdS )zRead the next I{count} records from the wire data and add them to
        the specified section.

        section: the section of the message to which to add records
        count: the number of records to read
        Nz!HHIHr   Tz"got signed message without keyringzkey '%s' unknowni).r   r%   r   r   r   Zcurrentr   r,   rP   r   r"   r{   r   ry   r   r   	exception	FormErrorr   Zrestrict_tordataZfrom_wire_parserri   r+   ZSOArT   r|   r&   r(   r   rU   dictrc   r   r)   r   r~   Zvalidater   rb   rp   r*   r-   rs   rn   rr   )r   r`   r   rY   rl   rX   Zrr_startZabsolute_namerS   rh   rg   r   Zrdlenrj   emptyrdri   rm   rT   r   r   r	   _get_section  s    



$




z_WireReader._get_sectionc                 C   s   | j  dk rt| j d\}}}}}}ttj|}||d| _|| j_	| 
| j | j| j| _| tj| | jrdS | tj| | tj| | tj| | js| j  dkrt| jr| jjr| jjs| jj| j j | jS )zNRead a wire format DNS message and build a dns.message.Message
        object.   z!HHHHHHr#   Nr   )r   Z	remainingr   r   r   r"   rD   rE   r   r$   r   r   r   r   r   r   r   r   r   r   r   r   r
   rs   r-   r   r   r   )r   r#   r$   r   ZancountZaucountZadcountfactoryr   r   r	   readH  s*    
z_WireReader.read)FFFNF)r   r   r   r   r/   r   r   r   r   r   r   r	   r     s      
Kr   r!   Fc                    s    fdd}t | ||||	||}z| }W n@ tjjyr   |jrl|jjtjj@ rl|
rlt|jdn Y n0 |jtjj@ r|
rt|d|S )a4  Convert a DNS wire format message into a message
    object.

    *keyring*, a ``dns.tsig.Key`` or ``dict``, the key or keyring to use
    if the message is signed.

    *request_mac*, a ``bytes``.  If the message is a response to a
    TSIG-signed request, *request_mac* should be set to the MAC of
    that request.

    *xfr*, a ``bool``, should be set to ``True`` if this message is part of
    a zone transfer.

    *origin*, a ``dns.name.Name`` or ``None``.  If the message is part
    of a zone transfer, *origin* should be the origin name of the
    zone.  If not ``None``, names will be relativized to the origin.

    *tsig_ctx*, a ``hmac.HMAC`` object, the ongoing TSIG context, used
    when validating zone transfers.

    *multi*, a ``bool``, should be set to ``True`` if this message is
    part of a multiple message sequence.

    *question_only*, a ``bool``.  If ``True``, read only up to
    the end of the question section.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its
    own RRset.

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the message.

    *raise_on_truncation*, a ``bool``.  If ``True``, raise an exception if
    the TC bit is set.

    Raises ``dns.message.ShortHeader`` if the message is less than 12 octets
    long.

    Raises ``dns.message.TrailingJunk`` if there were octets in the message
    past the end of the proper DNS message, and *ignore_trailing* is ``False``.

    Raises ``dns.message.BadEDNS`` if an OPT record was in the
    wrong section, or occurred more than once.

    Raises ``dns.message.BadTSIG`` if a TSIG record was not the last
    record of the additional data section.

    Raises ``dns.message.Truncated`` if the TC flag is set and
    *raise_on_truncation* is ``True``.

    Returns a ``dns.message.Message``.
    c                    s   | _ | _ | _| _d S r;   )r*   r+   r,   r-   r   r,   r*   r-   r+   r   r	   r     s    z%from_wire.<locals>.initialize_messager   )	r   r   r"   r   r   r   r$   ZTCr   )r   r(   r*   r+   r,   r-   rs   r   r   r   Zraise_on_truncationr   readermr   r   r	   	from_wirec  s    9
r   c                   @   sB   e Zd ZdZdddZdd Zd	d
 Zdd Zdd Zdd Z	dS )_TextReaderat  Text format reader.

    tok: the tokenizer.
    message: The message object being built.
    DNS dynamic updates.
    last_name: The most recently read name when building a message object.
    one_rr_per_rrset: Put each RR into its own RRset?
    origin: The origin for relative names
    relativize: relativize names?
    relativize_to: the origin to relativize to.
    FNTc                 C   sh   d | _ tjj||d| _d | _|| _|| _|| _|| _	d | _
d| _d| _d | _d | _tjj| _d| _d S )N
idna_codecr@   r   )r   r"   Z	tokenizer	Tokenizertok	last_namer   r,   rP   relativize_tor#   rH   rG   rI   rF   rD   r   r$   )r   textr   r   r,   rP   r   r   r   r	   r/     s    
z_TextReader.__init__c                 C   s  | j  }|j}|dkr(| j  | _nJ|dkrl| j  }| sP| j | qh| jtj	|jB | _q0n|dkr| j  | _
| j| j
d> B | _n|dkr| j
dk rd| _
| j  }| s| j | q| jtj|jB | _qn|dkr| j  | _| j
dk rrd| _
nb|dkrJ| j  }tj	|| _| jtj| jB | _n(|d	krn| j  }tj	|| _nt| j   d
S )z5Process one line from the text format header section.r#   r$   rH   r   Zeflagsr   rI   rD   rF   N)r   rc   r   Zget_intr#   is_identifierungetr$   r"   r   rH   rG   Zedns_from_textrI   Z
get_stringrD   r   rF   r   get_eol)r   rY   tokenZwhatr   r   r   r	   _header_line  sH    









z_TextReader._header_linec                 C   s  | j j| }| jjdd}| s>| j|| j j| j| j| _	| j	}| j }|
 s^tjjz,tj|j}| j }|
 stjjW n6 tjjy   tjjY n ty   tjj}Y n0 tj|j}| j ||||\}}}}| j j||||ddd | j  dS )z7Process one line from the text format question section.TZwant_leadingr   N)r   r%   r   rc   is_whitespaceas_namer,   rP   r   r   r   r"   r   SyntaxErrorrz   r   r   	ExceptionINr{   r   rn   r   )r   r`   rY   r   rS   rg   rh   r   r   r   r	   _question_line  s6    


z_TextReader._question_linec              
   C   s  | j j| }| jjdd}| s>| j|| j j| j| j| _	| j	}| j }|
 s^tjjz*t|jd}| j }|
 stjjW n2 tjjy   tjjY n ty   d}Y n0 z,tj|j}| j }|
 stjjW n: tjjy   tjjY n ty"   tjj}Y n0 tj|j}| j ||||\}}}}	| j }|	rn| sntjj| s| j| tj||| j| j j| j| j}
|
 }nd}
tjj}| j ||||||d| j}|
dur||
| dS )zfProcess one line from the text format answer, authority, or
        additional data sections.
        Tr   r   N)r   r%   r   rc   r   r   r,   rP   r   r   r   r"   r   r   rb   r   r   rz   r   r   r{   r   is_eol_or_eofr   r   ri   r   rn   r   rr   )r   r`   rY   r   rS   r   rg   rh   rj   r   r   ri   rT   r   r   r	   _rr_line  sd    










z_TextReader._rr_linec                 C   s`   t | j}|| jd}| j|_| jdkr<|| j| j| j | jrN|	| j | j
r\| j
|_
|S )Nr   r   )r   rD   r#   r$   rH   r   rG   rI   rF   r   r,   )r   r   r   r   r   r	   _make_messageV  s    

z_TextReader._make_messagec                 C   s   | j }d}| jdd}| r"q| r|j }|dkrB| j }| jrP| j}n|  }zB|j	
|}| js|| _|| j| _|tjkr| j}n| j}W n ty   Y n0 | j  q
| j| || q
| js|  | _| jS )zNRead a text format DNS message and build a dns.message.Message
        object.NTZHEADER)r   r   rc   r   Z
is_commentr   upperr   r   rK   r   r   r   r   r   r   r   r   r   r   )r   Zline_methodr`   r   ur   r   r   r	   r   b  s<    






z_TextReader.read)FNTN)
r   r   r   r   r/   r   r   r   r   r   r   r   r   r	   r     s     
*:r   Tc                 C   s   t | |||||}| S )a  Convert the text format message into a message object.

    The reader stops after reading the first blank line in the input to
    facilitate reading multiple messages from a single file with
    ``dns.message.from_file()``.

    *text*, a ``str``, the text format message.

    *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
    encoder/decoder.  If ``None``, the default IDNA 2003 encoder/decoder
    is used.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, then each RR is put
    into its own rrset.  The default is ``False``.

    *origin*, a ``dns.name.Name`` (or ``None``), the
    origin to use for relative names.

    *relativize*, a ``bool``.  If true, name will be relativized.

    *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use
    when relativizing names.  If not set, the *origin* value will be used.

    Raises ``dns.message.UnknownHeaderField`` if a header is unknown.

    Raises ``dns.exception.SyntaxError`` if the text is badly formed.

    Returns a ``dns.message.Message object``
    )r   r   )r   r   r   r,   rP   r   r   r   r   r	   r     s    $
r   c                 C   sP   t  4}t| tr"|t| } t| ||W  d   S 1 sB0    Y  dS )a  Read the next text format message from the specified file.

    Message blocks are separated by a single blank line.

    *f*, a ``file`` or ``str``.  If *f* is text, it is treated as the
    pathname of a file to open.

    *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
    encoder/decoder.  If ``None``, the default IDNA 2003 encoder/decoder
    is used.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, then each RR is put
    into its own rrset.  The default is ``False``.

    Raises ``dns.message.UnknownHeaderField`` if a header is unknown.

    Raises ``dns.exception.SyntaxError`` if the text is badly formed.

    Returns a ``dns.message.Message object``
    N)
contextlib	ExitStackrU   r   enter_contextopenr   )fr   r   stackr   r   r	   	from_file  s    

r   c
                 C   s   t | trtjj| |	d} tjj|}tjj	|}t
 }
|
 jtjjO  _|
j|
j| ||ddd i }|dur||d< |du rd}|dur||d< |du rd}|dur||d< |du rd}|dur||d	< |du rd}||d
< |
jf i | |
| |
S )a  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.

    qname, a ``dns.name.Name`` or ``str``, the query name.

    *rdtype*, an ``int`` or ``str``, the desired rdata type.

    *rdclass*, an ``int`` or ``str``,  the desired rdata class; the default
    is class IN.

    *use_edns*, an ``int``, ``bool`` or ``None``.  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.

    *want_dnssec*, a ``bool``.  If ``True``, DNSSEC data is desired.

    *ednsflags*, an ``int``, the EDNS flag values.

    *payload*, an ``int``, is the EDNS sender's payload field, which is the
    maximum size of UDP datagram the sender can handle.  I.e. how big
    a response to this message can be.

    *request_payload*, an ``int``, is the EDNS payload size to use when
    sending this message.  If not specified, defaults to the value of
    *payload*.

    *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
    options.

    *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
    encoder/decoder.  If ``None``, the default IDNA 2003 encoder/decoder
    is used.

    Returns a ``dns.message.QueryMessage``
    r   Tr   NrG   r   rI   r'   rJ   rH   )rU   r   r"   rS   r   r{   Z	RdataTypera   rz   Z
RdataClassr   r$   RDrn   r1   r   r   )r   rh   rg   r   r   rG   rI   r'   rJ   r   r   r   r   r   r	   
make_query  s<    -

r       r   c              	   C   s   | j tj j@ rtjdt|  }|| jd}tj j| j tj j@ B |_ |r`| j tj j	O  _ |
|   t| j|_| jdkr|dd|| j | jr|| j| j|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.

    *query*, a ``dns.message.Message``, the query to respond to.

    *recursion_available*, a ``bool``, should RA be set in the response?

    *our_payload*, an ``int``, the payload size to advertise in EDNS
    responses.

    *fudge*, an ``int``, the TSIG time fudge.

    *tsig_error*, an ``int``, the TSIG error.

    Returns a ``dns.message.Message`` object whose specific class is
    appropriate for the query.  For example, if query is a
    ``dns.update.UpdateMessage``, response will be too.
    z&specified query message is not a queryr   r   Nr!   )r$   r"   r]   r   r   r   rD   r#   r   ZRAr   listr1   rH   r   rI   r   r   r(   r}   r   r   r*   )ZqueryZrecursion_availableZour_payloadr   r   r   Zresponser   r   r	   make_response#  s"    
r   )
Nr!   FNNFFFFF)NFNTN)NF)Fr   r   r   )3r   r   rA   rp   Zdns.wirer"   Zdns.ednsZdns.enumZ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.rdtypes.ANY.OPTZdns.rdtypes.ANY.TSIGr   r   r   r
   ZDNSExceptionr   r   r   r   r   enumIntEnumr   globalsr   rL   r    r   r   r   r   r   r   r   r   rz   r   r   r   r   r   r   r	   <module>   sr       a
     
Q \  
)

O  