
    g#n              	           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mZm	Z	m
Z
mZmZ ej                  dk\  rd dlmZ nd dlmZ  ej$                  e      ZddddddZdd	d
dddddiZdddddddddd
dddddiZ G d d      Z G d d      Zy)    N   )NetErrorASNRegistryErrorASNParseErrorASNLookupErrorHTTPLookupErrorWhoisLookupErrorWhoisRateLimitErrorASNOriginLookupError)   r   )
ip_network)	IPNetwork)cidrdescription
maintainerupdatedsourceradbzwhois.radb.netz(descr):[^\S\n]+(?P<val>.+?)\nz(mnt-by):[^\S\n]+(?P<val>.+?)\nz (changed):[^\S\n]+(?P<val>.+?)\nz(source):[^\S\n]+(?P<val>.+?)\nr   r   r   r   )serverfieldszhttp://www.radb.net/querykeywords1Query origin)advanced_queryquery	ip_optionz-iz	-i optionz(source):[^\S\n]+(?P<val>.+?)\<)urlform_data_asn_field	form_datar   c                   <    e Zd ZdZd Zd Zd Zd Zd	dZ	 	 d
dZ	y)IPASNz
    The class for parsing ASN data for an IP address.

    Args:
        net (:obj:`ipwhois.net.Net`): A ipwhois.net.Net object.

    Raises:
        NetError: The parameter provided is not an instance of
            ipwhois.net.Net
    c                 z    ddl m}m} ddlm} t        ||      r|| _        nt        d      || _        || _	        y )Nr   )NetORG_MAP)	RIR_WHOIS@The provided net parameter is not an instance of ipwhois.net.Net)
netr&   r'   whoisr(   
isinstance_netr   org_map	rir_whois)selfr*   r&   r'   r(   s         /opt/Tautulli/lib/ipwhois/asn.py__init__zIPASN.__init__`   s?    '$ c3DI  - . . "    c                    	 |j                  d      }d|d   j                  d      i}|d   | j                  j                         vrt	        dj                  |d               |d   j                  d      |d<   |d	   j                  d      |d
<   |d   j                  d      j                         |d<   |d   j                  d      |d<   d|d<   |S # t        $ r  t        $ r#}t        dj                  ||      dd       d}~ww xY w)aE  
        The function for parsing ASN fields from a dns response.

        Args:
            response (:obj:`str`): The response from the ASN dns server.

        Returns:
            dict: The ASN lookup results

            ::

                {
                    'asn' (str) - The Autonomous System Number
                    'asn_date' (str) - The ASN Allocation date
                    'asn_registry' (str) - The assigned ASN registry
                    'asn_cidr' (str) - The assigned ASN CIDR
                    'asn_country_code' (str) - The assigned ASN country code
                    'asn_description' (None) - Cannot retrieve with this
                        method.
                }

        Raises:
            ASNRegistryError: The ASN registry is not known.
            ASNParseError: ASN parsing failed.
        |asn_registryr    
ASN registry {0} is not known.r    "
asnr   asn_cidr   asn_country_code   asn_dateNasn_description-Parsing failed for "{0}" with exception: {1}.d   	splitstripr/   keysr   formatupper	Exceptionr   r0   responsetempretes        r1   parse_fields_dnszIPASN.parse_fields_dnsr   s&   6	>>>#&D "47==#78C>"$..*=*=*??&4;;N+- 
 av.CJ"1gmmE2C
O&*1gmmE&:&@&@&BC"#"1gmmF3C
O%)C!" 
   	 	> !##)6(A#6t!= > >	>   CC D(DDc                    	 |j                  d      }d|d   j                  d      i}|d   | j                  j                         vrt	        dj                  |d               |d   j                  d      |d<   d	|d
<   |d   j                  d      j                         |d<   |d   j                  d      |d<   |d   j                  d      |d<   |S # t        $ r  t        $ r#}t        dj                  ||      d	d       d	}~ww xY w)a3  
        The function for parsing ASN fields from a verbose dns response.

        Args:
            response (:obj:`str`): The response from the ASN dns server.

        Returns:
            dict: The ASN lookup results

            ::

                {
                    'asn' (str) - The Autonomous System Number
                    'asn_date' (str) - The ASN Allocation date
                    'asn_registry' (str) - The assigned ASN registry
                    'asn_cidr' (None) - Cannot retrieve with this method.
                    'asn_country_code' (str) - The assigned ASN country code
                    'asn_description' (str) - The ASN description
                }

        Raises:
            ASNRegistryError: The ASN registry is not known.
            ASNParseError: ASN parsing failed.
        r5   r6   r<   r7   r8   r   r9   r:   Nr;   r   r=   r   r?   r>   r@   rA   rB   rC   rJ   s        r1   parse_fields_verbose_dnszIPASN.parse_fields_verbose_dns   s&   4	>>>#&D "47==#78C>"$..*=*=*??&4;;N+- 
 av.CJ"C
O&*1gmmE&:&@&@&BC"#"1gmmE2C
O%)!W]]6%:C!" 
   	 	> !##)6(A#6t!= > >	>rP   c                 @   	 |j                  d      }d|d   j                  d      i}|d   | j                  j                         vrt	        dj                  |d               |d   j                  d      |d<   |d   j                  d      |d	<   |d
   j                  d      j                         |d<   |d   j                  d      |d<   |d   j                  d      |d<   |S # t        $ r  t        $ r#}t        dj                  ||      dd       d}~ww xY w)a"  
        The function for parsing ASN fields from a whois response.

        Args:
            response (:obj:`str`): The response from the ASN whois server.

        Returns:
            dict: The ASN lookup results

            ::

                {
                    'asn' (str) - The Autonomous System Number
                    'asn_date' (str) - The ASN Allocation date
                    'asn_registry' (str) - The assigned ASN registry
                    'asn_cidr' (str) - The assigned ASN CIDR
                    'asn_country_code' (str) - The assigned ASN country code
                    'asn_description' (str) - The ASN description
                }

        Raises:
            ASNRegistryError: The ASN registry is not known.
            ASNParseError: ASN parsing failed.
        r5   r6   r>   r7   r8   r   r:   r<   r;   r   r=      r?      r@   rA   NrB   rC   rJ   s        r1   parse_fields_whoiszIPASN.parse_fields_whois   s3   4	>>>#&D "47==#78C>"$..*=*=*??&4;;N+- 
 au-CJ"1gmmE2C
O&*1gmmE&:&@&@&BC"#"1gmmE2C
O%)!W]]5%9C!" 
   	 	> !##)6(A#6t!= > >	>s   C$C( (D:DDNc           	         | j                   j                         }	 |j                  |       	 ddddddd}	 |d   d   }t        |t              s|g}t        |      D ]   }	 ||d   d   j                            |d<    n |d   s t        j                  d
       t        d      	 |S # t        t        t
        t        f$ r Y w xY w# t        t        f$ r t        j                  d       g }Y w xY w# t        $ r7}t        j                  d	j                  t        |                   Y d}~d}~ww xY w# t        $ r  t         $ r#}t#        dj                  ||      dd       d}~ww xY w)a  
        The function for parsing ASN fields from a http response.

        Args:
            response (:obj:`str`): The response from the ASN http server.
            extra_org_map (:obj:`dict`): Dictionary mapping org handles to
                RIRs. This is for limited cases where ARIN REST (ASN fallback
                HTTP lookup) does not show an RIR as the org handle e.g., DNIC
                (which is now the built in ORG_MAP) e.g., {'DNIC': 'arin'}.
                Valid RIR values are (note the case-sensitive - this is meant
                to match the REST result): 'ARIN', 'RIPE', 'apnic', 'lacnic',
                'afrinic'. Defaults to None.

        Returns:
            dict: The ASN lookup results

            ::

                {
                    'asn' (None) - Cannot retrieve with this method.
                    'asn_date' (None) - Cannot retrieve with this method.
                    'asn_registry' (str) - The assigned ASN registry
                    'asn_cidr' (None) - Cannot retrieve with this method.
                    'asn_country_code' (None) - Cannot retrieve with this
                        method.
                    'asn_description' (None) - Cannot retrieve with this
                        method.
                }

        Raises:
            ASNRegistryError: The ASN registry is not known.
            ASNParseError: ASN parsing failed.
        N)r6   r:   r;   r=   r?   r@   netsr*   zNo networks foundorgRefz@handler6   z*Could not parse ASN registry via HTTP: {0}z%Could not parse ASN registry via HTTPzASN registry lookup failed.rA   rB   )r.   copyupdate	TypeError
ValueError
IndexErrorKeyErrorr,   listlogdebugreversedrH   rG   strr   rI   r   )r0   rK   extra_org_mapr.   asn_datanet_listnrN   s           r1   parse_fields_httpzIPASN.parse_fields_http  s   H ,,##%	NN=)3	> !% $( #'H
#F+E2!(D1 (zH h' 
  (I 6 < < >? ^,   N+		AB&'DEE , s :z8< 		, i( 		-.   II $$*F3q6N4	   	 	> !##)6(A#6t!= > >	>su   B) 	D7 C D7 "C4>(D7 )CC&C1.D7 0C11D7 4	D4=-D/*D7 /D44D7 7E,	E''E,c           	      *   |g d}n h dj                  |      rt        d      |}d}d}d}	t        |      D ]^  \  }
}|dk(  r	 | j                  j                  j
                  |xr |xs dz  | j                  j                  _        | j                  j                         }g }|D ]+  }|j                  | j                  t        |                   - |j                  d      }	 t        |d	         j                  }|D ]$  }t        |d	         j                  }||kD  s!|}|}& 	 d
}	 nm|dk(  r/	 | j                  j)                  |      }| j+                  |      } n9|dk(  s0	 | j                  j-                  |      }| j/                  ||      } n |t!        d      |rI|	rG	 | j                  j1                  dj'                  |d               }| j3                  |      }|d   |d<   |r||d<   |S # t        t        f$ r Y w xY w# t        t         f$ r/}t"        j%                  dj'                  |             Y d}~d}~ww xY w# t        t         f$ r/}t"        j%                  dj'                  |             Y d}~Rd}~ww xY w# t        t         f$ r/}t"        j%                  dj'                  |             Y d}~d}~ww xY w# t        t         f$ r/}t"        j%                  dj'                  |             Y d}~d}~ww xY w)a  
        The wrapper function for retrieving and parsing ASN information for an
        IP address.

        Args:
            inc_raw (:obj:`bool`): Whether to include the raw results in the
                returned dictionary. Defaults to False.
            retry_count (:obj:`int`): The number of times to retry in case
                socket errors, timeouts, connection resets, etc. are
                encountered. Defaults to 3.
            extra_org_map (:obj:`dict`): Mapping org handles to RIRs. This is
                for limited cases where ARIN REST (ASN fallback HTTP lookup)
                does not show an RIR as the org handle e.g., DNIC (which is
                now the built in ORG_MAP) e.g., {'DNIC': 'arin'}. Valid RIR
                values are (note the case-sensitive - this is meant to match
                the REST result): 'ARIN', 'RIPE', 'apnic', 'lacnic', 'afrinic'
                Defaults to None.
            asn_methods (:obj:`list`): ASN lookup types to attempt, in order.
                If None, defaults to all: ['dns', 'whois', 'http'].
            get_asn_description (:obj:`bool`): Whether to run an additional
                query when pulling ASN information via dns, in order to get
                the ASN description. Defaults to True.

        Returns:
            dict: The ASN lookup results

            ::

                {
                    'asn' (str) - The Autonomous System Number
                    'asn_date' (str) - The ASN Allocation date
                    'asn_registry' (str) - The assigned ASN registry
                    'asn_cidr' (str) - The assigned ASN CIDR
                    'asn_country_code' (str) - The assigned ASN country code
                    'asn_description' (str) - The ASN description
                    'raw' (str) - Raw ASN results if the inc_raw parameter is
                        True.
                }

        Raises:
            ValueError: methods argument requires one of dns, whois, http.
            ASNRegistryError: ASN registry does not match.
        N)dnsr+   http>   rk   rl   r+   z;methods argument requires at least one of dns, whois, http.Frk   r   r   r;   TzASN DNS lookup failed: {0}r+   zASN WHOIS lookup failed: {0}rl   )retry_countzASN HTTP lookup failed: {0}z.ASN lookup failed with no more methods to try.AS{0}r:   r@   z"ASN DNS verbose lookup failed: {0}raw)
isdisjointr]   	enumerater-   dns_resolvertimeoutlifetimeget_asn_dnsappendrO   rd   popr   	prefixlenr_   r   r   ra   rb   rG   get_asn_whoisrV   get_asn_httpri   get_asn_verbose_dnsrR   )r0   inc_rawrm   re   asn_methodsget_asn_descriptionlookupsrK   rf   dns_successindexlookup_methodasn_data_list	asn_entry
prefix_len
asn_parsedprefix_len_comprN   asn_verbose_datas                      r1   lookupzIPASN.lookup  sJ   \ .G (22;?  "5 6 6 "G$-g$6 G	 E=%% 		..66'7K<1 II**3
  $yy446H$&M%- -	%,,T-B-B	N., --  -003H%/0D%E%O%O
*7 =J.8 *: 6/88A	 ,.;+5-<
= #'K ')
#yy66{CH#66  "H &(#yy55$/  6  H  $55h7D FHEG	R " $* + + ;9988UO:% &#'#@#@#J .>%/'*+ &HUOE %j1  '(89 II:AA!DE '(89 II<CCAFG  '(89 II;BB1EF( #$45 		>EEaHIs   B!H(:G<#G<)H4,I*.J-AK <HHHHI $I

IJ!$JJK"$KKL#$LLN)Fr   NNT)
__name__
__module____qualname____doc__r2   rO   rR   rV   ri   r    r3   r1   r$   r$   T   s5    	#$8t7r7rbH BF59_r3   r$   c                   6    e Zd ZdZd Z	 	 ddZddZ	 	 d	dZy)
	ASNOriginz
    The class for parsing ASN origin whois data

    Args:
        net (:obj:`ipwhois.net.Net`): A ipwhois.net.Net object.

    Raises:
        NetError: The parameter provided is not an instance of
            ipwhois.net.Net
    c                 L    ddl m} t        ||      r|| _        y t	        d      )Nr   )r&   r)   )r*   r&   r,   r-   r   )r0   r*   r&   s      r1   r2   zASNOrigin.__init__0  s,     c3DI  - . .r3   Nc                    i }sg dfd|j                         D        }|D ]  \  }}	t        j                  t        |	      t        j                        }	||	j                  |||      }
n&||	j                  ||      }
n|	j                  |      }
g }d}|
D ][  }|r||j                         dz
  k7  r nA	 |j                  |j                  d      j                                |j                         }] t        |      dkD  sd}	 |d   }|||<    |S # t        $ r Y =w xY w# t        $ r/}t        j                  dj!                  ||             Y d}~Kd}~ww xY w)a  
        The function for parsing ASN whois fields from a data input.

        Args:
            response (:obj:`str`): The response from the whois/rwhois server.
            fields_dict (:obj:`dict`): Mapping of fields->regex search values.
            net_start (:obj:`int`): The starting point of the network (if
                parsing multiple networks). Defaults to None.
            net_end (:obj:`int`): The ending point of the network (if parsing
                multiple networks). Defaults to None.
            field_list (:obj:`list`): If provided, a list of fields to parse:
                ['description', 'maintainer', 'updated', 'source']
                If None, defaults to all fields.

        Returns:
            dict: A dictionary of fields provided in fields_dict.
        r   c              3   4   K   | ]  \  }}|v r||f  y wr   r   ).0fieldpattern
field_lists      r1   	<genexpr>z)ASNOrigin.parse_fields.<locals>.<genexpr>X  s,      @)9%+0J+> G$ @s   Nr   valr   z2ASN origin Whois field parsing failed for {0}: {1})itemsrecompilerd   DOTALLfinditerstartrv   grouprE   r^   endlenr]   ra   rb   rG   )r0   rK   fields_dict	net_startnet_endr   rM   generater   r   matchvaluessub_section_endmvaluerN   s        `          r1   parse_fieldszASNOrigin.parse_fields>  s|   ( KJ@%%'@ ' 3	#NE7jjG		G
 $((7IF$((7;  ((2F"O *"&1779q=9MM!''%."6"6"89 #$%%'*" 6{Q"1IE #E
g3	#j 
+ "  " II $$*F5!$46	s*   8.D
D'	D$#D$'	E0%EEc                 p   g }|rd}nd}t        j                  ||t         j                        D ]u  }	 t        j                  t
              }|j                  d      j                         |d<   |j                         |d<   |j                         |d<   |j                  |       w |S # t        $ r Y w xY w)a  
        The function for parsing network blocks from ASN origin data.

        Args:
            response (:obj:`str`): The response from the RADB whois/http
                server.
            is_http (:obj:`bool`): If the query is RADB HTTP instead of whois,
                set to True. Defaults to False.

        Returns:
            list: A list of network block dictionaries

            ::

                [{
                    'cidr' (str) - The assigned CIDR
                    'start' (int) - The index for the start of the parsed
                        network block
                    'end' (int) - The index for the end of the parsed network
                        block
                }]
        z"route(?:6)?:[^\S\n]+(?P<val>.+?)\nz$^route(?:6)?:[^\S\n]+(?P<val>.+|.+)$r   r   r   r   )r   r   	MULTILINErZ   deepcopyBASE_NETr   rE   r   r   rv   r]   )r0   rK   is_httprX   regexr   r*   s          r1   get_nets_radbzASNOrigin.get_nets_radb  s    0 9E;E [[
 	E
mmH-#kk!n224F${{}G"YY[E
C 	$ 	  s   A2B))	B54B5c                    |dd dk7  rdj                  |      }|ddg}n ddhj                  |      rt        d      |}|g dd	}d
}	|t        |      D ]  \  }
}|dk(  rD	 t        j                  dj                  |             | j                  j                  ||      } nh|dk(  sU	 t        j                  dj                  |             | j                  j                  dj                  t        d   d   |      |d      }d}	 n |t        d      |r||d<   g }| j                  ||	      }|j                  |       |	rt        }nt         }t        j                  d       t        |      D ]X  \  }
}d}|
dz   t#        |      k  r||
dz      d   }| j%                  ||d   d   ||d   |      }|j'                  |       |d= |d= Z ||d<   |S # t        t        f$ r/}t        j                  dj                  |             Y d}~d}~ww xY w# t        $ r/}t        j                  dj                  |             Y d}~d}~ww xY w)a?  
        The function for retrieving and parsing ASN origin whois information
        via port 43/tcp (WHOIS).

        Args:
            asn (:obj:`str`): The ASN (required).
            inc_raw (:obj:`bool`): Whether to include the raw results in the
                returned dictionary. Defaults to False.
            retry_count (:obj:`int`): The number of times to retry in case
                socket errors, timeouts, connection resets, etc. are
                encountered. Defaults to 3.
            response (:obj:`str`): Optional response object, this bypasses the
                Whois lookup. Defaults to None.
            field_list (:obj:`list`): If provided, fields to parse:
                ['description', 'maintainer', 'updated', 'source']
                If None, defaults to all.
            asn_methods (:obj:`list`): ASN lookup types to attempt, in order.
                If None, defaults to all ['whois', 'http'].

        Returns:
            dict: The ASN origin lookup results

            ::

                {
                    'query' (str) - The Autonomous System Number
                    'nets' (list) - Dictionaries containing network
                        information which consists of the fields listed in the
                        ASN_ORIGIN_WHOIS dictionary.
                    'raw' (str) - Raw ASN origin whois results if the inc_raw
                        parameter is True.
                }

        Raises:
            ValueError: methods argument requires one of whois, http.
            ASNOriginLookupError: ASN origin lookup failed.
        r   r<   ASrn   Nr+   rl   z6methods argument requires at least one of whois, http.)r   rX   ro   Fz;Response not given, perform ASN origin WHOIS lookup for {0})r:   rm   z#ASN origin WHOIS lookup failed: {0}z;Response not given, perform ASN origin HTTP lookup for: {0}zM{0}?advanced_query=1&keywords={1}&-T+option=&ip_option=&-i=1&-i+option=originr   r    GET)r    rm   request_typeTz"ASN origin HTTP lookup failed: {0}z5ASN origin lookup failed with no more methods to try.ro   zParsing ASN origin datar   r   r   r   rX   )rG   rp   r]   rq   ra   rb   r-   get_asn_origin_whoisr	   r
   get_http_rawASN_ORIGIN_HTTPr   r   r   extendASN_ORIGIN_WHOISr   r   r[   )r0   r:   r|   rm   rK   r   r}   r   resultsr   r   r   rN   rX   nets_responser   r*   section_endtemp_nets                      r1   r   zASNOrigin.lookup  s   P q8t..%C'G  ++K8  "0 1 1 "G 
  (1'(: 1$} G+		 #99?F $(99#A#A # $B $  #f,		 #99?F $(99#9#9"F#)6/&*A%*H##N(3). $: $ #'W1f * ,B C C %GEN**8W=M"$F%F 			+,#D/ 	)JE3Kqy3t9$"519og6((vx(E
H JJx  Gc%j'	), g -.AB 		 #%%+VAY0	: + 		 #%%+VAY0	s2   "AG,AHH&$HH	I!$II)NNN)F)NFr   NNN)r   r   r   r   r2   r   r   r   r   r3   r1   r   r   $  s2    	. =A.2Rh3j GK,0hr3   r   )r   sysrZ   logging
exceptionsr   r   r   r   r   r	   r
   r   version_info	ipaddressr   ipaddrr   	getLoggerr   ra   r   r   r   r$   r   r   r3   r1   <module>r      s   2 
 
  D D D v$ /g!  "<<:8	

  *)!!
 =<:8	
,M M`K Kr3   