509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
¢báW“.  ã               @   sh   d 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	m
Z
 dZdZdZdZG dd	„ d	eƒZdS )
z*Help for building DNS wire format messagesé    )ÚBytesIONé   )Úlongé   é   c               @   st   e Zd ZdZddd„Zdd„ Zd	d
„ Zejj	fdd„Z
dd„ Zdd„ Zddd„Zejjfdd„Zdd„ Zdd„ ZdS )ÚRendererai  Helper class for building DNS wire-format messages.

    Most applications can use the higher-level L{dns.message.Message}
    class and its to_wire() method to generate wire-format messages.
    This class is for those applications which need finer control
    over the generation of messages.

    Typical use::

        r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
        r.add_question(qname, qtype, qclass)
        r.add_rrset(dns.renderer.ANSWER, rrset_1)
        r.add_rrset(dns.renderer.ANSWER, rrset_2)
        r.add_rrset(dns.renderer.AUTHORITY, ns_rrset)
        r.add_edns(0, 0, 4096)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2)
        r.write_header()
        r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
        wire = r.get_wire()

    @ivar output: where rendering is written
    @type output: BytesIO object
    @ivar id: the message id
    @type id: int
    @ivar flags: the message flags
    @type flags: int
    @ivar max_size: the maximum size of the message
    @type max_size: int
    @ivar origin: the origin to use when rendering relative names
    @type origin: dns.name.Name object
    @ivar compress: the compression table
    @type compress: dict
    @ivar section: the section currently being rendered
    @type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
    dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
    @ivar counts: list of the number of RRs in each section
    @type counts: int list of length 4
    @ivar mac: the MAC of the rendered message (if TSIG was used)
    @type mac: string
    Nr   éÿÿ  c             C   sh   t ƒ | _|dkr tjddƒ| _n|| _|| _|| _|| _i | _t	| _
ddddg| _| jjdƒ d| _dS )aó  Initialize a new renderer.

        @param id: the message id
        @type id: int
        @param flags: the DNS message flags
        @type flags: int
        @param max_size: the maximum message size; the default is 65535.
        If rendering results in a message greater than I{max_size},
        then L{dns.exception.TooBig} will be raised.
        @type max_size: int
        @param origin: the origin to use when rendering relative names
        @type origin: dns.name.Name or None.
        Nr   iÿÿ  ó    é   Ú s               )r   ÚoutputÚrandomZrandintÚidÚflagsÚmax_sizeÚoriginÚcompressÚQUESTIONÚsectionÚcountsÚwriteÚmac)Úselfr   r   r   r   © r   ú/usr/lib/python3.6/renderer.pyÚ__init__N   s    zRenderer.__init__c             C   s^   | j j|ƒ | j jƒ  g }x(| jjƒ D ]\}}||kr&|j|ƒ q&W x|D ]}| j|= qJW dS )zÕTruncate the output buffer at offset I{where}, and remove any
        compression table entries that pointed beyond the truncation
        point.

        @param where: the offset
        @type where: int
        N)r   ÚseekÚtruncater   ÚitemsÚappend)r   ÚwhereZkeys_to_deleteÚkÚvr   r   r   Ú	_rollbackk   s    	

zRenderer._rollbackc             C   s&   | j |kr"| j |krtjj‚|| _ dS )aZ  Set the renderer's current section.

        Sections must be rendered order: QUESTION, ANSWER, AUTHORITY,
        ADDITIONAL.  Sections may be empty.

        @param section: the section
        @type section: int
        @raises dns.exception.FormError: an attempt was made to set
        a section value less than the current section.
        N)r   ÚdnsÚ	exceptionZ	FormError)r   r   r   r   r   Ú_set_section}   s    

zRenderer._set_sectionc             C   sz   | j tƒ | jjƒ }|j| j| j| jƒ | jjtj	d||ƒƒ | jjƒ }|| j
krd| j|ƒ tjj‚| jt  d7  < dS )a  Add a question to the message.

        @param qname: the question name
        @type qname: dns.name.Name
        @param rdtype: the question rdata type
        @type rdtype: int
        @param rdclass: the question rdata class
        @type rdclass: int
        z!HHr   N)r&   r   r   ÚtellÚto_wirer   r   r   ÚstructÚpackr   r#   r$   r%   ÚTooBigr   )r   ZqnameZrdtypeZrdclassÚbeforeÚafterr   r   r   Úadd_questionŽ   s    




zRenderer.add_questionc             K   sh   | j |ƒ | jjƒ }|j| j| j| jf|Ž}| jjƒ }|| jkrR| j|ƒ tj	j
‚| j|  |7  < dS )a  Add the rrset to the specified section.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param rrset: the rrset
        @type rrset: dns.rrset.RRset object
        N)r&   r   r'   r(   r   r   r   r#   r$   r%   r+   r   )r   r   ZrrsetÚkwr,   Únr-   r   r   r   Ú	add_rrset£   s    




zRenderer.add_rrsetc             K   sj   | j |ƒ | jjƒ }|j|| j| j| jf|Ž}| jjƒ }|| jkrT| j|ƒ tj	j
‚| j|  |7  < dS )a©  Add the rdataset to the specified section, using the specified
        name as the owner name.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param name: the owner name
        @type name: dns.name.Name object
        @param rdataset: the rdataset
        @type rdataset: dns.rdataset.Rdataset object
        N)r&   r   r'   r(   r   r   r   r#   r$   r%   r+   r   )r   r   ÚnameZrdatasetr/   r,   r0   r-   r   r   r   Úadd_rdataset¸   s    




zRenderer.add_rdatasetc             C   sˆ  |t dƒM }||d> O }| jtƒ | jjƒ }| jjtjddtj	j
||dƒƒ |dk	�rJ| jjƒ }x’|D ]Š}tjd|jdƒ}| jj|ƒ | jjƒ }	|j| jƒ | jjƒ }
|
|	 dk s¶t‚| jj|	d ƒ tjd	|
|	 ƒ}| jj|ƒ | jjddƒ qfW | jjƒ }|| dk �st‚| jj|d ƒ tjd	|| ƒ}| jj|ƒ | jjddƒ | jjƒ }|| jk�rr| j|ƒ tjj‚| jt  d
7  < dS )aØ  Add an EDNS OPT record to the message.

        @param edns: The EDNS level to use.
        @type edns: int
        @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 options: The EDNS options list
        @type options: list of dns.edns.Option instances
        @see: RFC 2671
        l   ÿ~ é   z!BHHIHr   Nz!HHi   r   z!Hr   )r   r&   Ú
ADDITIONALr   r'   r   r)   r*   r$   Ú	rdatatypeÚOPTZotyper(   ÚAssertionErrorr   r   r#   r%   r+   r   )r   ZednsZ	ednsflagsZpayloadZoptionsr,   ZlstartÚoptZstuffÚstartÚendZlendr-   r   r   r   Úadd_ednsÑ   s<    










zRenderer.add_ednsc	             C   sB  | j tƒ | jjƒ }	| jjƒ }
tjj|
||tt	j	ƒ ƒ||||||d�
\}| _
}|j| j| j| jƒ | jjtjdtjjtjjddƒƒ | jjƒ }| jj|ƒ | jjƒ }|| dk s´t‚|| jkrÐ| j|	ƒ tjj‚| jj|d ƒ | jjtjd|| ƒƒ | jt  d7  < | jjdƒ | jjtjd| jt ƒƒ | jjddƒ d	S )
aõ  Add a TSIG signature to the message.

        @param keyname: the TSIG key name
        @type keyname: dns.name.Name object
        @param secret: the secret to use
        @type secret: string
        @param fudge: TSIG time fudge
        @type fudge: int
        @param id: the message id to encode in the tsig signature
        @type 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 request_mac: This message is a response to the request which
        had the specified MAC.
        @type request_mac: string
        @param algorithm: the TSIG algorithm to use
        @type algorithm: dns.name.Name object
        )Ú	algorithmz!HHIHr   i   r   z!Hr   é
   N)r&   r5   r   r'   Úgetvaluer$   ÚtsigZsignÚintÚtimer   r(   r   r   r   r)   r*   r6   ZTSIGÚ
rdataclassÚANYr8   r   r#   r%   r+   r   r   )r   ZkeynameZsecretZfudger   Z
tsig_errorZ
other_dataZrequest_macr=   r,   ÚsZ
tsig_rdataZctxZrdata_startr-   r   r   r   Úadd_tsig   s:    







zRenderer.add_tsigc          
   C   sX   | j jdƒ | j jtjd| j| j| jd | jd | jd | jd ƒƒ | j jddƒ dS )z¾Write the DNS message header.

        Writing the DNS message header is done after all sections
        have been rendered, but before the optional TSIG signature
        is added.
        r   z!HHHHHHr   r   r   N)r   r   r   r)   r*   r   r   r   )r   r   r   r   Úwrite_header5  s
    zRenderer.write_headerc             C   s
   | j jƒ S )z@Return the wire format message.

        @rtype: string
        )r   r?   )r   r   r   r   Úget_wireC  s    zRenderer.get_wire)Nr   r   N)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r#   r&   r$   rC   ÚINr.   r1   r3   r<   r@   Zdefault_algorithmrF   rG   rH   r   r   r   r   r   "   s   *

04r   )rL   Úior   r)   r   rB   Zdns.exceptionr$   Zdns.tsigZ_compatr   r   ZANSWERZ	AUTHORITYr5   Úobjectr   r   r   r   r   Ú<module>   s   