
    g                        d Z dZddlZddlZ	 ddlmZ ddddddddddd	
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!d"d#i d$d%d&d'd(d)d*d)d+d)d,d%d-d.d/d%d0d1d2d)d3d)d4d'd5d)d6d)d7d)d8d)d9d)i d:dd;d)d<d=d>d%d?d)d@d'dAd)dBd)dCd)dDd%dEd%dFd%dGdHdId)dJd%dKd'dLd'i dMd'dNd1dOd)dPd=dQddRddSddTddUddVddWddXddYddZdd[dd\d]d^dd_dd`dadbdcdddedfdgdhdidjZ
dkZdlZdmZdnZ	 eefZeefZe  G do dpe      Z G dq dre      Z G ds dtej6                        Zdu ZddvZdw Zdx Z dy Z!i dzd{d|dd}d~ddSddddddddddddddddddddddYddZ"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+e,dk(  r2ddl-Z- e-j\                         \  Z/Z0e/rddl1Z1 e1jd                  d       yyy# e$ r ddlZY w xY w# e$ r efZefZeZY w xY w)z
IPy - class and tools for handling of IPv4 and IPv6 addresses and networks.
See README file for learn how to use IPy.

Further Information might be available at:
https://github.com/haypo/python-ipy
z1.01    NPUBLICPRIVATECARRIER_GRADE_NATLOOPBACKRESERVED)
00000000000001010
011001000101111111110101001111111101010110000011100000010101000111r	   `000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ڀ00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000UNSPECIFIEDڀ00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001`000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111IPV4MAP`000000000110010011111111100110110000000000000000000000000000000000000000000000000000000000000000
WKP46TRANS00000001
UNASSIGNED000000100000100000011000010001001zGLOBAL-UNICAST00100000000000010000000SPECIALPURPOSE 00100000000000010000000000000000TEREDO0001000000000000100000000000000100000000000000000BMWG0010000000000001000000000001ORCHID00100000000000010000001zALLOCATED APNIC00100000000000010000010zALLOCATED ARIN00100000000000010000011zALLOCATED RIPE NCC001000000000000100001000010000000000001000010100100000000000010000110 00100000000000010000110110111000DOCUMENTATION0010000000000001000011100100000000000010001001zALLOCATED LACNIC00100000000000010001010001000000000000100010110010000000000001000110000100000000000010001101001000000000000100011100100000000000010010001000000000000100110001000000000000100111000100000000000010011110010000000000001010000000100000000000010100001zALLOCATED AFRINIC0010000000000001010001000100000000000010100011001000000000000101001000010000000000001010010100100000000000010100110001000000000000101010010000000000001100001000000000000110100010000000000001101100100000000000106TO4001000000000001100001001000000001001100000001001100001000000000000010011000100000000000000101000000000101010000000101100000000101101001011100110100111001011101110111101111101111110ULA	111111100	LINKLOCAL	MULTICASTzNODE-LOCAL MULTICASTzLINK-LOCAL MULTICASTzADMIN-LOCAL MULTICASTzSITE-LOCAL MULTICASTzORG-LOCAL MULTICASTzGLOBAL MULTICASTzRESERVED MULTICASTzPREFIX-BASED MULTICASTzRP-EMBEDDED MULTICAST)
1111111010
1111111011111111111111111100000001111111110000001011111111000001001111111100000101111111110000100011111111000011101111111100001111111111110011111111110111l    l	    l	        l        c                       e Zd ZdZd$dZd Zd Zd Zd Zd Z	d Z
d%d
Zd%dZd%dZd%dZd%dZd%dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d  Z!d! Z"d" Z#d# Z$y	)&IPintzHandling of IP addresses returning integers.

    Use class IP instead because some features are not implemented for
    IPint.c                 B   d| _         d| _        d}d}t        |t              rt	        |      | _        |dk(  r| j
                  t        k  rd}nd}|dk(  r4| j
                  t        kD  rt        dt        | j
                  fz        d}nD|dk(  r4| j
                  t        kD  rt        d	t        | j
                  fz        d
}nt        d      || _	        || _
        yt        |t              r4|j                  | _	        |j                  | _
        |j
                  | _        yt        |t              rY|j                  d      }t        |      dk(  r|\  }}t        |      \  | _        }	|	dk7  rt        d      t        |      \  }}
|
dk7  rt        d      || j
                  k  rt        d      || j
                  z
  }t!        |      }t#        |dd|z
        j%                         j	                         |k7  rt        d|z        t        |      dk(  r|j                  d      }t        |      dk(  r|d   }d}nt        |      dkD  rt        d      |\  }}|j'                  d      dk7  rNt        |      \  }}|dk7  rt        d      t)        |      }n$t        |      dkD  rt        d      t        d      t        ||      \  | _        }	|dk(  r|	}|dk(  rt+        |      }||z
  }|| _	        t	        |      | _
        |r2| j
                  t-        | j                  | j                        z  | _        t/        | j
                  | j                  | j                        s$t        t1        |       d| j                  d      yt3        dt5        |      z        )a-  Create an instance of an IP object.

        Data can be a network specification or a single IP. IP
        addresses can be specified in all forms understood by
        parseAddress(). The size of a network can be specified as

        /prefixlen        a.b.c.0/24               2001:658:22a:cafe::/64
        -lastIP           a.b.c.0-a.b.c.255        2001:658:22a:cafe::-2001:658:22a:cafe:ffff:ffff:ffff:ffff
        /decimal netmask  a.b.c.d/255.255.255.0    not supported for IPv6

        If no size specification is given a size of 1 address (/32 for
        IPv4 and /128 for IPv6) is assumed.

        If make_net is True, an IP address will be transformed into the network
        address by applying the specified netmask.

        >>> print(IP('127.0.0.0/8'))
        127.0.0.0/8
        >>> print(IP('127.0.0.0/255.0.0.0'))
        127.0.0.0/8
        >>> print(IP('127.0.0.0-127.255.255.255'))
        127.0.0.0/8
        >>> print(IP('127.0.0.1/255.0.0.0', make_net=True))
        127.0.0.0/8

        See module documentation for more examples.
           Nr         (IPv4 Address can't be larger than %x: %x    (IPv6 Address can't be larger than %x: %x   only IPv4 and IPv6 supported-   z)first-last notation only allowed for IPv4z last address should be IPv4, tooz(last address should be larger than first/z*the range %s is not on a network boundary.z"only one '/' allowed in IP Address.znetmask must be IPv4z"only one '-' allowed in IP Addresszcan't parse has invalid prefix length ()zUnsupported data type: %s)NoPrefixForSingleIpWantPrefixLen
isinstance	INT_TYPESintipMAX_IPV4_ADDRESS
ValueErrorMAX_IPV6_ADDRESS
_ipversion
_prefixlenro   	STR_TYPESsplitlenparseAddress_count1BitsIP	broadcastfind_netmaskToPrefixlen_ipVersionToLen_prefixlenToNetmask_checkNetaddrWorksWithPrefixlenrepr	TypeErrortype)selfdata	ipversionmake_netnetbits	prefixlenxr   lastparsedVersionlastversionsizenetmaskversbitss                  /opt/Tautulli/lib/IPy.py__init__zIPint.__init__   sX   < $%  "	 dI&$iDGA~77.. !I !IA~77--$%OSceielelRm%mnn	a77--$%OSceielelRm%mnn	 !?@@'DO'DOe$"ooDO"ooDOggDGi( 

3A1v{
T+7+;(- A%$%PQQ&24&8#{!#$%GHH$''>$%OPPdgg~%d+ RZ01;;=AACtK$%QTX%XYYQ1JJsOq6Q;1B "IVaZ$%IJJ&'OR ~~c*b0 +7y*A$19",-C"DD$7$@	Q! !EFF //'3B	'B$TWmA~)	B&y1 7N	'DO!)nDO''$7$YY2477OOT__. T
TXTcTc!dee. 7$t*DEE    c                     | j                   S )zReturn the first / base / network addess as an (long) integer.

        The same as IP[0].

        >>> "%X" % IP('10.0.0.0/8').int()
        'A000000'
        )r   r   s    r   r   z	IPint.int  s     wwr   c                     | j                   S )zReturn the IP version of this Object.

        >>> IP('10.0.0.0/8').version()
        4
        >>> IP('::1').version()
        6
        )r   r   s    r   versionzIPint.version  s     r   c                     | j                   S )zWReturns Network Prefixlen.

        >>> IP('10.0.0.0/8').prefixlen()
        8
        )r   r   s    r   r   zIPint.prefixlen  s     r   c                 "    | j                         S )zT
        Return the base (first) address of a network as an (long) integer.
        )r   r   s    r   netz	IPint.net'  s     xxzr   c                 J    | j                         | j                         z   dz
  S )zl
        Return the broadcast (last) address of a network as an (long) integer.

        The same as IP[-1].rq   )r   r   r   s    r   r   zIPint.broadcast-  s     
 xxzDHHJ&**r   c                    | j                   dk(  r| j                  dk(  s| j                   dk(  r| j                  dk(  r| j                  rd}|dk(  r| j                  }|dk(  rd}|r|dk(  rI| j	                         }t        |t              s|j                         }d	t        || j                         z  S |d
k(  r7dt        | j                  | j                         z   dz
  | j                         z  S d| j                  z  S y)a  Prints Prefixlen/Netmask.

        Not really. In fact it is our universal Netmask/Prefixlen printer.
        This is considered an internal function.

        want == 0 / None        don't return anything    1.2.3.0
        want == 1               /prefix                  1.2.3.0/24
        want == 2               /netmask                 1.2.3.0/255.255.255.0
        want == 3               -lastip                  1.2.3.0-1.2.3.255
        rs   rv   rt   rx   r   Nrq   r{   /%s   z-%s/%d )r   r   r   r   r   r   r   r   intToIpr   r   )r   wantr   s      r   _printPrefixzIPint._printPrefix4  s     OOq T__%:OOq T__%;''4<%%Dt|qy,,.!'95%kkmG ABB$((*(<q(@$// RSS 00r   Nc                     t        | j                        }| j                  dk(  r|dk(  rd}t        | j                        }d|t        |      z
  z  |z   | j                  |      z   S )aW  Return a string representation as a binary value.

        >>> print(IP('127.0.0.1').strBin())
        01111111000000000000000000000001
        >>> print(IP('2001:0658:022a:cafe:0200::1').strBin())
        00100000000000010000011001011000000000100010101011001010111111100000001000000000000000000000000000000000000000000000000000000001
        Nr   r   )r   r   r   	_intToBinr   r   r   )r   wantprefixlenr   rets       r   strBinzIPint.strBin^  sb     t/%-4*?M tc#h'#-0A0A-0PPPr   c                    | j                   dk(  r|dk(  rd}| j                  dk(  r| j                  |      S | j                  dz	  dk(  r6t	        | j                  t
        z  d      }d|z   | j                  |      z   }|S | j                  d      j                  d      D cg c]  }t        |d	       }}dgd
z  }t        t        |            D ]  }t        ||d       ||<    |j                  t        |            }t        |      dkD  r| j                  d      j                  d      D cg c]  }| }}|t        |      k  r"||   dk(  r||= |t        |      k  r	||   dk(  r|j                  |d       |dz   t        |      k\  r|j!                  d       |dk(  rdg|z   }dj#                  |      | j                  |      z   S | j                  d      | j                  |      z   S c c}w c c}w )ak  Return a string representation in compressed format using '::' Notation.

        >>> IP('127.0.0.1').strCompressed()
        '127.0.0.1'
        >>> IP('2001:0658:022a:cafe:0200::1').strCompressed()
        '2001:658:22a:cafe:200::1'
        >>> IP('ffff:ffff:ffff:ffff:ffff:f:f:fffc/127').strCompressed()
        'ffff:ffff:ffff:ffff:ffff:f:f:fffc/127'
        Nrq   rs   rv     z::ffff:r   :      r   r   )r   r   strFullsizer   r   r   r   r   r   xranger   _countFollowingZerosindexmax	strNormalinsertappendjoin)	r   r   ipv4textr   hextetsfollowingzerosicompressionposs	            r   strCompressedzIPint.strCompressedm  s    %-4*?M??a##M22ww"}&tww)991= 4'$*;*;M*JJ+/+;+;A+>+D+DS+IJas1bzJGJ  S1WNCL) F$8$Eq!F ,11#n2EFN>"Q& '+nnQ&7&=&=c&BC1CC$s7|38OSV8V/ %s7|38OSV8V~r2!A%W5NN2&!Q&!dWnGxx(4+<+<]+KKK~~a(4+<+<]+KKK+ K Ds   !G00	G5c           	         | j                   dk(  r|dk(  rd}| j                  dk(  r| j                  d      }ns| j                  dk(  rYdj                  | j                  d      j	                  d      D cg c]  }t        |d       c}D cg c]  }d|z  	 c}      }nt        d	      || j                  |      z   S c c}w c c}w )
zReturn a string representation in the usual format.

        >>> print(IP('127.0.0.1').strNormal())
        127.0.0.1
        >>> print(IP('2001:0658:022a:cafe:0200::1').strNormal())
        2001:658:22a:cafe:200:0:0:1
        Nrq   rs   r   rt   r   r   %xry   )r   r   r   r   r   r   r   r   )r   r   r   r   s       r   r   zIPint.strNormal  s     %-4*?M??a""1%C__!((4CSCSTUCVC\C\]`Ca.bas1bz.bcD1HcdC;<< T&&}555 /ccs   4B?Cc                     | j                   dk(  r|dk(  rd}t        | j                  | j                        | j	                  |      z   S )zReturn a string representation in the non-mangled format.

        >>> print(IP('127.0.0.1').strFullsize())
        127.0.0.1
        >>> print(IP('2001:0658:022a:cafe:0200::1').strFullsize())
        2001:0658:022a:cafe:0200:0000:0000:0001
        Nrq   )r   r   r   r   r   )r   r   s     r   r   zIPint.strFullsize  sC     %-4*?Mtww043D3D]3SSSr   c                 t    | j                   dk(  r|dk(  rd}d| j                  z  }|| j                  |      z   S )zReturn a string representation in hex format in lower case.

        >>> print(IP('127.0.0.1').strHex())
        0x7f000001
        >>> print(IP('2001:0658:022a:cafe:0200::1').strHex())
        0x20010658022acafe0200000000000001
        Nr   z0x%xr   r   r   r   r   r   s      r   strHexzIPint.strHex  sB     %-4*?MTWW4$$]333r   c                 t    | j                   dk(  r|dk(  rd}d| j                  z  }|| j                  |      z   S )zReturn a string representation in decimal format.

        >>> print(IP('127.0.0.1').strDec())
        2130706433
        >>> print(IP('2001:0658:022a:cafe:0200::1').strDec())
        42540616829182469433547762482097946625
        Nr   z%dr   r   s      r   strDeczIPint.strDec  sA     %-4*?M477N4$$]333r   c                     | j                   dk(  rt        }n!| j                   dk(  rt        }nt        d      | j	                         }t        t        |      dd      D ]  }|d| |v s||d|    c S  y)a  Return a description of the IP type ('PRIVATE', 'RESERVED', etc).

        >>> print(IP('127.0.0.1').iptype())
        LOOPBACK
        >>> print(IP('192.168.1.1').iptype())
        PRIVATE
        >>> print(IP('195.185.1.2').iptype())
        PUBLIC
        >>> print(IP('::1').iptype())
        LOOPBACK
        >>> print(IP('2001:0658:022a:cafe:0200::1').iptype())
        ALLOCATED RIPE NCC

        The type information for IPv6 is out of sync with reality.
        rs   rt   ry   r   rr   Nunknown)r   
IPv4ranges
IPv6rangesr   r   r   r   )r   ipranger   r   s       r   iptypezIPint.iptype  s}    & ??a G__! G;<<{{}D	1b) 	)ABQx7"tBQx((	) r   c                 t    t        | j                        }|| j                  z
  }d| j                  z  dz
  |z  S )zrReturn netmask as an integer.

        >>> "%X" % IP('195.185.0.0/16').netmask().int()
        'FFFF0000'
        r{   rq   r   r   r   r   r   locallens      r   r   zIPint.netmask  s9     t/$//)doo%*x77r   c                     t        | j                        }| j                  dk(  r.|| j                  z
  }t        d| j                  z  dz
  |z  d      S | j                  dk(  rd| j                  z  S y)zReturn netmask as an string. Mostly useful for IPv6.

        >>> print(IP('195.185.0.0/16').strNetmask())
        255.255.0.0
        >>> print(IP('2001:0658:022a:cafe::0/64').strNetmask())
        /64
        rs   r{   rq   rt   r   N)r   r   r   r   r   s      r   
strNetmaskzIPint.strNetmask  sl     t/??adoo-HQ$//1Q68CQGG__!4??** "r   c                 T    t        | j                        }|| j                  z
  }d|z  S )zReturn the length of a subnet.

        >>> print(IP('195.185.1.0/28').len())
        16
        >>> print(IP('195.185.1.0/24').len())
        256
        r{   r   r   s      r   r   z	IPint.len  s*     t/$//)H}r   c                      y)a  All IPy objects should evaluate to true in boolean context.
        Ordinarily they do, but if handling a default route expressed as
        0.0.0.0/0, the __len__() of the object becomes 0, which is used
        as the boolean value of the object.
        T r   s    r   __nonzero__zIPint.__nonzero__,  s     r   c                 "    | j                         S N)r   r   s    r   __bool__zIPint.__bool__4  s    !!r   c                 "    | j                         S )z
        Return the length of a subnet.

        Called to implement the built-in function len().
        It will break with large IPv6 Networks.
        Use the object's len() instead.
        r   r   s    r   __len__zIPint.__len__7  s     xxzr   c                 t   | j                   |j                   k7  rt        d      | j                  |j                  k7  rt        d      | j                  dk  rt        d      | |kD  r|j                  |       S |j	                         | d   j	                         z
  dk7  rt        d      t        | j	                         | j                         }| j                         dz
  |_        t        |j                  |j                  |j                         s%t        dt        |      d	|j                  d
      |S )z3Emulate numeric objects through network aggregationz4Only networks with the same IP version can be added.z3Only networks with the same prefixlen can be added.rq   z8Networks with a prefixlen longer than /1 can't be added.rr   z-Only adjacent networks can be added together.r   zThe resulting r~   r   )
r   r   r   __add__r   r   r   r   r   r   )r   otherr   s      r   r   zIPint.__add__A  s    ??e...STT??e...RSS??QWXX%<==&&99;b'1,LMMt7)A-.svvs~~/2~~? $S	3>>; < <
r   c                     t        | |      S )z<Return the prefixes that are in this IP but not in the other)_remove_subprefixr   r   s     r   __sub__zIPint.__sub__V  s     u--r   c                    t        |t              rDt        |j                  t	        |              D cg c]  }| j
                  t        |      z    c}S t        |t              st        |dk  r?t        |      | j	                         k  r| j	                         t        |      z
  }nt        || j	                         k\  rt        | j
                  t        |      z   S c c}w )aN  Called to implement evaluation of self[key].

        >>> ip=IP('127.0.0.0/30')
        >>> for x in ip:
        ...  print(repr(x))
        ...
        IP('127.0.0.0')
        IP('127.0.0.1')
        IP('127.0.0.2')
        IP('127.0.0.3')
        >>> ip[2]
        IP('127.0.0.2')
        >>> ip[-1]
        IP('127.0.0.3')
        r   )r   slicer   indicesr   r   r   r   r   abs
IndexErrorr   keyr   s      r   __getitem__zIPint.__getitem__Z  s    " c5!.4ckk#d)6L.MNDGGc!f$NN#y)O73x488:%hhj3s8+  dhhj   wwS!! Os   C c                    t        |t              r|j                  | j                  k7  ryt        |      }|j                  | j                  k\  r?|j                  | j                  | j	                         z   |j	                         z
  dz   k  ryy)a  Called to implement membership test operators.

        Should return true if item is in self, false otherwise. Item
        can be other IP-objects, strings or ints.

        >>> IP('195.185.1.1').strHex()
        '0xc3b90101'
        >>> 0xC3B90101 in IP('195.185.1.0/24')
        True
        >>> '127.0.0.1' in IP('127.0.0.0/24')
        True
        >>> IP('127.0.0.0/24') in IP('127.0.0.0/25')
        False
        Frq   T)r   r   r   r   r   r   items     r   __contains__zIPint.__contains__|  sk      dB$//1d8D77dgg$''DGGdhhj,@488:,MPQ,Q"Qr   c                 J   t        |t              st        |      }|j                  | j                  k\  r+|j                  | j                  | j                         z   k  ry| j                  |j                  k\  r+| j                  |j                  |j                         z   k  ryy)a  Check if two IP address ranges overlap.

        Returns 0 if the two ranges don't overlap, 1 if the given
        range overlaps at the end and -1 if it does at the beginning.

        >>> IP('192.168.0.0/23').overlaps('192.168.1.0/24')
        1
        >>> IP('192.168.0.0/23').overlaps('192.168.1.255')
        1
        >>> IP('192.168.0.0/23').overlaps('192.168.2.0')
        0
        >>> IP('192.168.1.0/24').overlaps('192.168.0.0/23')
        -1
        rq   rr   r   )r   r   r   r   r  s     r   overlapszIPint.overlaps  st      $#d8D77dgg$''DGGdhhj,@"@WWDGGdgg
.B$Br   c                 "    | j                         S )zSDispatch to the prefered String Representation.

        Used to implement str(IP).r   r   s    r   __str__zIPint.__str__  s    
 !!##r   c                 *    d| j                  d      z  S )a  Print a representation of the Object.

        Used to implement repr(IP). Returns a string which evaluates
        to an identical Object (without the wantprefixlen stuff - see
        module docstring.

        >>> print(repr(IP('10.0.0.0/24')))
        IP('10.0.0.0/24')
        zIPint('%s')rq   r  r   s    r   __repr__zIPint.__repr__  s      2 21 567r   c                    t        |t              st        | j                  |j                  k7  r!| j                  |j                  k  xr dxs dS | j                  |j                  k7  r!| j                  |j                  k  xr dxs dS | j
                  |j
                  k7  r!| j
                  |j
                  k  xr dxs dS y)a&  Called by comparison operations.

        Should return a negative integer if self < other, zero if self
        == other, a positive integer if self > other.
        
        Order is first determined by the address family. IPv4 addresses
        are always smaller than IPv6 addresses:
        
        >>> IP('10.0.0.0') < IP('2001:db8::')
        1
        
        Then the first address is compared. Lower addresses are
        always smaller:
        
        >>> IP('10.0.0.0') > IP('10.0.0.1')
        0
        >>> IP('10.0.0.0/24') > IP('10.0.0.1')
        0
        >>> IP('10.0.1.0') > IP('10.0.0.0/24')
        1
        >>> IP('10.0.1.0/24') > IP('10.0.0.0/24')
        1
        >>> IP('10.0.1.0/24') > IP('10.0.0.0')
        1
        
        Then the prefix length is compared. Shorter prefixes are
        considered smaller than longer prefixes:
        
        >>> IP('10.0.0.0/24') > IP('10.0.0.0')
        0
        >>> IP('10.0.0.0/24') > IP('10.0.0.0/25')
        0
        >>> IP('10.0.0.0/24') > IP('10.0.0.0/23')
        1

        rr   rq   r   )r   ro   r   r   r   r   r   s     r   __cmp__zIPint.__cmp__  s    J %'O ??e...??U%5%55<"AA 77ehh77UXX%,"11 ??e...??U%5%55<"AA r   c                 L    t        |t              sy| j                  |      dk(  S )NFr   )r   ro   r  r   s     r   __eq__zIPint.__eq__  s#    %'||E"a''r   c                 &    | j                  |       S r   )r  r   s     r   __ne__zIPint.__ne__  s    ;;u%%%r   c                 *    | j                  |      dk  S Nr   r  r   s     r   __lt__zIPint.__lt__  s    ||E"Q&&r   c                 *    | j                  |      dk  S r  r  r   s     r   __le__zIPint.__le__	  s    ||E"a''r   c                     t        d      }| j                  }|dkD  r||dz  z  }|dz	  }|dkD  r|| j                  z  }t        |      S )ah  Called for the key object for dictionary operations, and by
        the built-in function hash(). Should return a 32-bit integer
        usable as a hash value for dictionary operations. The only
        required property is that objects which compare equal have the
        same hash value

        >>> IP('10.0.0.0/24').__hash__()
        -167772185
        rr   r   irv   )r   r   r   )r   thehashr   s      r   __hash__zIPint.__hash__  sW     b'WW1fj1GrB 1f DOO+7|r   )r   r   r   )%__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r	  r  r  r  r  r  r  r  r  r   r   r   ro   ro      s    
{Fz+!TQ+LZ6.T44B8+$"*."D64$85n(
&'(r   ro   c                   R    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zy)r   z-Class for handling IP addresses and networks.c                 V    t        t        j                  |       | j                        S )zReturn the base (first) address of a network as an IP object.

        The same as IP[0].

        >>> IP('10.0.0.0/8').net()
        IP('10.0.0.0')
        r   )r   ro   r   r   r   s    r   r   zIP.net#  s     %))D/T__==r   c                 >    t        t        j                  |             S )zReturn the broadcast (last) address of a network as an IP object.

        The same as IP[-1].

        >>> IP('10.0.0.0/8').broadcast()
        IP('10.255.255.255')
        )r   ro   r   r   s    r   r   zIP.broadcast-  s     %//$'((r   c                 V    t        t        j                  |       | j                        S )ziReturn netmask as an IP object.

        >>> IP('10.0.0.0/8').netmask()
        IP('255.0.0.0')
         r   )r   ro   r   r   r   s    r   r   z
IP.netmask7  s     %--%AAr   c                     | j                   dk7  ry | j                  dz	  dk7  ry | j                  t        z  }| j                  dk7  r|ddd| j                  z
  z
  }t	        |d      S )Nrt   rv   r   rx   r|   rs   r   )r   r   r   r   r   )r   r   s     r   _getIPv4MapzIP._getIPv4Map?  sd    ??aGGrMf$ww))??c!"BDOO(;$<=D$!$$r   c                    | j                   dk(  r8g }| j                         dk  r(| D ]!  }|j                  |j                                # |S | j                         dk  rGt	        d| j                         d      D ]'  }|j                  | |   j                         dd        ) |S | j                         dk  rGt	        d| j                         d      D ]'  }|j                  | |   j                         dd        ) |S t	        d| j                         d      D ]'  }|j                  | |   j                         dd        ) |S | j                   dk(  r| j                         }||j                         S d	| j                  z  }| j                  dz  dk7  rt        d
      t        |      }|j                          dj                  |      }t        d| j                  dz  z
        dz  }d||d z  gS t        d      )a  Return a list with values forming the reverse lookup.

        >>> IP('213.221.113.87/32').reverseNames()
        ['87.113.221.213.in-addr.arpa.']
        >>> IP('213.221.112.224/30').reverseNames()
        ['224.112.221.213.in-addr.arpa.', '225.112.221.213.in-addr.arpa.', '226.112.221.213.in-addr.arpa.', '227.112.221.213.in-addr.arpa.']
        >>> IP('127.0.0.0/24').reverseNames()
        ['0.0.127.in-addr.arpa.']
        >>> IP('127.0.0.0/23').reverseNames()
        ['0.0.127.in-addr.arpa.', '1.0.127.in-addr.arpa.']
        >>> IP('127.0.0.0/16').reverseNames()
        ['0.127.in-addr.arpa.']
        >>> IP('127.0.0.0/15').reverseNames()
        ['0.127.in-addr.arpa.', '1.127.in-addr.arpa.']
        >>> IP('128.0.0.0/8').reverseNames()
        ['128.in-addr.arpa.']
        >>> IP('128.0.0.0/7').reverseNames()
        ['128.in-addr.arpa.', '129.in-addr.arpa.']
        >>> IP('::1:2').reverseNames()
        ['2.0.0.0.1.ip6.arpa.']
        rs      i   r   r{   Ni   rt   r   z3can't create IPv6 reverse names at sub nibble levelr}   rv   z%s.ip6.arpa.ry   )r   r   r   reverseNamer   r'  reverseNamesr   r   NotImplementedErrorlistreverser   r   r   )r   r   r   r   r   sfirst_nibble_indexs          r   r+  zIP.reverseNamesI  s   . ??aCxxzD  0AJJq}}/0 J e#488:t4 :AJJtAw224QR89: J e#488:u5 :AJJtAw224QR89:
 J  488:u5 :AJJtAw224QR89:J__!##%D((**twwA"a')*_``QAIIKA!$R4??a+?%@!AA!E"Q'9':%;;<<;<<r   c                    | j                   dk(  r| j                  d      }|j                  d      }|j                          t	        d| j
                  dz  z
        }| j
                  dz  dk7  rZ|d| j
                  dz  z
     dt        | j                  | j                         z   dz
  d      j                  d      d   }|dz  }nd	}dj                  ||d
       }||dS | j                   dk(  r| j                         }||j                         S d| j                  z  }| j
                  dz  dk7  r8d|| j
                  d
 | j                  | j                         z   dz
  fz  }|dz  }nd	}t        |      }|j                          dj                  |      }t	        d| j
                  dz  z
        dz  }|||d
 dS t        d      )a  Return the value for reverse lookup/PTR records as RFC 2317 look alike.

        RFC 2317 is an ugly hack which only works for sub-/24 e.g. not
        for /23. Do not use it. Better set up a zone for every
        address. See reverseName for a way to achieve that.

        >>> print(IP('195.185.1.1').reverseName())
        1.1.185.195.in-addr.arpa.
        >>> print(IP('195.185.1.0/28').reverseName())
        0-15.1.185.195.in-addr.arpa.
        >>> IP('::1:2').reverseName()
        '2.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.'
        >>> IP('ff02::/64').reverseName()
        '0.0.0.0.0.0.0.0.0.0.0.0.2.0.f.f.ip6.arpa.'
        rs   r   r}   r   r   rz   rq   rr   r   Nz.in-addr.arpa.rt   %032xz%s-%xrv   r{   z
.ip6.arpa.ry   )r   r   r   r.  r   r   r   r   r   r   r'  r*  r-  r   )r   r/  first_byte_index
nibblepartr   r0  s         r   r*  zIP.reverseName  s   " ??a  #AAIIK"11(<#=>"a'()!T__-A*B(CWTWWW[W_W_WaMadeMeghEiEoEopsEtuwExy
c!

+,-.A+5q99__!##%D''))$''!A"a'$$//*:(;TWWtxxz=QTU=U'VV
c!

QAIIKA!$R4??a+?%@!AA!E'115G5H3IJJ;<<r   c                 \    dt        |      v rt        d|z        t        | d|d      S )zTransform a single IP address into a network specification by
        applying the given netmask.

        Returns a new IP instance.

        >>> print(IP('127.0.0.1').make_net('255.0.0.0'))
        127.0.0.0/8
        r|   zinvalid netmask (%s)T)r   )strr   r   )r   r   s     r   r   zIP.make_net  s3     #g,3g=>>T7+d;;r   c           	      0   t        |t              rWt        |j                  t	        |              D cg c]-  }t        t        j                  | |      | j                        / c}S t        t        j                  | |      | j                        S c c}w )aA  Called to implement evaluation of self[key].

        >>> ip=IP('127.0.0.0/30')
        >>> for x in ip:
        ...  print(str(x))
        ...
        127.0.0.0
        127.0.0.1
        127.0.0.2
        127.0.0.3
        >>> print(str(ip[2]))
        127.0.0.2
        >>> print(str(ip[-1]))
        127.0.0.3
        r   )	r   r   r   r   r   r   ro   r  r   r  s      r   r  zIP.__getitem__  st      c5!W]_b_j_jknoskt_uWvwRSBu((q1T__Mww%##D#.$//JJ xs   2Bc                 *    d| j                  d      z  S )zePrint a representation of the Object.

        >>> IP('10.0.0.0/8')
        IP('10.0.0.0/8')
        zIP('%s')rq   r  r   s    r   r  zIP.__repr__  s     T//234r   c                    | j                   dk7  ry| j                  dz  dk7  ryd| j                  dz	  dz  dz  | j                  d	z	  dz  | j                  d
z	  dz  | j                  dz	  dz  | j                  dz	  dz  | j                  dz  fz  S )z
        Get the 802.3 MAC address from IPv6 RFC 2464 address, in lower case.
        Return None if the address is an IPv4 or not a IPv6 RFC 2464 address.

        >>> IP('fe80::f66d:04ff:fe47:2fae').get_mac()
        'f4:6d:04:47:2f:ae'
        rt   Nl      ~ l      | z%02x:%02x:%02x:%02x:%02x:%02x8         0   (   r   r   )r   r   r   s    r   get_macz
IP.get_mac  s     ??aGG'',==.ww"}$,WW]d"WW]d"WW]d"WW\T!GGdN2
 
 	
r   c                 b   | j                   dk(  r8t        t        t        | j                  z         d| j
                  dz   z  z         S | j                  t        z  t        k(  r8t        t        | j                  t        z
        d| j
                  dz
  z  z         S t        dt        |       z        )a  
        Returns the IPv6 mapped address of an IPv4 address, or the corresponding
        IPv4 address if the IPv6 address is in the appropriate range.
        Raises a ValueError if the IPv6 address is not translatable. See RFC 4291.

        >>> IP('192.168.1.1').v46map()
        IP('::ffff:192.168.1.1')
        >>> IP('::ffff:192.168.1.1').v46map()
        IP('192.168.1.1')
        rs   r   `   z*%s cannot be converted to an IPv4 address.)	r   r   r6  IPV6_MAP_MASKr   r   IPV6_TEST_MAPr   r   r   s    r   v46mapz	IP.v46map  s     ??ac-$''124??R#789 : : ww&-7#dgg564??R#789 : :E:& ' 	'r   N)r  r  r   r!  r   r   r   r'  r+  r*  r   r  r  r?  rD  r   r   r   r   r      s@    7>)B%4=l/=b<K(5
*'r   r   c                   ^    e Zd Zg fdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zy)IPSetc                     t        |t        j                        s!t        dt	        |      j
                  z        |D ]  }t        |t              rt        d       |d d  | _        | j                          y )Nz'%s' object is not iterable(Only IP objects can be added to an IPSet)
r   collections_abcIterabler   r   r  r   r   prefixesoptimize)r   iterableprefixs      r   r   zIPSet.__init__  sl    (O$<$<=9DN<S<SSTT  	MFfb) !KLL	M
 !r   c                 B   | j                   j                         }t        |t              r!|j                  }|D cg c]
  }||k  s	| }}t        |      D ]A  }t        j                  | j                   |   |      }|s)|| j                   |   |dz
     v sA y y c c}w )Nrq   T)prefixtablekeysr   r   r   sortedbisect)r   r   valid_masksip_maskr   maskr   s          r   r  zIPSet.__contains__  s    &&++-b"mmG&1BQ'\1BKB;' 	Dd..t4b9A R4++D1!a%88	 Cs   
BBc              #   6   K   | j                   D ]  }|  y wr   )rK  )r   rN  s     r   __iter__zIPSet.__iter__   s     mm 	FL	s   c                 "    | j                         S r   r   r   s    r   r   zIPSet.__len__$  s    xxzr   c                 F    t        | j                  |j                  z         S r   )rF  rK  r   s     r   r   zIPSet.__add__'  s    T]]U^^344r   c                 `    t        | j                        }|D ]  }|j                  |        |S r   )rF  rK  discard)r   r   newrN  s       r   r   zIPSet.__sub__*  s0    DMM" 	 FKK	 
r   c                 |   t        | j                        }t        |j                        }g }	 t        |      }t        |      }	 ||v r|j                  |       t        |      }"||v r|j                  |       t        |      }C||k  rt        |      }nt        |      }_# t        $ r t        |      cY S w xY wr   )iterrK  nextr   StopIterationrF  )r   r   leftrightresultlrs          r   __and__zIPSet.__and__0  s    DMM"U^^$	!T
AUA 6MM!$T
A!VMM!$UAq5T
AUA   	!= 	!s   A6B$ $B;:B;c                     d| j                   j                  z  dj                  t        t        | j
                              z   dz   S )Nz%s([z, z]))	__class__r  r   mapr   rK  r   s    r   r  zIPSet.__repr__I  s6    ///$))Cdmm<T2UUX\\\r   c                 :    t        d | j                  D              S )Nc              3   <   K   | ]  }|j                           y wr   r   ).0rN  s     r   	<genexpr>zIPSet.len.<locals>.<genexpr>M  s     <F6::<<s   )sumrK  r   s    r   r   z	IPSet.lenL  s    <dmm<<<r   c                     t        |t        j                        s|g}|D ]  }t        |t              rt	        d       | j
                  j                  |       | j                          y )NrH  )r   rI  rJ  r   r   rK  extendrL  )r   valuerN  s      r   addz	IPSet.addO  s_    %!9!9:GE  	MFfb) !KLL	M
 	U#r   c                 V   t        |t        j                        s|g}t        |t              r|j                  }|D ]  }t        |t
              st        d      d}d}t        t        | j                              D ]<  }| j                  ||z
     |v s| j                  j                  ||z
         |dz   }d}> |rd}t        t        | j                              D ]7  }|| j                  |   v s| j                  |   |z
  | j                  ||dz       | j                          y )Nz,Only IP objects can be removed from an IPSetFr   rq   T)r   rI  rJ  rF  rK  r   r   ranger   poprL  )r   rr  
del_prefixfounddr   s         r   r\  zIPSet.discard]  s&   %!9!9:GE eU#NNE   	Jj"- !OPP EA3t}}-. !==Q':5MM%%a!e,AA E	!   E3t}}-. q!11+/==+;j+HDMM!AaC()	2 	r   c                     t        | j                        }t        |j                        }	 t        |      }t        |      }	 ||v s||v ry||k  rt        |      }nt        |      }&# t        $ r Y yw xY w)NTF)r_  rK  r`  ra  )r   r   rb  rc  re  rf  s         r   
isdisjointzIPSet.isdisjoint  sz    DMM"U^^$	T
AUA6Q!V q5T
AUA   		s   A) A) )	A54A5c                 f   | j                   j                          t        | j                         }d}||k  rh|dz   }||k  rV| j                   |   | j                   |   v r8d | j                   |<   |dz  }||k  r| j                   |   | j                   |   v r8|}||k  rhd}|r| j                   D cg c]  }||	 c}| _         d}t        | j                         }d}||dz
  k  rI|dz   }	 | j                   |xx   | j                   |   z  cc<   d | j                   |<   |dz   }d}||dz
  k  rI|ri | _        | j                   D ]+  }	 | j                  |j
                     j                  |       - y c c}w # t        $ r |}Y `w xY w# t        $ r |g| j                  |j
                  <   Y jw xY w)Nr   rq   TF)rK  sortr   r   rP  r   r   KeyError)r   addrlenr   j	run_againaaddresss          r   rL  zIPSet.optimize  s    dmm$'k !Ag+$--"2dmmA6F"F#'a Q g+$--"2dmmA6F"F A 'k 	 )-G1QGDM I $--(GAgai-E	 MM!$a(88$'+DMM!$AA $I gai- : }} 	AGA  !3!34;;GD	A7 H( " A  A8?y  !3!34As0   1E49E4,:E9 	(F
9FF
#F0/F0N)r  r  r   r   r  rX  r   r   r   rg  r  r   rs  r\  r{  rL  r   r   r   rF  rF    sI     " 5!2]=#J 7Ar   rF  c                    g }d}d}|t        |       k  r| |d }|j                  d      r!|t        d| z        t        |      }|dz  }E|j                  d      }|dk(  rt        d| z        |dk7  rI|j	                  |d|        |||dz    dk(  r||z  }n||d	z   z  }|t        |       k(  r t        d| z        |j	                  |       n|t        |       k  r|rOd
|d   v rH||t        |      d	z
  k  st        d| z        t        |d         d   }|dd d|dz	  z  d|dz  z  gz   }|3dt        |      z
  }|dk  rt        d| z        |d| dg|z  z   ||d z   }t        |      dk7  rt        d| z        d}d}|D ]?  }	 t        |d      }d|cxk  xr dk  nc  }	|	rt        | d|      |dz  |z   }|d	z  }A |S # t        $ r d}	Y 0w xY w)at  
    Internal function used by parseAddress() to parse IPv6 address with ':'.

    >>> print(_parseAddressIPv6('::'))
    0
    >>> print(_parseAddressIPv6('::1'))
    1
    >>> print(_parseAddressIPv6('0:0:0:0:0:0:0:1'))
    1
    >>> print(_parseAddressIPv6('0:0:0::0:0:1'))
    1
    >>> print(_parseAddressIPv6('0:0:0:0:0:0:0:0'))
    0
    >>> print(_parseAddressIPv6('0:0:0::0:0:0'))
    0

    >>> print(_parseAddressIPv6('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210'))
    338770000845734292534325025077361652240
    >>> print(_parseAddressIPv6('1080:0000:0000:0000:0008:0800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('1080:0:0:0:8:800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('1080:0::8:800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('1080::8:800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('FF01:0:0:0:0:0:0:43'))
    338958331222012082418099330867817087043
    >>> print(_parseAddressIPv6('FF01:0:0::0:0:43'))
    338958331222012082418099330867817087043
    >>> print(_parseAddressIPv6('FF01::43'))
    338958331222012082418099330867817087043
    >>> print(_parseAddressIPv6('0:0:0:0:0:0:13.1.68.3'))
    218186755
    >>> print(_parseAddressIPv6('::13.1.68.3'))
    218186755
    >>> print(_parseAddressIPv6('0:0:0:0:0:FFFF:129.144.52.38'))
    281472855454758
    >>> print(_parseAddressIPv6('::FFFF:129.144.52.38'))
    281472855454758
    >>> print(_parseAddressIPv6('1080:0:0:0:8:800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('1080::8:800:200C:417A'))
    21932261930451111902915077091070067066
    >>> print(_parseAddressIPv6('::1:2:3:4:5:6'))
    1208962713947218704138246
    >>> print(_parseAddressIPv6('1:2:3:4:5:6::'))
    5192455318486707404433266432802816
    r   Nz::z,%r: Invalid IPv6 address: more than one '::'r{   r   z%r: Invalid IPv6 addressrr   rq   r}   z)%r: Invalid IPv6 address: '::' after IPv4z%04xr   r   r   z,%r: Invalid IPv6 address: '::' is not neededr   z/%r: Invalid IPv6 address: should have 8 hextetsTz': Invalid IPv6 address: invalid hexlet )r   
startswithr   r   r   r   r   )
ipstritemsr   fill_posr   posrr  diffr  errors
             r   _parseAddressIPv6r    si   l EEH
#e*
UV}??4 # !ORW!WXX5zHQJEiin!87%?@@"9LLds$CA$&QE
" !;e!CDDLL3 #e*
6 b	! 8s5z!|+CH5PQQU2Y'*cr
f4f6OPP 3u:~19KeSTTix C5:-hi0@@ 5zQJURSS EE 		tR=DT+V+,E eUYZ[["$
	 L  	E	s   GGGc                 j   	 t        | d      }	 t        | d      }| j                  d      r0|.|t        kD  rt        dt        |fz        |t        k  r|dfS |dfS | j                  d      d	k7  rt        |       dfS t        |       d
k(  r||dfS | j                  d      d	k7  s||dk  r|dk7  r| j                  d      }t        |      dkD  rt        d      |dgdt        |      z
  z  z  }|D cg c]  }t        |       }}|D ]  }|dkD  s|dk  st        d| z         |d   dz  |d   dz  z   |d   dz  z   |d   z   dfS |3|t        kD  rt        dt        |fz        |t        k  r	|dk7  r|dfS |dfS t        d| z        # t        $ r d}Y w xY w# t        $ r d}Y w xY wc c}w )aT  
    Parse a string and return the corresponding IP address (as integer)
    and a guess of the IP version.

    Following address formats are recognized:

    >>> def testParseAddress(address):
    ...     ip, version = parseAddress(address)
    ...     print(("%s (IPv%s)" % (ip, version)))
    ...
    >>> testParseAddress('0x0123456789abcdef')           # IPv4 if <= 0xffffffff else IPv6
    81985529216486895 (IPv6)
    >>> testParseAddress('123.123.123.123')              # IPv4
    2071690107 (IPv4)
    >>> testParseAddress('123.123')                      # 0-padded IPv4
    2071658496 (IPv4)
    >>> testParseAddress('127')
    2130706432 (IPv4)
    >>> testParseAddress('255')
    4278190080 (IPv4)
    >>> testParseAddress('256')
    256 (IPv4)
    >>> testParseAddress('108000000000000000080800200C417A')
    21932261930451111902915077091070067066 (IPv6)
    >>> testParseAddress('0x108000000000000000080800200C417A')
    21932261930451111902915077091070067066 (IPv6)
    >>> testParseAddress('1080:0000:0000:0000:0008:0800:200C:417A')
    21932261930451111902915077091070067066 (IPv6)
    >>> testParseAddress('1080:0:0:0:8:800:200C:417A')
    21932261930451111902915077091070067066 (IPv6)
    >>> testParseAddress('1080:0::8:800:200C:417A')
    21932261930451111902915077091070067066 (IPv6)
    >>> testParseAddress('::1')
    1 (IPv6)
    >>> testParseAddress('::')
    0 (IPv6)
    >>> testParseAddress('0:0:0:0:0:FFFF:129.144.52.38')
    281472855454758 (IPv6)
    >>> testParseAddress('::13.1.68.3')
    218186755 (IPv6)
    >>> testParseAddress('::FFFF:129.144.52.38')
    281472855454758 (IPv6)
    r   N
   0xz&IP Address can't be larger than %x: %xrs   rt   r   rr   rv   r}   r)  z#IPv4 Address with more than 4 bytesr   r;  r   z'%r: single byte must be 0 <= byte < 256   rq   r{   r   r   z!IP Address format was invalid: %s)	r   r   r  r   r   r   r  r   r   )r  r   hexvalintvalbytesr   s         r   r   r   C  s   ZUBUB &"4$$EIY[aHbbcc%%A;A;zz#"!%(!,,	Ur	f0{	CB	6#5&3,9XY>C u:>BCC#!c%j.))!&'AQ'' 	VA3w!a% !Je!TUU	V qRE!HN3uQx1}EaPRSTT		 $$EIY[aHbbcc%%)q.A;A;
85@
AA[    0 (s(   F F 4F0FFF-,F-c                    t        |       } | dk  rt        d| z        d}|dk(  rM| t        kD  rt        dt        | fz        t        d      D ]  }t	        | dz        dz   |z   }| dz	  }  |d	d
 }|S |dk(  rQ| t
        kD  rt        dt
        | fz        d| z  }t        dd      D ]  }||    |z   }|dz  dk(  sd|z   } |dd	 }|S t        d      )z/Transform an integer string into an IP address.r   zIPs can't be negative: %dr   rs   ru   r;  r}   r   Nrr   rt   rw   r2  rq   !   r   ry   )r   r   r   r   r6  r   )r   r   r   re  r   s        r   r   r     s&    
RB	Av4;<<
C!|  GK[]_J``aa 	Ab4i.3&,CqB	 #2h J 
A  GK[]_J``aabL2 	 AQB%#+C1uzCi	  !"g J 788r   c                 0    | dk(  ry| dk(  ryt        d      )a  Return number of bits in address for a certain IP version.

    >>> _ipVersionToLen(4)
    32
    >>> _ipVersionToLen(6)
    128
    >>> _ipVersionToLen(5)
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "IPy.py", line 1076, in _ipVersionToLen
        raise ValueError("only IPv4 and IPv6 supported")
    ValueError: only IPv4 and IPv6 supported
    rs   rv   rt   rx   ry   )r   )r   s    r   r   r     s$     !|	A788r   c                 T    t        |       dk(  ry| d   dk7  rydt        | dd       z   S )zDReturn number of elements containing 0 at the beginning of the list.r   rq   N)r   r   )re  s    r   r   r     s5    
1v{	
1'!"...r   r   0000r   200103401005010160110701118100091001r  1010b1011c1100ry  1101ef1111c                     | dk  rt        d      d| z  }d}|D ]  }|t        |   z  } |d   dk(  r*t        |      dkD  r|dd }|d   dk(  rt        |      dkD  r|S )z9Return the binary representation of an integer as string.r   zOnly positive values allowedr   r   r   rq   N)r   	_BitTabler   )valr/  r   r   s       r   r   r     s     Qw788s
A
C y| a&C-CHqL!"g a&C-CHqLJr   c                 4    d}| dkD  r| dz	  } |dz  }| dkD  r|S )z,Find the highest bit set to 1 in an integer.r   rq   r   numr   s     r   r   r     s0    
C
'Qhq ' Jr   c                     t        |       } | dk  rt        d| z        d}| dkD  r| dz  dk(  r	 |S | dz	  } |dz  }| dkD  r|S )z,Find the highest bit set to 0 in an integer.r   z Only positive Numbers please: %srq   r   r   r  s     r   _count0Bitsr    sj     c(C
Qw;sCDD
C
'7a< J Qhq	 '
 Jr   c                 n    t        |      }|dk  s||kD  ry| dk(  r|dz   }nt        |       }|||z
  k  ryy)aJ  Check the validity of a prefix

    Checks if the variant part of a prefix only has 0s, and the length is
    correct.

    >>> _checkPrefix(0x7f000000, 24, 4)
    1
    >>> _checkPrefix(0x7f000001, 24, 4)
    0
    >>> repr(_checkPrefix(0x7f000001, -1, 4))
    'None'
    >>> repr(_checkPrefix(0x7f000001, 33, 4))
    'None'
    r   Nrq   )r   r  )r   r   r   r   zbitss        r   _checkPrefixr    sK    " 7#D1}	D(	QwqBy  r   c                     t        |       }|}|dz  dk(  r#|dk7  r|dz	  }|dz  }|dk(  rn|dz  dk(  r|dk7  r|dkD  r'|dz  dk(  rt        d| z        |dz	  }|dz  }|dkD  r&yy)z2Checks if a netmask is expressable as a prefixlen.rq   r   z-Netmask 0x%x can't be expressed as an prefix.Nr  )r   masklenr  r   s       r   _checkNetmaskr  -  s     g,CD 7q.TQYQh	19	 7q.TQY (!G>LwVWWQh		 (r   c                 F    	 | t        ||      z  | k(  S # t        $ r Y yw xY w)zBCheck if a base addess of a network is compatible with a prefixlenF)r   r   )r   r   r   s      r   r   r   A  s1    ))W==DE s    	  c                 P    t        |       }t        |       }t        | |       ||z
  S )znConvert an Integer representing a netmask to a prefixlen.

    E.g. 0xffffff00 (255.255.255.0) returns 24
    )r  r   r  )r   netlenr  s      r   r   r   I  s-     !F'"G'7#Vr   c                 b    | dk(  ry| dk  rt        d      d| dz
  z  dz
  t        |      | z
  z  S )zReturn a mask of n bits as a long integer.

    From 'IP address conversion functions with the builtin socket module'
    by Alex Martelli
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66517
    r   zPrefixlen must be > 0r{   rq   )r   r   )r   r   s     r   r   r   U  sC     A~	Q011	!^QOG$<y$HIIr   c           	         | |v r
t               S || vrt        t        |       g      S t        d| d   | j                  dz   fz        t        d| t        | j	                         dz           | j                  dz   fz        g}||d   v rt        |d   |      t        |d   g      z   S t        |d   g      t        |d   |      z   S )Nz%s/%dr   rq   r{   )rF  r   r   r   r   r   )rN  	subprefixrK  s      r   r   r   c  s    wbj\"" 	7fQi!2!2Q!6778
7fS!123V5F5F5JKKLH HQK !i85(1+;OOOhqk]#&7Y&OOOr   __main__rq   )r   )3r!  __version__rS  typescollections.abcabcrI  ImportErrorcollectionsr   r   r   r   rC  rB  r   longr   r6  unicoder   r   	NameErrorru  objectro   r   
MutableSetrF  r  r   r   r   r   r  r   r   r  r  r  r   r   r   r   r  doctesttestmodfailurenbtestsysexitr   r   r   <module>r     sC     *- !!!+" !!!"
"QjQjQ mQ j	Q
 iQ 2lQ lQ jQ jQ jQ jQ jQ 
6FQ 6FQ 'hQ  2f!Q" #h#Q$ 6G%Q& 6F'Q( 6J)Q* 6J+Q, 6J-Q. 6G/Q0 'o1Q2 6G3Q4 6H5Q6 6J7Q8 6J9Q: 6F;Q< 6J=Q> 6J?Q@ 6JAQB 6JCQD 6JEQF jGQH 6JIQJ 6IKQL 6GMQN 6JOQP 6FQQR 6JSQT 6JUQV 6JWQX 6GYQZ 6G[Q\ 6G]Q^ f_Q` 6JaQb 6GcQd 6FeQf 6FgQh 6FiQj 6HkQl 6JmQn 6IoQp jqQr jsQt juQv 
jwQx 
jyQz 
j{Q| 
j}Q~ 
jQ@ jAQB jCQD jEQF eGQH jIQJ 7B6@6A6L6L6M6L6K6H6J6N6MaQ
f  5 55dIgI
U
F U
pb' b'HEAO&& EANvp\B~>9./@S& @#v @sF @C @@f@&)6@36@@f@&)6@36@ @ f@ '*6@ 47@	
 @(	JP( z%goo'OGV  Q3  *)*f  IIFs#   G 
G' 	G$#G$'G76G7