
    J*                     n    S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSK	J
r
  SrSrSrSr " S S	\5      rg)
z*Help for building DNS wire format messages    )BytesION   )long      c                       \ rS rSrSrSS jrS rS r\R                  R                  4S jrS rS	 rSS
 jr\R                  R                   4S jr\R                  R                   4S jrS rS rS rSrg)Renderer$   a  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()

output, a BytesIO, where rendering is written

id: the message id

flags: the message flags

max_size: the maximum size of the message

origin: the origin to use when rendering relative names

compress: the compression table

section: an int, the section currently being rendered

counts: list of the number of RRs in each section

mac: the MAC of the rendered message (if TSIG was used)
Nc                    [        5       U l        Uc  [        R                  " SS5      U l        OXl        X l        X0l        X@l        0 U l        [        U l
        / SQU l        U R                  R                  S5        SU l        g)zInitialize a new renderer.Nr     )r   r   r   r   s                )r   outputrandomrandintidflagsmax_sizeorigincompressQUESTIONsectioncountswritemac)selfr   r   r   r   s        lib/third_party/dns/renderer.py__init__Renderer.__init__M   sf     i:nnQ.DGG
 ",'    c                    U R                   R                  U5        U R                   R                  5         / nU R                  R	                  5        H  u  p4XA:  d  M  UR                  U5        M     U H  nU R                  U	 M     g)zTruncate the output buffer at offset *where*, and remove any
compression table entries that pointed beyond the truncation
point.
N)r   seektruncater   itemsappend)r   wherekeys_to_deletekvs        r   	_rollbackRenderer._rollback^   so     	MM'')DAz%%a( *  Aa   r   c                     U R                   U:w  a1  U R                   U:  a  [        R                  R                  eXl         gg)zSet the renderer's current section.

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

Raises dns.exception.FormError if an attempt was made to set
a section value less than the current section.
N)r   dns	exception	FormError)r   r   s     r   _set_sectionRenderer._set_sectionm   s6     <<7"||g%mm---"L #r   c                    U R                  [        5        U R                  R                  5       nUR	                  U R                  U R
                  U R                  5        U R                  R                  [        R                  " SX#5      5        U R                  R                  5       nXPR                  :  a+  U R                  U5        [        R                  R                  eU R                  [        ==   S-  ss'   g)zAdd a question to the message.!HHr   N)r/   r   r   tellto_wirer   r   r   structpackr   r)   r,   r-   TooBigr   )r   qnamerdtyperdclassbeforeafters         r   add_questionRenderer.add_question|   s     	(#!!#dkk4==$++>&++eV=>  "MM!NN6"--&&&H"r   c                    U R                  U5        U R                  R                  5       nUR                  " U R                  U R                  U R
                  40 UD6nU R                  R                  5       nX`R                  :  a+  U R                  U5        [        R                  R                  eU R                  U==   U-  ss'   g)zrAdd the rrset to the specified section.

Any keyword arguments are passed on to the rdataset's to_wire()
routine.
Nr/   r   r3   r4   r   r   r   r)   r,   r-   r7   r   )r   r   rrsetkwr;   nr<   s          r   	add_rrsetRenderer.add_rrset   s     	'"!!#MM$++t}}dkkHRH  "MM!NN6"--&&&G!r   c                    U R                  U5        U R                  R                  5       nUR                  " X R                  U R                  U R
                  40 UD6nU R                  R                  5       nXpR                  :  a+  U R                  U5        [        R                  R                  eU R                  U==   U-  ss'   g)zAdd 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.
Nr@   )r   r   namerdatasetrB   r;   rC   r<   s           r   add_rdatasetRenderer.add_rdataset   s     	'"!!#T;;t{{ #!#  "MM!NN6"--&&&G!r   c           
         U[        S5      -  nX!S-  -  nU R                  [        5        U R                  R	                  5       nU R                  R                  [        R                  " SS[        R                  R                  UUS5      5        UGb  U R                  R	                  5       nU GH  n[        R                  " SUR                  S5      nU R                  R                  U5        U R                  R	                  5       n	UR                  U R                  5        U R                  R	                  5       n
X-
  S:  d   eU R                  R                  U	S-
  5        [        R                  " S	X-
  5      nU R                  R                  U5        U R                  R                  SS5        GM     U R                  R	                  5       nX-
  S:  d   eU R                  R                  US-
  5        [        R                  " S	X-
  5      nU R                  R                  U5        U R                  R                  SS5        U R                  R	                  5       nXR                  :  a+  U R                  U5        [        R                   R"                  eU R$                  [        ==   S
-  ss'   g)z&Add an EDNS OPT record to the message.l   ~    z!BHHIHr   Nr2      r   !Hr   )r   r/   
ADDITIONALr   r3   r   r5   r6   r,   	rdatatypeOPTotyper4   r!   r   r)   r-   r7   r   )r   edns	ednsflagspayloadoptionsr;   lstartoptstuffstartendlendr<   s                r   add_ednsRenderer.add_edns   s    	T*%%	bj!	*%!!#&++h3==3D3Dg&/4 	5[[%%'FE399a8!!%(((*DKK(kk&&({U***  +D#+6!!%(  A&  ;;##%D=5(((KKVaZ(KKdm4EKKe$KKQ"  "MM!NN6"--&&&J1$r   c	                     U R                   R                  5       n	[        R                  R	                  U	UU[        [        R                  " 5       5      UUUUUUS9
u  ol        nU R                  X5        g)z$Add a TSIG signature to the message.)	algorithmN	r   getvaluer,   tsigsigninttimer   _write_tsig)r   keynamesecretfudger   
tsig_error
other_datarequest_macr`   s
tsig_rdatactxs               r   add_tsigRenderer.add_tsig   sm     KK  "&)hhmmA4;4:47		4D49464>4>4?>G '4 	'I#Xs 	-r   c
                     U R                   R                  5       n
[        R                  R	                  U
UU[        [        R                  " 5       5      UUUUUUUSL SU	S9u  ol        nU R                  X5        U$ )aQ  Add a TSIG signature to the message. Unlike add_tsig(), this can be
used for a series of consecutive DNS envelopes, e.g. for a zone
transfer over TCP [RFC2845, 4.4].

For the first message in the sequence, give ctx=None. For each
subsequent message, give the ctx that was returned from the
add_multi_tsig() call for the previous message.NT)rp   firstmultir`   ra   )r   rp   rh   ri   rj   r   rk   rl   rm   r`   rn   ro   s               r   add_multi_tsigRenderer.add_multi_tsig   s     KK  "&)hhmmA4;4:47		4D49464>4>4?8;:=+:>>G '4 'I#Xs 	-
r   c           	      v   U R                  [        5        U R                  R                  5       nUR	                  U R                  U R
                  U R                  5        U R                  R                  [        R                  " S[        R                  R                  [        R                  R                  SS5      5        U R                  R                  5       nU R                  R                  U5        U R                  R                  5       nXT-
  S:  d   eXPR                  :  a+  U R!                  U5        [        R"                  R$                  eU R                  R'                  US-
  5        U R                  R                  [        R                  " SXT-
  5      5        U R(                  [        ==   S-  ss'   U R                  R'                  S5        U R                  R                  [        R                  " SU R(                  [           5      5        U R                  R'                  SS5        g )Nz!HHIHr   rM   r   rN   r   
   )r/   rO   r   r3   r4   r   r   r   r5   r6   r,   rP   TSIG
rdataclassANYr   r)   r-   r7   r!   r   )r   ro   rh   r;   rdata_startr<   s         r   rg   Renderer._write_tsig   s   *%!!#T]]DKK@&++gs}}/A/A&)nn&8&8!Q@ 	Akk&&(*%  ""U***MM!NN6"--&&&q)&++dE,?@AJ1$&++dDKK
,CDEAr   c                 l   U R                   R                  S5        U R                   R                  [        R                  " SU R
                  U R                  U R                  S   U R                  S   U R                  S   U R                  S   5      5        U R                   R                  SS5        g)zWrite 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   r5   r6   r   r   r   r   s    r   write_headerRenderer.write_header  s     	&++i$**&*kk!ndkk!n&*kk!ndkk!nF 	G 	Ar   c                 6    U R                   R                  5       $ )zReturn the wire format message.)r   rb   r   s    r   get_wireRenderer.get_wire   s     {{##%%r   )	r   r   r   r   r   r   r   r   r   )Nr   r   N)N)__name__
__module____qualname____firstlineno____doc__r   r)   r/   r,   r{   INr=   rD   rI   r]   rc   default_algorithmrq   rv   rg   r   r   __static_attributes__ r   r   r	   r	   $   sr    &P"!# 36..2C2C #" "$!%H ),(B(B.& "%!;!;8.&r   r	   )r   ior   r5   r   rf   dns.exceptionr,   dns.tsig_compatr   r   ANSWER	AUTHORITYrO   objectr	   r   r   r   <module>r      sC   $ 1        	
	
&v &r   