
    gH                        d dl 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
mZ d dlZe j                  dk\  rd dlmZmZmZmZmZmZmZ nd dlmZmZmZmZmZmZmZ 	 d dlmZ  ej<                  e      Z i d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)Z!d*Z"d+ Z#d, Z$d4d-Z%d. Z&d/ Z'd5d0Z(d6d1Z)d7d2Z*d7d3Z+y# e$ r	 d d	lmZ Y tw xY w)8    N)parseString)path)
namedtuple)   r   )
ip_address
ip_networkIPv4AddressIPv4NetworkIPv6Addresssummarize_address_rangecollapse_addresses)	IPAddress	IPNetworkr	   r
   r   r   collapse_address_list)filterfalse)ifilterfalseRFC 1122, Section 3.2.1.3z2http://tools.ietf.org/html/rfc1122#section-3.2.1.3RFC 1918z"http://tools.ietf.org/html/rfc1918RFC 3927z"http://tools.ietf.org/html/rfc3927RFC 5736z"http://tools.ietf.org/html/rfc5736RFC 5737z"http://tools.ietf.org/html/rfc5737RFC 3068z"http://tools.ietf.org/html/rfc3068RFC 2544z"http://tools.ietf.org/html/rfc2544RFC 3171z"http://tools.ietf.org/html/rfc3171RFC 919, Section 7z+http://tools.ietf.org/html/rfc919#section-7RFC 4291, Section 2.7z.http://tools.ietf.org/html/rfc4291#section-2.7RFC 4291z"http://tools.ietf.org/html/rfc4291RFC 4291, Section 2.5.2z0http://tools.ietf.org/html/rfc4291#section-2.5.2RFC 4291, Section 2.5.3z0http://tools.ietf.org/html/rfc4291#section-2.5.3RFC 4291, Section 2.5.6z0http://tools.ietf.org/html/rfc4291#section-2.5.6RFC 4291, Section 2.5.7z0http://tools.ietf.org/html/rfc4291#section-2.5.7RFC 4193z#https://tools.ietf.org/html/rfc4193a  (?P<ip>(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.)){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|\[?(((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?))\]?((:(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}))|(\/(?:[012]\d?|3[012]?|[4-9])))?)c                     | j                         j                  d      }t        |      D ]8  \  }}|j                  d      d   j                  d      ||<   ||   dv s4d||<   : dj	                  |      S )z
    The function to strip leading zeros in each octet of an IPv4 address.

    Args:
        address (:obj:`str`): An IPv4 address.

    Returns:
        str: The modified IPv4 address.
    ./r   0) N)stripsplit	enumeratelstripjoin)addressobjxys       "/opt/Tautulli/lib/ipwhois/utils.pyipv4_lstrip_zerosr2   u   sx     --/


$C# 1 a'',Aq6ZCF 88C=    c           
         g }	 |j                  t        t        |       t        |                   t        |      D cg c]  }|j                          c}S # t        t        t
        f$ r 	 |j                  t        t        |       j                  t        |      j                               nP# t        $ rD |j                  t        t        |       j                  t        |      j                               Y nw xY wY w xY wc c}w )a  
    The function to calculate a CIDR range(s) from a start and end IP address.

    Args:
        start_address (:obj:`str`): The starting IP address.
        end_address (:obj:`str`): The ending IP address.

    Returns:
        list of str: The calculated CIDR ranges.
    )extendr   r   KeyError
ValueError	TypeErrorr   network_addressAttributeErroripr   __str__)start_addressend_address	tmp_addrsis       r1   calculate_cidrrA      s     I-0}%{#% 	&$ "4I!>?AAIIK?? j), -
	-4=)99;'779 :  	-4=),,;'**, -	-- @s<   -A DD-AB/.D/A
C<9D;C<<DDc                    i }t         j                  dk(  r5t        t         dd      r$t        j                  t         j
                        }nt        j                  t              }| r t        j                  dj                  t        |      dz                t        j                  t        |      dz   dd      }|j                         }|j                          |si S t        |      }|j!                  d	      }|D ]e  }|j!                  d
      d   j"                  j$                  }|j!                  d      d   j"                  j$                  }	|	j'                         ||<   g |S t        j                  dj                  t        |      dz                t        j                  t        |      dz   dd      }t)        j*                  |dd      }
|
D ]  }|d   }|d   }	|	||<    |j                          |S )aU  
    The function to generate a dictionary containing ISO_3166-1 country codes
    to names.

    Args:
        is_legacy_xml (:obj:`bool`): Whether to use the older country code
            list (iso_3166-1_list_en.xml).

    Returns:
        dict: A mapping of country codes as the keys to the country names as
            the values.
    win32frozenFz$Opening country code legacy XML: {0}z/data/iso_3166-1_list_en.xmlrz
ISO-8859-1)encodingzISO_3166-1_EntryzISO_3166-1_Alpha-2_Code_elementr   zISO_3166-1_Country_namezOpening country code CSV: {0}z/data/iso_3166-1.csvzutf-8,")	delimiter	quotechar   )sysplatformgetattrr   dirname
executable__file__logdebugformatstrioopenreadcloser   getElementsByTagName
firstChilddatatitlecsvreader)is_legacy_xml	countriesdata_dirfr\   domentriesentrycodename
csv_readerrows               r1   get_countriesrk      s    I ||w73%#@<</ <<)		8??H >>@ 	A GGCM$BBC)+ vvx		 I $ **+=>  		+E --133466@j --)++,..8j  #jjlIdO		+F - 			188H >>@ 	A GGCM$::C$& ZZSC@
  	#C q6Dq6D #IdO	# 	
	r3   c                    t        t        |             }t        dd      }|t        d      v r
 |ddd      S |j                  r
 |ddd      S |j
                  r
 |ddd	      S |t        d
      v r
 |ddd      S |t        d      v r
 |ddd      S |t        d      v r
 |ddd      S |t        d      v r
 |ddd      S |t        d      v r
 |ddd      S |t        d      v r
 |ddd      S |j                  r
 |ddd      S |t        d      v r
 |ddd      S |j                  r
 |ddd       S |t        d!      v r
 |dd"d#      S  |d$d#d#      S )%a  
    The function for checking if an IPv4 address is defined (does not need to
    be resolved).

    Args:
        address (:obj:`str`): An IPv4 address.

    Returns:
        namedtuple:

        :is_defined (bool): True if given address is defined, otherwise
            False
        :ietf_name (str): IETF assignment name if given address is
            defined, otherwise ''
        :ietf_rfc (str): IETF assignment RFC if given address is defined,
            otherwise ''
    ipv4_is_defined_resultsis_defined, ietf_name, ietf_rfcz	0.0.0.0/8TzThis Networkr   Loopbackz
Link Localr   z192.0.0.0/24zIETF Protocol Assignmentsr   z192.0.2.0/24z
TEST-NET-1r   z192.88.99.0/24z6to4 Relay Anycastr   z198.18.0.0/15z-Network Interconnect Device Benchmark Testingr   z198.51.100.0/24z
TEST-NET-2z203.0.113.0/24z
TEST-NET-3	Multicastr   z255.255.255.255/32zLimited Broadcastr   zPrivate-Use Networksr   z198.97.38.0/24zIANA Reservedr'   F)r	   rU   r   r
   is_loopbackis_link_localis_multicast
is_privater-   query_ipresultss      r1   ipv4_is_definedrx     s   ( 3w<(H 2 5? @G ;{++t^-HII 
		tZ)DEE 
		t\:66 
[0	0t8*EE 
[0	0t\:66 
[!12	2t1:>> 
[1	1?"$ 	%
 
[!23	3t\:66 
[!12	2t\:66 
		t[*55 
[!56	6t02FGG 
		t3Z@@ 
[!12	2t_b115"b!!r3   c                    t        t        |             }t        dd      }|j                  r
 |ddd      S |j                  r
 |ddd      S |j
                  r
 |ddd	      S |j                  r
 |dd
d      S |j                  r
 |ddd      S |j                  r
 |ddd      S |j                  r
 |ddd      S  |ddd      S )a  
    The function for checking if an IPv6 address is defined (does not need to
    be resolved).

    Args:
        address (:obj:`str`): An IPv6 address.

    Returns:
        namedtuple:

        :is_defined (bool): True if given address is defined, otherwise
            False
        :ietf_name (str): IETF assignment name if given address is
            defined, otherwise ''
        :ietf_rfc (str): IETF assignment RFC if given address is defined,
            otherwise ''
    ipv6_is_defined_resultsrn   Trp   r   Unspecifiedr   ro   r   Reservedr   z
Link-Localr    z
Site-Localr!   zUnique Local Unicastr"   Fr'   )
r   rU   r   rs   is_unspecifiedrq   is_reservedrr   is_site_localrt   ru   s      r1   ipv6_is_definedr   l  s    ( 3w<(H 2 5? @G t[*ABB 
	 	 t],EFF 
		tZ)BCC 
		tZ44 
		t\+DEE 
		t\+DEE 
		t3Z@@5"b!!r3   c              #      K   t               }|j                  }|(t        |j                  |       D ]  } ||       |  y| D ]  } ||      }||vs ||       |  yw)az  
    The generator to list unique elements, preserving the order. Remember all
    elements ever seen. This was taken from the itertools recipes.

    Args:
        iterable (:obj:`iter`): An iterable to process.
        key (:obj:`callable`): Optional function to run when checking
            elements (e.g., str.lower)

    Yields:
        The next unique element found.
    N)setaddr   __contains__)iterablekeyseenseen_addelementks         r1   unique_everseenr     ss      5DxxH
{"4#4#4h? 	GWM	   	GGA}	s   AA$A$c                 H   | s|st        d      i }di d}d}|rbt        j                  dj                  t	        |                   t        t	        |      d      }|j                         }|j                          t        j                  t	        t              t        j                        }t        j                  dj                  t	        |                   | |fD ]  }|s|j                  |      D ]  }d}	d}
	 |j                  d	      }d
|v r d|v r|j                  d      }|d   }|d   }
n.d|v r|j                  d      }|d   dd }|d   }
nd|v rd}	|}n|}|	rt        |      }nt!        |      }|j#                         }||j%                         vrt'        j(                  |      ||<   ||   dxx   dz  cc<   |
r	 ||   d   t	        |
      xx   dz  cc<    	 |S # t*        $ r d||   d   t	        |
      <   Y &w xY w# t*        t         f$ r Y )w xY w)a  
    The function to search an input string and/or file, extracting and
    counting IPv4/IPv6 addresses/networks. Summarizes ports with sub-counts.
    If both a string and file_path are provided, it will process them both.

    Args:
        data (:obj:`str`): The data to process.
        file_path (:obj:`str`): An optional file path to process.

    Returns:
        dict: The addresses/networks mapped to ports and counts:

        ::

            {
                '1.2.3.4' (dict) - Each address or network found is a
                    dictionary:
                    {
                        'count' (int) - Total number of times seen.
                        'ports' (dict) - Mapping of port numbers as keys and
                            the number of times seen for this ip as values.
                    }
            }

    Raises:
        ValueError: Arguments provided are invalid.
    zNo data or file path provided.r   )countportsNz-Opening file for unique address analysis: {0}rE   zAnalyzing input/file dataFr;   r$   :rK   [z]:r%   Tr   r   )r7   rR   rS   rT   rU   rW   rX   rY   recompileIP_REGEXDOTALLfinditergroupr)   r   r   r<   keyscopydeepcopyr6   )r\   	file_pathretbase	file_datarc   pattern
input_datamatchis_netportfoundr)   	ip_or_netip_objobj_strs                   r1   unique_addressesr     sF   : 	9::
CD
 I		AHHI  	! Y% FFH			jjH
		G II)00I  !Y' =
 !))*5 84!KK-Ee|u %C 0$)!H	$Qx %D 1$)!HQRL	$Qx!%$)	 %*	!+I!6 ",I!6$nn.Gchhj0'+}}T':GL)Q.)AL1#d)<A<a8=~ J  ( A?@CL1#d)<A !*- s1   ?CHG++HH
HHH! H!c              #      K   d}t               }|| k  r[t        t        t        j                  dd                  }t        |      d   s||vr|dz  }|j                  |       | || k  rZyyw)a  
    The generator to produce random, unique IPv4 addresses that are not
    defined (can be looked up using ipwhois).

    Args:
        total (:obj:`int`): The total number of IPv4 addresses to generate.

    Yields:
        str: The next IPv4 address.
    r   l    rK   N)r   rU   r	   randomrandintrx   r   totalr   yieldedr-   s       r1   ipv4_generate_randomr   L  sl      EeG
%-k&..G"<=>w'*wg/EQJEKK M %-s   A+A0.A0c           	   #      K   d}t               }|| k  rat        t        t        j                  dddz  dz
                    }t        |      d   s||vr|dz  }|j                  |       | || k  r`yyw)a  
    The generator to produce random, unique IPv6 addresses that are not
    defined (can be looked up using ipwhois).

    Args:
        total (:obj:`int`): The total number of IPv6 addresses to generate.

    Yields:
        str: The next IPv6 address.
    r         rK   N)r   rU   r   r   r   r   r   r   s       r1   ipv6_generate_randomr   e  st      EeG
%-k&..AsF1H"=>?w'*wg/EQJEKK M %-s   A1A64A6)F)N)NN)d   ),rL   xml.dom.minidomr   osr   r   r   rV   r^   r   collectionsr   loggingversion_info	ipaddressr   r   r	   r
   r   r   r   ipaddrr   r   r   	itertoolsr   ImportErrorr   	getLogger__name__rR   IETF_RFC_REFERENCESr   r2   rA   rk   rx   r   r   r   r   r    r3   r1   <module>r      s  2  '  	  	 
  " v/ / /E E E6%
 g!8 4	
 4 4 4 4 4 4 G M 4 6!" 6%& 6)* 6-. 5/ 6	 	<0"@JVr^"B<"~!Hzz2[  656s   $C CC